爬虫之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
        }
例子:爬取去哪儿网

 

posted @ 2019-04-09 16:12  爱学习的红领巾  阅读(460)  评论(0编辑  收藏  举报