1. 与scrapy的比较:
- pyspider提供 了 WebUI,爬虫的编写、调试都是在 WebUI 中进行的 。 而 Scrapy原生是不具备这个功能的,它采用的是代码和命令行操作,但可以通过对接 Portia实现可视化配置。
- pyspider调试非常方便 , WebUI操作便捷直观。 Scrapy则是使用 parse命令进行调试, ;民:方便程度不及 p)叩ider。
- pyspider支持 PhantomJS来进行 JavaScript谊染页面的采集 。 Scrapy可以对接 Scrapy-Splash组件,这需要额外配置 。
-
pyspider中内置了 pyquery作为选择器。 Scrapy对接了 XPath、 css选择器和正则匹配。
-
pyspider 的可扩展程度不足,可配制化程度不高 。 Scrapy 可以 通过对接 Middleware、 Pipeline、Extension等组件实现非常强大 的功能, 模块之间的稠合程度低,可扩展程度极高 。
2. pyspider的架构:
pyspider的架构主要分为 Scheduler (调度器)、 Fetcher (抓取器)、 Processer (处理器) 三个部分,整个爬取过程受到 Monitor (监控器)的监控,抓取的结果被 Result Worker (结果处理器)处理。
Scheduler 发起任务调度, Fetcher 负责抓取网页内容, Processer 负责解析网页内容,然后将新生成的 Request发给 Scheduler进行调度,将生成的提取结果输出保存。
- 每个 pyspider 的项目对应一个 Python j阅本,该脚本中定义了一个 Handler 类,它有一个on_start()方法。 爬取首先调用 on_start()方法生成最初的抓取任务,然后发送给 Scheduler进行调度 。
- Scheduler将抓取任务分发给 Fetcher进行抓取, Fetcher执行并得到响应,随后将响应发送给Processer。
- Processer 处理响应并提取 H-',新的 URL 生成新的抓取任务,然后通过消息队列的方式通知Schduler 当前抓取任务执行情况,并将新生成的抓取任务发送给 Scheduler。 如果生成了新的提取结果,则将其发送到结果队列等待 ResultWorker处理。
- Scheduler 接收到新的抓取任务,然后查询数据库,判断其如果是新的抓取任务或者是需要重试的任务就继续进行调度,然后将其发送回 Fetcher进行抓取。
- 不断重复以上工作,直到所有的任务都执行完毕,抓取结束 。
- 抓取结束后,程序会回调 on_finished()方法,这里可以定义后处理过程。
3.使用
pyspider all
http:localhost:5000
当爬取网页无法加载图片时,可能是图片是由JS渲染的
1 def index_page(self, response): 2 for each in response.doc('li > .tit > a').items(): 3 self.crawl(each.attr.href, 4 callback=self.detail_page, 5 fetch_type='js')#启用PhantomJS渲染 6 next = response.doc('.next').attr.href 7 self.crawl(next,callback=self.index_page)
1 from pyspider.libs.base_handler import * 2 3 4 class Handler(BaseHandler): 5 crawl_config = { 6 } 7 8 @every(minutes=24 * 60) 9 def on_start(self): 10 self.crawl('http://travel.qunar.com/travelbook/list.htm', callback=self.index_page) 11 12 @config(age=10 * 24 * 60 * 60) 13 def index_page(self, response): 14 for each in response.doc('li > .tit > a').items(): 15 self.crawl(each.attr.href, 16 callback=self.detail_page, 17 fetch_type='js') 18 next = response.doc('.next').attr.href 19 self.crawl(next,callback=self.index_page) 20 21 @config(priority=2) 22 def detail_page(self, response): 23 return { 24 "url": response.url, 25 #"title": response.doc('title').text(), 26 "title": response.doc('#booktitle').text(), 27 "date": response.doc('.when .data').text(), 28 "day": response.doc('.howlong .data').text(), 29 "who": response.doc('.who .data').text(), 30 "text": response.doc('#b_panel_schedule').text(), 31 "image": response.doc('.cover_img').attr.src 32 }
rate/burst代表当前的爬取速率, rate代表 l 秒发IH多少个请求, burst相当于流量控制中的令牌桶算法的令牌数, rate和 burst设置的越大,爬取速率越快,当然连率需要考虑本机性能和爬取过快被封的问题。 process中的 5m、 lh、 ld指的是最近 5分、l 小时 、 l 天内的请求’情况, all 代表所有的请求情况 。 请求由不同颜色表示,蓝色的代表等待被执行的请求 ,绿色的代表成功的请求,黄色的代表请求失败后等待重试的请求,红色的代表失败次数过 多rfi被忽略的请求,这样可以直观知道爬取的进度和请求情况.
pyspider [OPTIONS) COMMAND [ARGS)
1 Options: 2 -c, --config FILENAME 指定配置文件名称 3 --logging-config TEXT 日志配置文件名称 ,默认 :pyspider/pyspider/logging.conf 4 --debug 开启调试模式 5 --queue-maxsize INTEGER 队列的最大长反 6 --taskdb TEXT taskdb 的数据库连接字符串,默认: sqlite 7 --projectdb TEXT projectdb 的数据库连接字符串,默认: sqlite 8 --resultdb TEXT resultdb 的数据库连接字符串,默认: sqlite 9 --message-queue TEXT 消息队连接字符串,默认· multiprocessing.Queue 10 --phantomjs-proxy TEXT PhantomJS 使用的代理, ip:port 的形式 11 --data-path TEXT 数据库存放的路径 12 --version pyspider 的版本 13 --help 显示帮助信息 14
crawl用法
• url
url是爬取时的 URL,可以定义为单个 URL字符串,也可以定义成 URL列表
• callback
callback是回调函数,指定了该 URL对应的响应内容用哪个方法来解析,
• age
age 是任务的有效时间 。 如果某个任务在有效时间内且已经被执行,则它不会重复执行
• priority
priority 是爬取任务的优先级,其值默认是 0,priority 的数值越大,对应的请求会越优先被调度,
• exetime
exetime参数可以设置定时任务,其值是时间戳,默认是 0,即代表立即执行
• retries
retries 可以定义重试次数,其值默认是 3。
• itag
itag 参数设置判定网页是存发生变化的节点值,在爬取时会判定次当前节点是否和上次爬取到的节点相同 。 如果节点相同,则证明页面没有更新,就不会重复爬取,
• auto recrawl
当开启 时,爬取任务在过期后会重新执行,循环时间即定义的 age 时间长度
• method
method是 HTTP请求方式,它默认是 GET。 如果想发起 POST请求,可以将 method设置为 POST。
• params
我们可以方便地使用 params 来定义 GET请求参数
• data
data是 POST表单数据。 当请求方式为 POST时,我们可以通过此参数传递表单数据
• files
files 是上传的文件,需要指定文件名
• 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。
• proxy
proxy是爬取时使用的代理,它支持用户名密码的配置,格式为 username:password@hostname:port,
• fetch_type
fetch_type开启 PhantomJS渲染 。如果遇到 JavaScript渲染的页面,指定此字段即可实现 PhantomJS的对接,pyspider将会使用 PhantomJS 进行网页的抓取,
• js_script
js script 是页面加载完毕后执行的 JavaScript脚本
• js_run_at
JavaScript脚本运行的位置,是在页面节点开头还是结尾 , 默认是结尾, 即 document-end。
• js_viewport_width/js_viewport_height
js_viewport_width/js_viewport_height是 JavaScript渲染页面时的窗口大小。
• load_images
load_images在加载 JavaScript页面时确定是否加载图片,它默认是否。
• save
save 参数非常有用,可以在不同的方法之 间传递参数
• cancel
cancel是取消任务,如果一个任务是 ACTIVE状态的, 则需要将 force_update设置为 True。
• force_ update
即使任务处于 ACTIVE状态,那也会强制更新状态。
pyspider判断两个任务是否是重复 的是使用的是该任务对应的 URL 的 MD5 值作为任务的唯一ID,如果ID 相 同,那么两个任务就会判定为相同,其中一个就不会爬取了 。 很多情况下请求的链接叮能是同一个,但是POST的参数不同。 这时可以重写task_id()方法,改变这个ID的计算方式来实现不同任务的区分,
定时爬取
1 @every(minutes=24 * 60) 2 def on_start(self): 3 for url in urllist: 4 self.crawl(url, callback=self.index_page)