# Python3 爬虫学习笔记 C18

TRHX

2019-09-21

Python3 学习笔记 / 爬虫学习

字数统计:

2,532字

阅读时长≈

11分

> Python3 爬虫学习笔记第十八章 —— 【爬虫框架 pyspider — 深入理解】

# 【18.1】启动参数

常用启动命令：`pyspider all`，完整命令结构为：`pyspider [OPTIONS] COMMAND [ARGS]`，OPTIONS 为可选参数，包含以下参数：

- -c, –config FILENAME：指定配置文件名称
- –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：数据库存放的路径
- –add-sys-path / –not-add-sys-path：将当前工作目录添加到python lib搜索路径
- –version：显示 pyspider 的版本信息
- –help：显示帮助信息

配置文件为一个 JSON 文件，一般为 config.json 文件，常用配置如下：

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

    {
      "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": {
      	"port": 5000,
        "username": "some_name",
        "password": "some_passwd",
        "need-auth": true
      }
    }

可以设置对应的用户名，密码，端口等信息，使用命令 `pyspider -c config.json all` 即可运行

# 【18.2】运行单个组件

pyspider 的架构主要分为 Scheduler（调度器）、Fetcher（抓取器）、Processer（处理器）三个部分，都可以单独运行，基本命令： `pyspider [component_name] [options]`

## 【18.2.1】运行 Scheduler

    1

    pyspider scheduler [OPTIONS]

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

    Options:
      --xmlrpc /--no-xmlrpc
      --xmlrpc-host TEXT
      --xmlrpc-port INTEGER
      --inqueue-limit INTEGER  任务队列的最大长度，如果满了则新的任务会被忽略
      --delete-time INTEGER    设置为 delete 标记之前的删除时间
      --active-tasks INTEGER   当前活跃任务数量配置
      --loop-limit INTEGER     单轮最多调度的任务数量
      --fail-pause-num INTEGER 上次失败时自动暂停项目暂停次数，任务失败，将0设置为禁用
      --scheduler-cls TEXT     Scheduler 使用的类
      --threads TEXT           ThreadBaseScheduler 的线程号，默认值：4
      --help                   显示帮助信息

## 【18.2.2】运行 Fetcher

    1

    pyspider fetcher [OPTIONS]

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

    Options:
      --xmlrpc /--no-xmlrpc
      --xmlrpc-host TEXT
      --xmlrpc-port INTEGER
      --poolsize INTEGER         同时请求的个数
      --proxy TEXT               使用的代理
      --user-agent TEXT          使用的 User-Agent
      --timeout TEXT             超时时间
      --phantomjs-endpoint TEXT  phantomjs 的端点，通过 pyspider 启动 phantomjs
      --splash-endpoint TEXT     执行 splash 的端点：http://splash.readthedocs.io/en/stable/api.html execut
      --fetcher-cls TEXT         Fetcher 使用的类
      --help                     显示帮助信息

## 【18.2.3】运行 Processer

    1

    pyspider processor [OPTIONS]

    1
    2
    3
    4

    Options:
      --processor-cls TEXT  Processor 使用的类
      --process-time-limit INTEGER    脚本处理时间限制
      --help                          显示帮助信息

## 【18.2.4】运行 WebUI

    1

    pyspider webui [OPTIONS]

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14

    Options:
      --host TEXT                   运行地址
      --port INTEGER                运行端口
      --cdn TEXT                    JS 和 CSS 的 CDN 服务器
      --scheduler-rpc TEXT          Scheduler 的 xmlrpc 路径
      --fetcher-rpc TEXT            Fetcher 的 xmlrpc 路径
      --max-rate FLOAT              每个项目最大的 rate 值
      --max-burst FLOAT             每个项目最大的 burst 值
      --username TEXT               Auth 验证的用户名
      --password TEXT               Auth 验证的密码
      --need-auth                   是否需要验证
      --webui-instance TEXT         运行时使用的 Flask 应用
      --process-time-limit INTEGER  调试中的脚本处理时间限制
      --help                        显示帮助信息

# 【18.3】crawl() 方法各参数

参数文档：http://docs.pyspider.org/en/latest/apis/self.crawl/

- url：爬取目标 URL，可以定义为单个 URL 字符串，也可以定义成 URL 列表

- callback：回调函数，指定了该 URL 对应的响应内容用哪个方法来解析，示例：

    1
    2

    def on_start(self):
      self.crawl('http://www.itrhx.com/', callback=self.index_page)

代码解释：指定 `callback` 为 `index_page`，代表爬取 http://www.itrhx.com/ 得到的响应会用 `index_page()` 方法来解析，而 `index_page()` 方法的第一个参数就是响应对象，如下所示：

    1
    2

    def index_page(self, response):
      pass

