轻松组建分布式 pyspider 集群

前言

写爬虫爬站,你只有一台机子怎么能叫一个科学的、高效的爬虫呢?你起码得要有成百上千台机子一起跑才叫爬虫吧~当然,我是开玩笑的,而且我觉得谁没事开成百上千个服务器来跑爬虫(当然,除了B/G等)

使用 pyspider 也有一段时间了,一直比较郁闷的是,这是一个可以分布式运行的爬虫框架,那究竟怎么能让他分布式起来呢?

趁着现在这段时间非常有空,于是我继续翻阅了pyspider架构设计,终于得到了我的答案,下面我就来演示演示如何组件分布式的 pyspider 集群。

理论

以下内容摘自框架设计

pyspider 的架构主要分为 scheduler(调度器), fetcher(抓取器), processor(脚本执行):

意思就是,如果我们想要进行分布式的运行,那么我们需要公用 master 的 scheduler ,其他 slave 机子只需要自己跑自己的 fetcher 和 processor 即可

组建

安装 pyspider

敬请参阅:Debian 8.1 安装配置 pyspider 爬虫

pyspider 设置

请参照上一篇文章我所写的配置

由于 MySQL 和 redis 的服务器地址都已经不是本地的 127.0.0.1 ,因此我们要将其设置为 master 或者你 MySQL 的服务器IP。

另外,我们要将 fetcher 设置 xmlrpc-host 地址,如果你修改了默认的地址可能需要设置 xmlrpc-port ,这都是因人而异的。

我的设置如下:

{
  "taskdb": "mysql+taskdb://pyspider:[email protected]:3306/taskdb",
  "projectdb": "mysql+projectdb://pyspider:[email protected]:3306/projectdb",
  "resultdb": "mysql+resultdb://pyspider:[email protected]:3306/resultdb",
  "message_queue": "redis://192.168.1.3:6379/db",
  "phantomjs-proxy": "127.0.0.1:25555",
  "fetcher": {
    "xmlrpc-host": "192.168.1.3"
  }
}

supervisor 配置

好吧这里并不需要参考上一篇文章的设置。

上一篇文章我们直接使用的是 /usr/local/bin/pyspider -c /pyspider/config.json 来运行,默认就是 ALL ,意思是将所有的模块都运行。

而现在,我们只是在 slave 中运行的,根据上面所说的,我们只需要运行 fetcher 和 processor 就好了,我顺便也把 phantomjs 也运行了吧,因为我指向的是127.0.0.1

这里我们的 supervisor 运行到了组的概念。

[group:pyspider]
programs=pyspider-fetcher,pyspider-processor,pyspider-phantomjs

[program:pyspider-fetcher]
command=/usr/local/bin/pyspider -c /pyspider/config.json fetcher
autorestart=true
user=pyspider
group=pyspider
directory=/pyspider
stopasgroup=true

[program:pyspider-processor]
command=/usr/local/bin/pyspider -c /pyspider/config.json processor
autorestart=true
user=pyspider
group=pyspider
directory=/pyspider
stopasgroup=true

[program:pyspider-phantomjs]
command=/usr/local/bin/pyspider -c /pyspider/config.json phantomjs
autorestart=true
user=pyspider
group=pyspider
directory=/pyspider
stopasgroup=true

同样将配置文件写入到 /etc/supervisor/conf.d/pyspider.conf ,写入后,运行 supervisorctl reload 刷新配置,即会自动运行。

测试

运行好 slave 后,我担心的就是,他会不会没有运行成功呢?

有两种方法可以检验,一是看 supervisor 的运行日志,如果你看到有信息的话就说明成功了;二我就是爬一个我可控的站,然后去看日志。

很明显我现在要讲的是第二种方法。

#!/usr/bin/env python
# -*- encoding: utf-8 -*-
# Created on 2015-06-11 13:24:29
# Project: imlonghao

from pyspider.libs.base_handler import *

class Handler(BaseHandler):
    crawl_config = {
    }

    def on_start(self):
        for i in range(1,11111):
            self.crawl('https://imlonghao.com/%s.html' % str(i), callback=self.detail_page)

    @config(priority=2)
    def detail_page(self, response):
        return {
            "url": response.url,
            "title": response.doc('title').text(),
        }

我新创建了一个新的 project 来跑我自己的博客,然后我用 tcpdump 来看连接(好吧其实我应该看 Nginx 日志的)

效果如下:

[email protected]:~# tcpdump -i eth0 -tnn dst port 443 -c 1000 | awk -F"." '{print $1"."$2"."$3"."$4}' | sort | uniq -c | sort -nr |head -20
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
1000 packets captured
1006 packets received by filter
0 packets dropped by kernel
    492 IP *.*.*.221
    463 IP *.*.*.203

我们可以看到目前我的 master 和一台 slave 都是正常运行的了,并且两台在相同时间内的请求数差别不大,应该是正常运行了!

后记

安装好 slave 后,由于我用的是 iwStack 的云 VPS ,我可以将这台安装好的 VPS 配置成模板,如果遇到需要大量 VPS 的话,我只需要新建一台 VPS 并且使用这个模板即可,根本不需要再 SSH 连接进去进行其他的操作,也是非常简单的了。

DigitalOcean 和 Vultr 等同理

若有不对,敬请指出