爬虫之pyspider
1.简单的介绍
pyspider是由国人binux编写的强大的网络爬虫系统,其GitHub地址为 https://github.com/binux/pyspider 官方文档地址为 http://docs.pyspider.org/
1)基本功能
♢ 提供方便易用的WebUI系统,可视化编写和调试爬虫。
♢ 提供爬取进度监控、爬取结果查看、爬虫项目管理等功能。
♢ 支持多种后端数据库,如MySQL、MongoDB、Redis、SQlite、Elasticsearch、PostgreSQL。
♢ 支持多种消息队列,如RabbitMQ、Beanstalk、Redis、Kombu。
♢ 提供优先级控制、失败重试、定时抓取等功能。
♢ 对接了PhantomJS,可以抓取JavaScript渲染的页面。
♢ 支持单机和分布式部署,支持Docket部署。
适合快速实现一个页面的抓取,开发便捷
2)架构
pyspider的架构主要分为Schrduler(调度器)、Fetcher(抓取器)、Processer(处理器)三个部分,整个爬取过程受到Monitor(监控器)的监控,抓取的结果被Result Worker(结果处理器)处理。
Scheduler发起任务调度,Fetcher负责抓取网页内容,Processer负责解析网页内容,然后将新生成的Request发给Scheduler进行调度,将生成的提取结果输出保存。
pyspider的任务执行流程:
♢ 每个pyspider的项目对应一个Python脚本,该脚本中定义了一个Handler类,它有一个on_start()方法。爬取首先调用on_start()方法生成最初的抓取任务,然后发送给Scheduler进行调度。
♢ Scheduler将抓取的任务分发给Fetcher进行抓取,Fetcher执行并得到响应,随后将响应发送给Pocesser。
♢ Pocesser处理响应并提取出新的URL生成新的抓取任务,然后通过消息队列的方式通知Scheduler当前抓取任务执行情况,并且新生成的住区任务发送给Scheduler。如果生成了新的提取结果,则将其发送到结果队列等待Result Worker处理。
♢ Scheduler接收到新的抓取任务,然后查询数据库,判断其如果是新的抓取任务或者需要重试的任务就继续进行调度,然后将其发送回Fetcher进行抓取。
♢ 不断重复以上工作,直到所有的任务都执行完毕,抓取结束。
♢ 抓取结束后,程序会回调on_finished()方法,这里可以定义后处理过程。
2.基本使用
命令行中输入 pyspider 开启服务
默认开启地址为http://localhost:5000
创建项目,点击create按钮
编辑与调试页面
左侧为代码调试页面,点击左侧右上角的run单步调试爬虫程序,在左侧下半部分可以玉兰当前的爬取页面。右侧为代码编辑页面,可以直接编辑代码和保存代码
from pyspider.libs.base_handler import * class Handler(BaseHandler): crawl_config = { } @every(minutes=24 * 60) def on_start(self): self.crawl('https://docs.python.org/zh-cn/3/library/index.html', callback=self.index_page) @config(age=10 * 24 * 60 * 60) def index_page(self, response): 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): return { "url": response.url, "title": response.doc('title').text(), } 创建项目即会生成
Handler就是pyspider爬虫的主类,定义爬取、解析、储存等逻辑。
crawl_config为爬取配置的定义
on_start()方法是爬取入口,出师的爬取请求会在这里生成,该方法通过调用crawl()方法即可新建一个爬取请求,crawl()方法还有存在回调函数callback,制定了这个页面爬取成功后用哪个方法进行解析
index_page()接收Response参数,Response对接了pyquery。可以直接调用doc()方法传入相应的css选择器,再次调用了crawl()方法生成了新的爬取请求,同时再指定了callback为detail_page。
detail_page()同样接收Response作为参数,抓取的是详情页的信息,只对Response对象做解析,将结果以字典形式返回。
3.注意事项
pyspider默认发送HTTP请求,网页中存在的图片等如果是由JavaScript产生,需要将index_page()中生成抓取详情页的请求方法添加一个参数fecth_type=‘js’,那么就会获取JS产物
4.命令行
http://docs.pyspider.org/en/latest/Command-Line/
5.crawl()方法
url 要抓取的网址或者网址列表 callback 确定解析函数 age 任务的有效期 priority 爬取的优先级 exetime 设置定时任务 retries 定义重试次数 itag 设置判定网页是否发生变化的节点值 auto_recrawl 开启后,爬取任务在过期之后会重新执行,循环时间为age method 请求方式 params GET请求数据 data POST请求数据 files 上传的文件 user_agent User-Agent headers 请求头 cookies Cookies connect_timeout 初始化连接时的最长等待时间 timeout 抓取网页时的最长等待时间 allow_redirects 确定是否自动处理重定向 validate_cert 确定是否验证证书 proxy 代理 fetch-type 开启PhantomJS js_script 页面加载完毕后执行的js脚本 js_run_at js脚本运行的位置,是在页面节点开头还是结尾,默认是结尾 js_viewport_width/js_viewport_height js渲染时的窗口大小 load_images 加载js页面时确定是否加载图片 save 在不同的方法之间传递参数 cancel 取消任务 force_update 强制更新状
from pyspider.libs.base_handler import * class Handler(BaseHandler): crawl_config = { } @every(minutes=24 * 60) def on_start(self): self.crawl('http://travel.qunar.com/travelbook/list.htm', callback=self.index_page) @config(age=10 * 24 * 60 * 60) def index_page(self, response): for each in response.doc('li > .tit > a').items(): self.crawl(each.attr.href, callback=self.detail_page,fetch_type='js') next = response.doc(".next").attr.href self.crawl(next, callback=self.index_page) @config(priority=2) def detail_page(self, response): return { "url": response.url, "title": response.doc('title').text(), "date": response.doc(".when .data").text(), "day": response.doc(".howlong .data").text(), "who": response.doc(".head").text(), "text": response.doc("#b_panel_schedule").text(), "image":response.doc(".cover_img").attr.src }