- age：任务的有效时间，如果某个任务在有效时间内且已经被执行，则它不会重复执行，有如下两种设置方法：

    1
    2

    def on_start(self):
      self.crawl('http://www.itrhx.com/', callback=self.callback, age=10*24*60*60)

    1
    2
    3

    @config(age=10 * 24 * 60 * 60)
    def callback(self):
        pass

- priority：爬取任务的优先级，其值默认是 0，priority 的数值越大，对应的请求会越优先被调度，如下所示，`2.html` 页面将会优先爬取：

    1
    2
    3

    def index_page(self):
      self.crawl('http://www.itrhx.com/1.html', callback=self.index_page)
      self.crawl('http://www.itrhx.com/2.html', callback=self.detail_page, priority=1)

- exetime：设置定时任务，其值是时间戳，默认是 0，即代表立即执行，如下所示表示该任务会在 30 分钟之后执行：

    1
    2
    3

    import time
    def on_start(self):
      self.crawl('http://www.itrhx.com/', callback=self.callback, exetime=time.time()+30*60)

- retries：定义重试次数，其值默认是 3

- itag：设置判定网页是否发生变化的节点值，在爬取时会判定次当前节点是否和上次爬取到的节点相同。如果节点相同，则证明页面没有更新，就不会重复爬取，如下所示：

    1
    2
    3

    def index_page(self, response):
      for item in response.doc('.item').items():
          self.crawl(item.find('a').attr.url, callback=self.detail_page, itag=item.find('.update-time').text())

代码解释：设置 `update-time` 这个节点的值为 itag，在下次爬取时就会首先检测这个值有没有发生变化，如果没有变化，则不再重复爬取，否则执行爬取

- auto_recrawl：开启时，爬取任务在过期后会重新执行，循环时间即定义的 age 时间长度，如下所示：

    1
    2

    def on_start(self):
      self.crawl('http://www.itrhx.com/', callback=self.callback, age=5*60*60, auto_recrawl=True)

代码解释：定义 `age` 有效期为 5 小时，设置了 `auto_recrawl` 为 `True`，这样任务就会每 5 小时执行一次

- method：HTTP 请求方式，默认为 GET，如果想发起 POST 请求，可以将 method 设置为 POST

- params：定义 GET 请求参数，如下所示表示两个等价的爬取任务：

    1
    2
    3

    def on_start(self):
      self.crawl('http://httpbin.org/get', callback=self.callback, params={'a': 123, 'b': 'c'})
      self.crawl('http://httpbin.org/get?a=123&b=c', callback=self.callback)

- data：POST 表单数据，当请求方式为 POST 时，我们可以通过此参数传递表单数据，如下所示：

    1
    2

    def on_start(self):
      self.crawl('http://httpbin.org/post', callback=self.callback, method='POST', data={'a': 123, 'b': 'c'})

- files：上传的文件，需要指定文件名，如下所示：

    1
    2

    def on_start(self):
      self.crawl('http://httpbin.org/post', callback=self.callback, method='POST', files={field: {filename: 'content'}})

- user_agent：爬取使用的 User-Agent

- headers：爬取时使用的 Headers，即 Request Headers

- cookies：爬取时使用的 Cookies，为字典格式

- connect_timeout：在初始化连接时的最长等待时间，默认为 20 秒

- timeout：抓取网页时的最长等待时间，默认为 120 秒

- allow_redirects：确定是否自动处理重定向，默认为 True

- validate_cert：确定是否验证证书，此选项对 HTTPS 请求有效，默认为 True

- proxy：爬取时使用的代理，支持用户名密码的配置，格式为 `username:password@hostname:port`，如下所示：

    1
    2

    def on_start(self):
      self.crawl('http://httpbin.org/get', callback=self.callback, proxy='127.0.0.1:9743')

也可以设置 `craw_config` 来实现全局配置，如下所示：

    1
    2

    class Handler(BaseHandler):
      crawl_config = {'proxy': '127.0.0.1:9743'}

- fetch_type：开启 PhantomJS 渲染，如果遇到 JavaScript 渲染的页面，指定此字段即可实现 PhantomJS 的对接，pyspider 将会使用 PhantomJS 进行网页的抓取，如下所示：

    1
    2

    def on_start(self):
      self.crawl('https://www.taobao.com', callback=self.index_page, fetch_type='js')

- js_script：页面加载完毕后执行的 JavaScript 脚本，如下所示，页面加载成功后将执行页面混动的 JavaScript 代码，页面会下拉到最底部：

    1
    2
    3
    4
    5
    6
    7

    def on_start(self):
      self.crawl('http://www.example.org/', callback=self.callback,
                 fetch_type='js', js_script='''
                 function() {window.scrollTo(0,document.body.scrollHeight);
                     return 123;
                 }
                 ''')

