分佈式部署pyspider

0. 引言

pyspider:一個國人編寫的強大的網絡爬蟲系統並帶有強大的WebUI。採用Python語言編寫,分佈式架構,支持多種數據庫後端,強大的WebUI支持腳本編輯器,任務監視器,項目管理器以及結果查看器。python

最近有項目須要爬蟲支撐,須要抓取的站點繁多,但數據量較小,決定使用pyspider來作數據抓取。考慮到單機性能和可用性問題,最後使用Docker分佈式部署了pyspider,到目前爲止的半年時間裏運行良好。本文主要介紹一下我搭建流程,以及遇到的問題以及解決辦法。linux

1. 部署說明

pyspider的框架設計在官方文檔中已經介紹的很清楚了,"以去重調度,隊列,抓取,異常處理,監控等功能做爲框架,提供給抓取腳本,並保證靈活性。最後加上webUI的編輯調試環境,以及web任務監控,即成爲了這套框架。 git

pyspider架構設計圖.png
pyspider中由 scheduler負責任務調度, fetcherprocessor負責數據抓取和解析輸出。除了 scheduler是單點部署, fetcherprocessorwebui均可以多實例分佈式部署。所以咱們能夠將 scheduler部署在一臺機器上,負責全部爬蟲任務的調度, fetcherprocessor部署到其餘機器進行數據抓取和解析輸出。

2. 構建pyspider鏡像

事實上做者在DockerHub上提供了基於python2的鏡像,由於有項目須要我就從新構建了基於python3的鏡像,並引入一些本身的類庫。DockerFile以下:github

FROM python:3.6

MAINTAINER LieFeng  "buqx@foxmail.com"

# copy本身的一些代碼到環境中

#$COPY . /spider

#WORKDIR /spider

# install phantomjs

RUN mkdir -p /opt/phantomjs \     && cd /opt/phantomjs \

    && wget -O phantomjs.tar.bz2 https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-2.1.1-linux-x86_64.tar.bz2 \

    && tar xavf phantomjs.tar.bz2 --strip-components 1 \

    && ln -s /opt/phantomjs/bin/phantomjs /usr/local/bin/phantomjs \

    && rm phantomjs.tar.bz2

RUN ["pip","install","wsgidav==2.4.1"] 
RUN ["pip","install","pyspider"] 
RUN ["pip","install","sqlalchemy"] 
RUN ["pip","install","redis"] 
RUN ["pip","install","psycopg2"] 
VOLUME ["/opt/pyspider"] 
ENTRYPOINT ["pyspider"] 
EXPOSE 5000 23333 24444 25555

複製代碼

build鏡像,我把鏡像命名爲buqx/pyspider,後面的部署都是基於這個鏡像來作的。web

3. 部署主節點

在部署說明裏咱們能夠將scheduler部署在一臺機器上,負責全部爬蟲任務的調度。這臺機器我稱爲主節點,除了部署scheduler以外,我還將pyspider的project、task、result數據庫和消息隊列部署在這臺機器上。redis

3.1 部署數據庫和消息隊列

pyspider有三個數據庫(projectdb\taskdb\resultdb)和一個消息隊列,數據庫我使用了PostgreSQL,消息隊列使用Redis。咱們使用docker來部署它們。sql

  • 爲了使用統一的網絡接口,咱們首先使用docker 建立pyspider network。docker

     $ docker network create --driver bridge pyspider
    
    複製代碼
  • 使用docker部署PostgreSQL,這裏須要注意的是端口綁定的問題,postgres默認端口是5432,因此無論綁定到外部那個端口,docker容器內必定要使用5432端口,除非你手動修改了它shell

     $ docker run --network=pyspider --name postgres \
    
      -v ~/data/postgres/:/var/lib/postgresql/data  \
    
      -d -p $LOCAL_IP:5432:5432 -e POSTGRES_PASSWORD="" postgres
    
    複製代碼
  • 進入postgres容器,新建數據庫用戶spider,新建數據庫:projectdb、taskdb和resultdb數據庫

  • 使用docker部署Redis

     $ docker run --network=pyspider --name redis -d -p 6379:6379 redis
    
    複製代碼

3.2 部署scheduler

docker命令以下,其中buqx/pyspider 是我鏡像名稱,spider@192.168.34.203是數據庫用戶名和機器的內網IP

 $ docker run --network=pyspider --name scheduler -d -p 23333:23333 --restart=always buqx/pyspider --taskdb "sqlalchemy+postgresql+taskdb://spider@192.168.34.203:5431/taskdb" --resultdb "sqlalchemy+postgresql+resultdb://spider@192.168.34.203:5431/resultdb" --projectdb "sqlalchemy+postgresql+projectdb://spider@192.168.34.203:5431/projectdb" --message-queue "redis://192.168.34.203:6379/1" scheduler --inqueue-limit 5000 --delete-time 43200

複製代碼

3.3 驗證

完成上面的操做後,能夠在主節點上看到啓動了9個容器,以下圖。

image-主節點啓動容器示例圖.png
###4. 子節點部署

