1、pyspider的架构
pyspider 的架构 主要分为 Scheduler (调度器)、 Fetcher ( 抓取器)、 Processer (处理器) 三个部分,整个爬取过程受到 Monitor (监控器)的监控,抓取的结果被 Result Worker (结果处理器)处理
- Scheduler 发起任务调度
- Fetcher 负责抓取网页内容
- Processer 负责解析网页内容,然后将新生成的 Request 发给 Scheduler 进行调度,将生成的提取结果输出保存
任务执行流程:
- 每个 pyspider 的项目对应一个 Python 脚本,该脚本中定义了 一个 Handler 类,它有 一个on_start()方法 。爬取首先调用 on_start()方法生成最初的抓取任务,然后发送给 Scheduler进行调度
- Scheduler 将抓取任务分发给 Fetcher 进行抓取, Fetcher 执行并得到响应,随后将响应发送给Processer
- Processer 处理响应并提取新的 URL 生成新的抓取任务,然后通过消息队列的方式通知Schduler 当前抓取任务执行情况,并将新生成的抓取任务发送给 Scheduler。 如果生成了新的提取结果,则将其发送到结果队列等待 Result Worker 处理
- Scheduler 接收到新的抓取任务,然后查询数据库,判断其如果是新的抓取任务或者是需要重试的任务就继续进行调度,然后将其发送回 Fetcher 进行抓取
- 不断重复以上工作,直到所有的任务都执行完毕,抓取结束
- 抓取结束后,程序会回调 on_finished ()方法,这里可以定义后处理过程
2、使用步骤
2.1创建项目
浏览器中输入:localhost:5000,点击右上角【create】按钮创建项目,填写名称和要爬取的初始url
2.2初始界面
from pyspider.libs.base_handler import *
class Handler(BaseHandler):
crawl_config = {
} # 将项目的所有爬取配置统一定义,如定义 Headers 、设置代理等,全局生效
@every(minutes=24 * 60) # 设置scheduler一天执行一次,可以添加seconds=30,表示30秒
def on_start(self): # 爬虫入口,产生初始爬取请求
self.crawl('__START_URL__', callback=self.index_page)
@config(age=10 * 24 * 60 * 60) #(单位:秒),设置请求过期时间为10天,10天内不会再次请求
def index_page(self, response): # Response对接了pyquery,实现解析爬取结果,以及生成新的爬取请求
for each in response.doc('a[href^="http"]').items():
self.crawl(each.attr.href, callback=self.detail_page)
@config(priority=2) # 优先级,数字越大越优先执行
def detail_page(self, response): # 对Response 对象做解析
return {
"url": response.url,
"title": response.doc('title').text(),
}
2.3项目编辑
run:单步调试爬虫程序
follows:代表有新的爬取请求
web:按钮:即可预览当前爬取结果的页面
html:按钮:即可查看当前页面的源代码
enable css selector helper: 通过点击页面对应元素,生成相应的css选择器
save:保存代码
3、代码编辑界面
1.命令行
参考:http://docs.pyspider.org/en/latest/Command-Line/
命令行可配制参数,完整的命令行结构如下所示 :pyspider [OPTIONS] COMMAND [ARGS]所有的命令参数(包括组件子命令)都可以通过-c由一个json文件配置,例如:
{
"taskdb": "mysql+taskdb://username:password@host:port/taskdb",
"projectdb": "mysql+projectdb://username:password@host:port/projectdb",
"resultdb": "mysql+resultdb://username:password@host:port/resultdb",
"message_queue": "amqp://username:password@host:port/%2F",
"webui": {
"username": "some_name",
"password": "some_passwd",
"need-auth": true
}
其中, OPTIONS 全局配置,对子命令有效,它可以指定如下参数 :
-c, --config FILENAME 指定配置文件名称,一般为json格式
--logging-config TEXT 日志配置文件名称 ,默认 : pyspider/pyspider/logging.conf
--debug 开启调试模式
--queue-maxsize INTEGER 队列的最大长度
--taskdb TEXT taskdb 的数据库连接字符串,默认: sqlite
--projectdb TEXT projectdb 的数据库连接字符串,默认: sqlite
--resultdb TEXT resultdb 的数据库连接字符串,默认: sqlite
--message-queue TEXT 消息队列连接字符串,默认:multiprocessing.Queue
--phantomjs-proxy TEXT PhantomJS 使用的代理, ip:port 的形式
--data-path TEXT 数据库存放的路径
--version pyspider 的版本
--help 显示帮助信息
单独配置某一组件,例如(具体选项看参考):
pyspider scheduler [OPTIONS]
pyspider bench [OPTIONS]
pyspider fetcher [OPTIONS]
pyspider processor [OPTIONS]
pyspider webui [OPTIONS]
2.crawl()方法
参考:http://docs.pyspider.org/en/latest/apis/self.crawl/
url:url 是爬取时的 URL ,可以定义为单个 URL 字符串,也可以定义成 URL 列表
callback:callback 是回调函数,指定了该 URL 对应的响应内容用哪个方法来解析
age:age是任务的有效时间.如果某个任务在有效时间内且已经被执行,则它不会重复执行,默认的有效时间为 10 天
priority:priority 是爬取任务的优先级,其值默认是 0, priority 的数值越大,对应的请求会越优先被调度
exetime:exetime 参数可以设置定时任务,其值是时间戳,默认是 0 ,即代表立即执行.例如exetime=time.time()+30*60
itag:itag 参数设置判定网页是存发生变化的节点值,在爬取时会判定次当前节点是否和上次爬取到的节点相同 。如果节点相同,则证明页面没有更新,就不会重复爬取.例如itag=i tem.find(’.update-time’).text()
auto_recrawl:当开启(True)时,爬取任务在过期后会重新执行,循环时间即定义的 age 时间长度
method:method 是 HTTP 请求方式,它默认是 GET
params:可以方便地使用 params 来定义 GET 请求参数.例如:params={‘a’:123, ‘b’: ‘c’}
data:data 是 POST 表单数据.当请求方式为POST时,我们可以通过此参数传递表单数据.例如:data={‘a’:123, ‘b’: ‘c’}
files:files 是上传的文件,需要指定文件名.例如:files ={field: {filename: ‘content’}
user_agent:user_agent 是爬取使用的 User-Agent 。
headers:headers 是爬取时使用的 Headers ,即 Request Headers
cookies:cookies 是爬取时使用的 Cookies ,为字典格式 。
connect timeout:connect timeout 是在初始化连接时的最长等待时间,它默认是 20 秒
timeout:timeout 是抓取网页时的最长等待时间,它默认是 120 秒。
allow redirects:allow redirects 确定是否自动处理重定向,它默认是 True 。
validate cert:validate cert 确定是否验证证书,此选项对 HTTPS 请求有效,默认是 True 。
proxy:proxy 是爬取时使用的代理,它支持用户名密码的配置,格式为 username:password@hostname:port
fetch_type:fetch_type 开启 PhantomJS 渲染.fetch_type = ‘js’
js_script:js_script 是页面加载完毕后执行的 JavaScript 脚本
js_run_at:JavaScript脚本运行的位置,是在页面节点开头还是结尾 , 默认是结尾, 即 document-end
js_viewport_width /js_viewport_height:是 JavaScript 渲染页面时的窗口大小
load_images:在加载 JavaScript 页面时确定是否加载图片,它默认是否
save:参数非常有用,可以在不同的方法之间传递参数.例如设置save={‘page’:1},在回调函数里可以通过 response变量的save字段接收到这些参数值response.save[‘page’]
cancel:是取消任务,如果一个任务是 ACTIVE 状态的, 则需要将 force_update设置为 True
force_ update:即使任务处于 ACTIVE 状态,那也会强制更新状态
3.任务区分
在 pyspider 判断两个任务是否是重复的是使用的是该任务对应的 URL 的 MD5 值作为任务的唯一ID ,如果ID相同,那么两个任务就会判定为相同,其中一个就不会爬取了。很多情况下请求的链接可能是同一个,但是POST的参数不同.这时可以重写get_taskid()方法,改变这个 ID 的计算方式来实现不同任务的区分.
import json
from pyspider.libs.utils import md5string
def get_taskid(self, task):
return md5string(task['url']+ json.dumps(task['fetch'].get ('data','')))
利用 URL 和 PO ST 的参数来生成囚 。这样一来,即使 URL 相同,但是 POST 的参数不同,两个任务的 ID 就不同,它们就不会被识别成重复任务
4.全局配置
使用crawl_config指定全局的配置(字典),配置中的参数和crawl()方法创建任务时的参数合并
5.定时爬取(请求过期时间内,不执行爬取)
@every(minutes=24 * 60) # every 属性来设置爬取的时间间隔,此处为每天执行一次
@config(age=10 * 24 * 60 * 60) # 请求过期时间是10天,10天内不会再次请求
4、主界面
4.1【group】
可以设置项目的组名【group】,给项目分类
4.2【project name】
项目名,创建新项目时自定义的项目名
4.3【status】
- TODO:它是项目刚刚被创建还未实现时的状态 。
- STOP:如果想停止某项目的抓取,可以将项目的状态设置为 STOP 。
- CHECKING:正在运行的项目被修改后就会变成 CHECKING 状态,项目在中途出错需要调整
的时候会遇到这种情况 。 - DEBUG/RUNNING:这两个状态对项目的运行没有影响,状态设置为任意一个,项目都可以
运行,但是可以用二者来区分项目是否已经测试通过 。
注:只有设为DEBUG/RUNNING之后,才可以在【actions】中点击【run】按钮 - PAUSE:当爬取过程中出现连续多次错误时,项目会自动设置为 PAUSE 状态,并等待一定时间后继续爬取
4.4【rate/burst】
- 1/3表示1秒发送一个请求,3个进程
4.5【avg time】
- 平均运行时长
4.6【progress】
- 爬取进度:5m、1h、1d、all表示抓取情况
- 蓝色:pending,等待被爬取
- 绿色:bar-success,爬取成功
- 粉红色:bar-warning,爬取出错,继续等待被爬取
- 红色:bar-danger,爬取失败
4.3【actions】
- run表示运行
- active tasks 查看请求
- results 查看结果
4.4删除项目
将项目的【status】设置为 【STOP】 ,将【group】设置为【delete】,24 小时之后项目会自动删除