- js_run_at：代表 JavaScript 脚本运行的位置，是在页面节点开头还是结尾，默认是结尾，即 `document-end`

- js_viewport_width/js_viewport_height：JavaScript 渲染页面时的窗口大小

- load_images：在加载 JavaScript 页面时确定是否加载图片，默认为否

- save：在不同的方法之间传递参数，如下所示：

    1
    2
    3
    4
    5
    6

    def on_start(self):
      self.crawl('http://www.example.org/', callback=self.callback,
                 save={'page': 1})

    def callback(self, response):
      return response.save['page']

- cancel：取消任务，如果一个任务是 `ACTIVE` 状态的，则需要将 `force_update` 设置为 `True`

- force_update：即使任务处于 ACTIVE 状态，那也会强制更新状态

# 【18.4】任务区分

pyspider 判断两个任务是否是重复的是使用的是该任务对应的 URL 的 MD5 值作为任务的唯一 ID，如果 ID 相同，那么两个任务就会判定为相同，其中一个就不会爬取了

某些情况下，请求的链接是同一个，但是 POST 的参数不同，这时可以重写 `task_id()` 方法，利用 URL 和 POST 的参数来生成 ID，改变这个 ID 的计算方式来实现不同任务的区分：

    1
    2
    3
    4

    import json
    from pyspider.libs.utils import md5string
    def get_taskid(self, task):
        return md5string(task['url']+json.dumps(task['fetch'].get('data', '')))

# 【18.5】全局配置

pyspider 可以使用 `crawl_config` 来指定全局的配置，配置中的参数会和 `crawl()` 方法创建任务时的参数合并：

    1
    2
    3
    4
    5

    class Handler(BaseHandler):
        crawl_config = {
            'headers': {'User-Agent': 'GoogleBot',}
            'proxy': '127.0.0.1:9743'
        }

# 【18.6】定时爬取

通过 `every` 属性来设置爬取的时间间隔，如下代码表示每天执行一次爬取：

    1
    2
    3
    4

    @every(minutes=24 * 60)
    def on_start(self):
        for url in urllist:
            self.crawl(url, callback=self.index_page)

注意事项：如果设置了任务的有效时间（age 参数），因为在有效时间内爬取不会重复，所以要把有效时间设置得比重复时间更短，这样才可以实现定时爬取

错误举例：设定任务的过期时间为 5 天，而自动爬取的时间间隔为 1 天，当第二次尝试重新爬取的时候，pyspider 会监测到此任务尚未过期，便不会执行爬取：

    1
    2
    3
    4
    5
    6
    7

    @every(minutes=24 * 60)
    def on_start(self):
        self.crawl('http://www.itrhx.com/', callback=self.index_page)

    @config(age=5 * 24 * 60 * 60)
    def index_page(self):
        pass

您的喜欢是作者写作最大的动力！❤️

- PayPal
- AliPay
- WeChatPay
- QQPay

Donate

最后更新于 2019年9月24日

爬虫

pyspider

###### 上一页

#### Python3 爬虫实战 — 猫眼电影TOP100

###### 爬虫 猫眼电影

###### 下一页

#### Python3 爬虫学习笔记 C17

###### 爬虫 pyspider

#### 评论

## ๑۩ﺴ TRHX ﺴ۩๑

本文目录
站内导航

- 所有文章
- 文章归档
- RSS订阅
- 我的友链
- 留言板
- 关于博主

欢迎光临
访客地图
交流群组

QQ 交流群 Telegram 交流群

文章分类

- BLOG
  (4)
- CDN
  (1)
- Hexo
  (9)
- Java
  (1)
- Linux
  (2)
- Markdown
  (2)
- Python3 学习笔记
  (39)
- 基础学习
  (9)
- 学习经验
  (4)
- 爬虫学习
  (18)
- 爬虫实战
  (8)
- VPS
  (1)
- WEB前端
  (2)
- 图床
  (1)

热门标签
12306 58同城 Ajax BLOG Beautiful Soup CDN Coding Pages Deepin Elicpse GitHub Pages Github Github Pages HTTPS Hexo ICP备案 JDBC JS 预加载 Markdown Material X MongoDB MySQL PEP8 PicGo Pygame Python Redis SEO SQL Server 2012 SSR Selenium Ubuntu User-Agent VMware VPS XPath if语句 input()函数 instant.page jsDelivr lxml pyspider requests spfk urllib while循环 主题个性化 代理 公安备案 函数 列表 变量 哔哩哔哩 图床 图形验证码 垃圾 备份 字典 安居客 年终总结 异常 技巧 操作列表 数据类型 文件 文件储存 无界面浏览器 模块 正则表达式 滑动验证码 点触验证码 爬虫 猫眼电影 瓜子二手车 类 继承 编辑器 虎扑论坛 豆瓣电影
最近在听