《 利用 Python36,基于 Scrapy 框架的爬虫思路 》

(一)引言 利用爬虫抓取网页数据已经是常见技能,八爪鱼等工具也比较方便,但导出数据需要付费。从长远来看,静下心来学习爬虫也未尝不可。不过还是有一定难度,需要有一些编程的基础,坑多,一般人就别整了。我做的第一个爬虫作品,欢迎有需要的朋友参考。(二)目标网址(这是一个JS渲染的网页,网页直接无法解析,风格:网址不变下实现表格的翻页 ):

chinabond.com.cn/jsp/in

(三)工具:Scrapy + Selenium + Phantomjs,平台:Python36。 Python36 -> Pycharm -> CMD -> Scrapy -> Selenium -> Phantomjs -> chrome + xpath helper -> MySQL ->Navicat Premium -> ODBC配置 -> Stata等应用层 (四)编程思路:1. Scrapy 下新建项目文件和主爬虫文件解析网页;2. 通过 Chrome + Xpath helper 插件,对网页进行初步分析,确定需要抓取的变数栏位,获取 xpath 地址;3. 编写 Items.py,这部分主要是定义要抓取和写入的栏位:class MyspiderItem(scrapy.Item):# 以下定义要爬虫的栏位名

id = scrapy.Field() # 序号

name = scrapy.Field() # 简称code = scrapy.Field() # 代码issuer = scrapy.Field() # 发行人date = scrapy.Field() # 日期amount = scrapy.Field() # 发行量payway = scrapy.Field() # 付息方式rate = scrapy.Field() # 利率deadline = scrapy.Field() # 期限startdate = scrapy.Field() # 起息日

enddate = scrapy.Field() # 到期日

# 以下定义要写入 MySQL 资料库的栏位,注意变数名要与 MySQL 数据表中的栏位一致。def get_insert_sql(self):insert_sql="""insert into chinabond(id,name,code,issuer,date,

amount,