咱們經過docker-compose來編排fetcherwebuiprocessor容器,docker-compose.yml文件以下:

version: "2"

services:

 phantomjs:

 image: 'buqx/pyspider:latest'

 command: phantomjs

 cpu_shares: 256

 environment:

 - 'EXCLUDE_PORTS=5000,23333,24444'

 expose:

 - '25555'

 mem_limit: 256m

 restart: always

 phantomjs-lb:

 image: 'dockercloud/haproxy:latest'

 links:

 - phantomjs

 volumes:

 - ~/docker/volumes/docker.sock:/var/run/docker.sock

 restart: always

 fetcher:

 image: 'buqx/pyspider:latest'

 command: '--message-queue "redis://192.168.34.203:6379/1" --phantomjs-proxy "phantomjs:80" fetcher --xmlrpc'

 cpu_shares: 256

 environment:

 - 'EXCLUDE_PORTS=5000,25555,23333'

 links:

 - 'phantomjs-lb:phantomjs'

 mem_limit: 256m

 restart: always

 fetcher-lb:

 image: 'dockercloud/haproxy:latest'

 links:

 - fetcher

 volumes:

 - ~/docker/volumes/docker.sock:/var/run/docker.sock

 restart: always

 processor:

 image: 'buqx/pyspider:latest'

 command: '--projectdb "sqlalchemy+postgresql+projectdb://spider:123@192.168.34.203:5431/projectdb" --message-queue "redis://192.168.34.203:6379/1" processor'

 cpu_shares: 256

 mem_limit: 256m

 restart: always

 result-worker:

 image: 'buqx/pyspider:latest'

 command: '--taskdb "sqlalchemy+postgresql+taskdb://spider:123@192.168.34.203:5431/taskdb" --projectdb "sqlalchemy+postgresql+projectdb://spider:123@192.168.34.203:5431/projectdb" --resultdb "sqlalchemy+postgresql+resultdb://spider:123@192.168.34.203:5431/resultdb" --message-queue "redis://192.168.34.203:6379/1" result-worker'

 cpu_shares: 256

 mem_limit: 256m

 restart: always

 webui:

 image: 'buqx/pyspider:latest'

 command: '--phantomjs-proxy "phantomjs:25555" --taskdb "sqlalchemy+postgresql+taskdb://spider:123@192.168.34.203:5431/taskdb" --projectdb "sqlalchemy+postgresql+projectdb://spider:123@192.168.34.203:5431/projectdb" --resultdb "sqlalchemy+postgresql+resultdb://spider:123@192.168.34.203:5431/resultdb" --message-queue "redis://192.168.34.203:6379/1" webui --scheduler-rpc "http://192.168.34.203:23333/" '

 cpu_shares: 256

 environment:

 - 'EXCLUDE_PORTS=24444,25555,23333'

 ports:

 - '5288:5000'

 links:

 - 'fetcher-lb:fetcher'

 mem_limit: 256m

 restart: always

networks:

 default:

 external:

 name: pyspider

複製代碼

使用docker-compose up啓動全部容器,經過docker container ls查看啓動的容器,能夠看到下圖中的九容器正在運行(子節點機器上裝了portainer,圖是從portainer截取的),訪問http://子節點IP:5288/ 進入pyspider控制檯。

image-子節點啓動容器示例.png

5. 問題羅列(會不斷補充)

  • self.crawl 添加 fetch_type=‘js’ 參數,出現

    Traceback (most recent call last):
    
          File "/usr/local/lib/python2.7/dist-packages/pyspider/libs/base_handler.py", line 188, in run_task
    
            result = self._run_task(task, response)
    
          File "/usr/local/lib/python2.7/dist-packages/pyspider/libs/base_handler.py", line 167, in _run_task
    
            response.raise_for_status()
    
          File "/usr/local/lib/python2.7/dist-packages/pyspider/libs/response.py", line 190, in raise_for_status
    
            raise http_error
    
        HTTPError: 501 Server Error
    
    複製代碼

    解決:參考https://github.com/binux/pyspider/issues/432解決,修改compose file 在webui 的command 增長「--phantomjs-proxy "phantomjs:25555 」

    webui:
    
     image: 'buqx/pyspider:latest'
    
     command: '--phantomjs-proxy "phantomjs:25555" --taskdb "sqlalchemy+postgresql+taskdb://spider:123@192.168.34.203:5431/taskdb" --projectdb "sqlalchemy+postgresql+projectdb://spider:123@192.168.34.203:5431/projectdb" --resultdb "sqlalchemy+postgresql+resultdb://spider:123@192.168.34.203:5431/resultdb" --message-queue "redis://192.168.34.203:6379/1" webui --scheduler-rpc "http://192.168.34.203:23333/" '
    
     cpu_shares: 256
    
     environment:
    
     - 'EXCLUDE_PORTS=24444,25555,23333'
    
     ports:
    
     - '5288:5000'
    
     links:
    
     - 'fetcher-lb:fetcher'
    
     mem_limit: 256m
    
     restart: always
    
    複製代碼
相關文章
相關標籤/搜索