zoukankan      html  css  js  c++  java
  • python3编写网络爬虫20-pyspider框架的使用

    二、pyspider框架的使用

    简介 pyspider是由国人binux 编写的强大的网络爬虫系统 github地址 :

    https://github.com/binux/pyspider 


    官方文档

     http://docs.pyspider.org/

    pyspider 带有强大的WebUI 脚本编辑器 任务监控器 项目管理器 以及结果处理器 支持多种数据库后端 多种消息队列 JavaScript
    渲染页面的爬取 使用起来非常方便

    1.基本功能

    提供可视化编写和调试爬虫
    爬虫项目管理能力
    支持多种后端数据库
    支持多种消息队列
    提供优先级控制 失败重试 定时抓取等
    支持单机的分布式部署


    pyspider架构

    主要分为Scheduler(调度器)Fetcher (抓取器) Processer (处理器) 三部分
    整个爬取过程受到Monitor(监控器) 的监控 抓取结果被Result Worker (结果处理器) 处理

    Scheduler 发起任务调度 Fetcher 负责抓取网页内容 Processer 负责解析网页 然后生成新的reuqest 发送给调度器 进行调度
    生成的提取结果输出保存

    pyspider的执行逻辑很清晰 如下:

    1.每个pyspider的项目对应一个python脚本 脚本中定义Handler类 有一个on_start 方法 爬取首先调用 on_start() 生成最初的
    抓取任务 然后发送给调度器

    2.调度器将抓取任务分发给抓取器进行抓取 抓取器执行并得到响应 随后将响应发送给处理器

    3.处理器处理响应并提取新的url生成新的抓取任务 然后通过消息队列的方式通知调度器 当前抓取任务执行情况 并将新生成的抓取
    任务发送给调度器 如果生成新的抓取结果 则将其发送到结果队列等待 结果处理器处理

    4.调度器收到新的抓取任务 查询数据库 判断新的抓取任务是否需要重新进行调度 然后发送给抓取器进行抓取

    5.不断重复上面的工作 直到所有任务执行完毕 抓取结束

    6.抓取结束后程序会回调 on_finished() 方法 这里可以定义后处理过程


    2.基本使用

    安装 

    pip install pyspider

    如果报错 python setup.py egg.......pycurl

    需要安装pycurl库 从 https://www.lfd.uci.edu/~gohlke/pythonlibs/#pycurl 找到对应版本的wheel文件 进行安装

    验证安装

    命令行 pyspider all

    浏览器打开 http://localhost:5000/ 看到WebUI管理页面 表示安装成功


    3.创建项目 (目标爬取 攻略的作者 标题 出发日期 人均费用 正文等保存)

    新建项目 点击create 弹窗输入 项目名 和 爬取链接 点击create 就创建了一个项目
    例如 qunar 链接 http://travel.qunar.com/travelbook/list.htm

    会看到左侧是调试页面 点击左侧右上角run 单步调试爬虫 左侧下半部分可以预览 当前爬取的页面
    右侧是代码编辑页面 可以直接编辑保存代码 不需要借助IDE工具

    右侧已经生成了一段代码

    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('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就是爬虫主类 可以在此处定义爬取 解析 存储的逻辑 整个代码只需要一个Handler即可完成

    crawl_config属性 可以将项目的爬取配置统一定义 例如headers 设置代理 配置之后全局生效

    on_start 爬虫入口 该方法通过调用 crawl() 方法即可新建一个爬取请求 第一个参数是爬取url callback 指定了爬取页面成功后
    用哪个方法解析

    index_page 接收response 参数 对接pyquery 直接调用doc 传入css选择器 代码中默认解析页面所有链接 然后遍历 再次调用crawl
    生成新的爬取请求 同时指定callback 为 detail_page 意思是如果页面爬取成功了就调用detail_page 方法解析
    这里实现两个功能 1.将爬取结果解析 2. 生成新的爬取请求

    detail_page 接收resposne参数 抓取的是详情页 就不会生成新的请求 只做解析 解析后将结果以字典形式返回


    4.爬取首页

    点击run 看到下方follows 产生一个新的请求

    左栏会出现当前run配置信息 这里有一个callback 为 on_start 说明点击run之后 实际执行了 on_start 方法
    在 on_start 中利用 crawl 生成一个爬取请求

    点击 follows 即可看到生成的爬取请求链接 每个链接右侧还有一个箭头

    点击箭头 就可以对此链接进行爬取 也就是攻略首页

    上方的 callback已经变成 index_page 代表运行了 index_page 方法 接收到的resposne 参数 就是第一个爬取请求的response对象

    调用doc 传入css 选择器 获取a 节点属性 拿到第一个爬取页面所有链接 然后遍历 调用 crawl 把链接构造成新的请求

    点击web 可预览爬取结果页面 结果和浏览器几乎一样结果

    html 查看页面源代码


    在 index_page 方法中提取了所有链接 并生成了新的爬取请求 但是爬取的肯定不是所有链接 只需要详情页就够了
    修改一下当前index_page css选择器

    可以借助另外一个工具

    首先切换到Web页面 找到攻略标题 点击下方 enable css selector helper
    在右侧选中要更改的区域
    点击左栏右箭头 css选择器就替换成功了
    重新run 就提取了当前页面10个攻略

    还需要抓取后续页面

    在 index_page 方法 添加如下代码

    next = response.doc('.next').attr.href
    self.crawl(next,callback = self.index_page)

    利用css选择器 选中下一页 链接 获取href属性 也就获取了页面的URL 然后将URL传给Crawl 指定回调函数
    注意这里回调函数仍然是index_page 因为下一页的结构与此页相同
    重新run 就可以看到11个请求

    索引列表页解析就完成了


    5.爬取详情页

    任选一个详情页进入 点击前10个爬取请求中的任意一个箭头 执行详情页爬取

    切换到web 页面下拉 头图正文中的图片一直显示加载中

    出现此现象的原因是pyspider默认发送http请求 请求文档本身不包含img 图片是经过js渲染的

    pyspider 内部对接了Phantomjs 只需要修改一个参数即可

    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)

    点击 左栏上方 返回箭头 重新调用 index_page 在点击新生成的详情页就可以看到了


    最后将详情页需要的信息 提取出来

    detail_page代码如下

    def detail_page(self,response):
      return{
        'url' : response.url,
        'title' : response.doc('#booktitle').text(),
        'date' : response.doc('.when .data').text(),
        'day' : response.doc('.howlong .data').text(),
        'who' : response.doc('.who .data').text(),
        'text' : response.doc('#b_panel_schedule').text(),
        'image' : response.doc('.cover_img').attr.src
      }

    6.启动爬虫


    返回爬虫主页面 将status 设置为DEBUG 或者 RUNNING 点击右侧RUN 即可开始爬取

    在最左侧可以定义项目分组 方便管理 rate/burst 代表当前爬取速率 rate 代表1秒 发出多少请求
    burst 相当于流量控制 rate和burst设置越大 爬取速率越快 (要考虑性能的IP被封)
    Process中 5m 1h 1d 指最近5分 1小时 1天 all代表所有请求
    蓝色代表等待执行请求
    绿色代表成功请求
    黄色代表失败 重试请求
    红色代表失败过多 忽略请求


    点击Active Tasks即可查看最近请求

    点击results 即可查看爬取结果

    点击右上角按钮 即可保存获取数据格式

    更多参考资料 参考官方文档 http://docs.pyspider.org/

  • 相关阅读:
    【C++】基础及引用
    gradle打包分编译环境
    gradle
    MediaPlayer滑动不准的问题
    python初步入门
    音频播放服务
    《深入理解Android2》读书笔记(二)
    缓存(LruCache)机制
    handler机制
    监听网络状态
  • 原文地址:https://www.cnblogs.com/liuxiaosong/p/10368435.html
Copyright © 2011-2022 走看看