payway,rate,deadline,startdate,enddate)VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)"""params=(self["id"],

self["name"],

self["code"],self["issuer"],self["date"],self["amount"],self["payway"],self["rate"],self["deadline"],self["startdate"],self["enddate"],

)

return insert_sql,params4. 编写通道文件: piplines.py,这部分主要完成将数据写入 MySQL 等资料库:from twisted.enterprise import adbapiimport pymysqlimport pymysql.cursorsclass MyspiderPipeline(object):def __init__(self,dbpool):self.dbpool = dbpool@classmethod

def from_settings(cls,settings):

dbpool = adbapi.ConnectionPool("pymysql",host="localhost",db="mysql",user="root",password="123",charset="utf8mb4",cursorclass=pymysql.cursors.DictCursor,use_unicode = True

)

return cls(dbpool)def process_item(self,item,spider):self.dbpool.runInteraction(self.do_insert,item)def do_insert(self,cursor,item):insert_sql,params=item.get_insert_sql()cursor.execute(insert_sql,params)5. 在 setting.py 开启通道文件,配置网页请求的头信息等:(1)考虑以网站可能存在防爬机制,为避免伺服器识别为机器访问,需要伪装成人工浏览器访问,启用头信息:DEFAULT_REQUEST_HEADERS = {

host: www.chinabond.com.cn,

accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,accept-language: zh-CN,zh;q=0.9,user-agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.75 Safari/537.36,}(2)启用 piplines.py 通道文件:# Configure item pipelines# See scrapy.readthedocs.org/ITEM_PIPELINES = {myspider.pipelines.MyspiderPipeline: 300,}6. 编写主爬虫文件: D:scrapymyspidermysipderspiderschinabond.py,需要在其中完成对网页的解析和元素的提取。 # -*- coding: utf-8 -*-import scrapyfrom myspider.items import MyspiderItemfrom selenium import webdriverfrom selenium.webdriver.support.ui import WebDriverWaitclass ChinabondSpider(scrapy.Spider):name = chinabondallowed_domains = [chinabond.com.cn]start_urls = ["chinabond.com.cn/jsp/in"]def parse(self, response):driver = webdriver.PhantomJS(executable_path=C:\Python36\phantomjs-2.1.1-windows\bin\phantomjs.exe)url = "chinabond.com.cn/jsp/in"driver.get(url)page_n = len(driver.find_elements_by_xpath(//*[@id="sel"]/option)) # 计算总页数,数值型;for j in range(1,3): # 在页数范围内爬虫!这里测试为 3,全爬应为:range(1,page_n+1)page_i = int(driver.find_element_by_xpath(//*[@id="nowpage"]).text) # 获得当前页的页码,数值型;print("当前是第:" + str(page_i) + "页,共计:" + str(page_n) + "页")for i in range(2, 22): # 爬取当前页面数据,2—22 表示页面数据是从2-22行,不含表头,一般 tr 代表行,td代表列。item = MyspiderItem()item[id] = driver.find_element_by_xpath("//*[@id=bodyTable]/tbody/tr[" + str(i) + "]/td[1]").textitem[name] = driver.find_element_by_xpath("//*[@id=bodyTable]/tbody/tr[" + str(i) + "]/td[2]").textitem[code] = driver.find_element_by_xpath("//*[@id=bodyTable]/tbody/tr[" + str(i) + "]/td[3]").textitem[issuer] = driver.find_element_by_xpath("//*[@id=bodyTable]/tbody/tr[" + str(i) + "]/td[4]").textitem[date] = driver.find_element_by_xpath("//*[@id=bodyTable]/tbody/tr[" + str(i) + "]/td[5]").textitem["amount"] = driver.find_element_by_xpath("//*[@id=bodyTable]/tbody/tr[" + str(i) + "]/td[6]").textitem["payway"] = driver.find_element_by_xpath("//*[@id=bodyTable]/tbody/tr[" + str(i) + "]/td[7]").textitem["rate"] = driver.find_element_by_xpath("//*[@id=bodyTable]/tbody/tr[" + str(i) + "]/td[9]").textitem["deadline"] = driver.find_element_by_xpath("//*[@id=bodyTable]/tbody/tr[" + str(i) + "]/td[10]").textitem["startdate"] = driver.find_element_by_xpath("//*[@id=bodyTable]/tbody/tr[" + str(i) + "]/td[11]").textitem["enddate"] = driver.find_element_by_xpath("//*[@id=bodyTable]/tbody/tr[" + str(i) + "]/td[12]").textyield item # 发送当前页数据driver.find_element_by_xpath(//*[@id="xiayiye"]/a/img).click() # 点击下一页;def load_ok(driver): # 判断下一页是否已经完成载入if int(driver.find_element_by_xpath(//*[@id="nowpage"]).text) != page_i:return 1else:return 0WebDriverWait(driver,20).until(load_ok) # 等待载入完成。# yield scrapy.Request(url, callback=self.parse) # 注意,在本例中,翻页后网址不变,网页是JS渲染得到的,因此直接不可解析。因此,也是使用 selenium + Phantomjs 的理由。该句如果网址有变化才考虑回传网页请求,本例是直接两重循还得到。但循环时要先等待网页载入完成才可进行,必须要有这个判断函数。(五)运行之,大功告成,哈哈!1. 爬虫过程图(164页,3270条记录): 2. 数据注入到 MySQL 的截图:3. Stata 走 ODBC 通道将数据导入结果(附录A) 安装 Scrapy:# python 下载包:lfd.uci.edu/~gohlke/pyt blog.csdn.net/HHTNAN/ar# pip3 安装 Scray 爬虫框架的方法:# ------------------------------------# 1.运行CMD,切换到Python目录,安装pip:python -m pip install --upgrade pip --force-reinstall# 说明:安装后的pip3存在于Scripts目录下,可在CMD中切换到 PythonScripts下,运行 pip3 -V 查看版本。# 2.在CMD中,进入Scripts目录下,运行pip3来安装 Scrapy 框架:pip3 install scrapy# 说明:可能遇到的错误:# ?Microsoft Visual C++ 14.0 is required 这一步报错了,缺少VC组件!# 解决方案1:(不推荐)提示:landinghub.visualstudio.com,到页面上下载!建议翻墙后安装,否则会报错!# # 解决方案2:(推荐):lfd.uci.edu/~gohlke/pyt下载twisted对应版本的whl文件Twisted?17.5.0?cp36?cp36m?win_amd64.whl),# 文件名中,cp后面是python版本,amd64代表64位,运行pip3 install C:python36Twisted-17.5.0-cp36-cp36m-win_amd64.whl。# 安装完成后,再次运行:pip3 install Scrapy1### 3.安装 Win32Py,地址:百度sourceforge.net/project# 检查是否成功:import win32com,不报错为OK!## 4.在CMD中添加路径:path C:Python36;%path%# path C:Python36Scripts;%path%## 5.chrome XPath Helper:Ctrl + Shift + X 激活 XPath Helper 的控制台,然后您可以在 Query 文本框中# 输入相应 XPath 进行调试了,提取的结果将被显示在旁边的 Result 文本框.# 5.使用firefox浏览器,安装Xpath插件:搜索框中输入:WebDriver Element Locator,点击Add to firefox## 6.在python中安装MySQLdb,在CMD中切换到 PythonScripts下:pip3 install mysql-python (不支持Python3.6)# 6.在python中安装pymysql,在CMD中切换到 PythonScripts下:pip3 install pymysql(可支持Python3.6)# 6.下载 pymssql, pip3 install C:python36pymssql-2.1.3-cp36-cp36m-win_amd64.whl# 在Windows下安装PIP+Phantomjs+Selenium 如果说在使用Python爬取相对正规的网页使用"urllib2 + BeautifulSoup + 正则表达式"就能搞定的话; 那么动态生成的信息页面,如Ajax、JavaScript等就需要通过"Phantomjs + CasperJS + Selenium"来实现了。 pip3 install selenium pip3 install -U selenium Phantomjs: phantomjs.org/ 官网下载解压到 python36scripts 下。 blog.csdn.net/five3/art * 注:解决:「ImportError: cannot import name webdriver」 问题的方法是:不要将自己编写的程序起名为:selenium.py,因为环境路径很可能优先搜索到这个文件,导致python36无法找到其中的模块。 from selenium import webdriver driver = webdriver.PhantomJS(executable_path=C:\Python36\phantomjs-2.1.1-windows\bin\phantomjs.exe) # 注意:路径中必须使用双斜杠才能被识别! driver.get("baidu.com") data = driver.title print(data) * 添加路径的方法:import os,sys sys.path.append("C:\Python36\phantomjs-2.1.1-windows\bin") * 添加路径的方法:import os,sys sys.path.append("C:\Python36\phantomjs-2.1.1-windows\bin") (附录B)Scrapy 框架的使用: 1.环境:进入CMD,添加环境路径:addpath.cmd,内容如下: path C:Python36;%path% path C:Python36Scripts;%path% 2.建立工程项目(D:scrapymyspider,.myspider,.spiders): scrapy startproject myspider3.建立爬虫文件(D:scrapyTencentTencentspiderschinabond.py): scrapy genspider chinabond "chinabond.com.cn" 4.进入 pycharm 中编辑;5.随时在 CMD 中试运行。 cd D: cd D:scrapyTencentTencentspiders scrapy crawl chinabond (附录C)MySQL 资料库配置:* mysql-5.7.18-winx64.绿色版 ,解压到:D:MySQL,此时 MySQL 的程序工作目录在:D:MySQLin 同时将:my-default.ini(已设定好配置)copy到 MySQL目录下(D:MySQL),改名:D: MySQL my.ini============================================================================================来源:blog.csdn.net/mhmyqn/ar---------------------------------------------------------------(1)先配置环境变数,把mysql所在目录的bin目录添加到path环境变数中,具体请百度。 说明:这一步也可以不要,如果你已经进入了:bin 目录下。 <1> 右键单击我的电脑->属性->高级系统设置(高级)->环境变数 点击系统变数下的新建按钮 输入变数名:MYSQL_HOME 输入变数值:D:mysql <2> 选择系统变数中的Path 点击编辑按钮 在变数值中添加变数值:%MYSQL_HOME%in 注意是在原有变数值后面加上这个变数,用;隔开,不能删除原来的变数值,(2)CMD 窗口重新以管理员身份运行;(3)CMD中,在 bin 目录下,安装 mysql 服务:mysqld --install 显示:Service successfully installed. (4)启动 mysql 服务: <1> 先在:INI中设置正确的路径(假设目录是:D:MySQL;D:MySQLin): 找到:D:MySQLmy-default.ini,或者自己建立一个my.ini文件,修改或增加如下内容: [mysqld] basedir=D:MySQL datadir=D:MySQLdata 说明:网上有的说配置中的目录分隔符必须是正斜杠『/』 但是经过实验,『/』、『』、『\』都没有问题,都是可以的。 <2> 到 bin 目录下启动服务:net start mysql,如果报错,可考虑先停止、删除原服务,再安装并启动。 mysqld --remove,如果原服务还在:net stop mysql mysqld --install 可能需要初始化一下 data 文件夹(可能需要将原行的删掉):mysqld --initialize-insecure --user=mysql net start mysql 显示:MySQL 服务正在启动 . MySQL 服务已经启动成功。(5)连接 mysql 服务:mysql -uroot,进入 MySQL 命令行:mysql>(6)退出:exit (7) CMD 下设置 mysql 新密码:mysqladmin -u root password 123(8)验证一下用密码登录:mysql -uroot -p(9)进入 mysql 后,连接到资料库(现在已是 mysql 命令行):mysql> use mysql update user set password=password(123) where user=root; 注意,分号结尾。 flush privileges (附录D)将 MySQL 服务连接到 ODBC 数据通道: ------------------------------------------------------------------------------------* 以下:将 MySQL 配置到 win10 的 ODBC(64位数据源),以方便各软体走 ODBC 通道访问。------------------------------------------------------------------------------------* (一)首先请开启 MySQL 服务(具体资料见附录A).*(二)为 MySQL 资料库安装并配置 ODBC 驱动* (必须安装MySQL的ODBC驱动,不能用 Win10 自带的 SQL server)。* 1. 下载地址:dev.mysql.com/downloads,安装64位驱动。* 2. 参考资料:jingyan.baidu.com/artic* 3. Win10 中:控制面板/管理工具/ODBC(64位数据源),打开后添加:* MySQL ODBC 5.3 Unicode driver 即可。* 填入信息:选 TCP/IP server, 埠号:3306* Data soure name:mysql(随便填);用户名:root;密码:123* Database 选MySQL项(必选), 伺服器:localhost 或 127.0.0.1; * 可以点 Test 按钮测试一下, 完事点OK就连上了MySQL伺服器.* (三) 例:在 Stata 可操作如下命令:* 1.查看 MySQL 中的资料库odbc list // 注:之后的操作均可以通过滑鼠进行;* 2.查看 mysql 资料库中的所有表:odbc query "mysql", dialog(complete)* 3. 查看 chinabond 表中的栏位名:odbc desc "chinabond"* 4. 导入 chinabond 数据表的数据到 stata 内存:* odbc load [extvarlist] [if] [in] , {table("TableName")|exec("SqlStmt")}* [load_options connect_options]* 如果导入错误,可以换种方式:通过菜单导入,勾选 「Do not quote SQL table name 」* 等价于加上参数选项:noquote ,因此该参数对于成功导入是很重要的!odbc load, table("chinabond") clear noquote user(root) password(123) dsn("mysql")


推荐阅读:
相关文章