塔游网

用 Docker Compose 部署 PySpider

2021-06-30 09:33:12   小编:佚名

PySpider 是一个国人编写的强大的网络爬虫系统并带有强大的 WebUI。采用 Python 语言编写,分布式架构,支持多种数据库后端,强大的 WebUI 支持脚本编辑器,任务监视器,项目管理器以及结果查看器。

上面这段是从「PySpider 中文网」摘录的。总而言之,它就是一个 All-in-one 的爬虫系统,比 Scrapy 强的地方,主要就是上手更容易,打开 web 页面就可以开始写爬虫。但「开包即食」这一点,仅限于 demo 阶段,比如在 http://demo.pyspider.org 试用一下。真正到自己用的时候,还是要考虑一个部署的问题。尤其是要充分利用它的分布式架构的时候,怎么部署更是一个避不过去的问题。

我之前做过一个 side project,功能是从国内各大视频网站抓取动漫新番,如果发现更新,就推送通知到 iOS 客户端,iOS 客户端仅展示订阅的动漫列表,观看还需要跳转到各官方应用去。

做这个的动机是现在各大视频网站的版权竞争,导致要追一季新番,不得不来回切换各个视频网站,我又不想打开一堆通知,让它们给我推垃圾信息。所以就搞一个只推送动漫更新的应用吧。

这个项目爬虫端已经完成,iOS 客户端也提交了审核,然而就是审核没有通过,没过的原因有以下三点:

后来发现自己已经有点脱宅了,也就没有再去和审核人员争论了,项目就这么流产,和许多其他 side project 一样。

下面是我在做这个 side project 的时候,部署 PySpider 的方案。

Docker + LeanCloud

现在要部署一个 web 项目,用 Docker 已经是首选了,可以节约不少时间。iOS 后端用现成的 LeanCloud 来做,不用写后端代码,又可以节约不少时间。

要用 LeanCloud,需要引入 LeanCloud 的 SDK,而 binux/pyspider 这个 image 并不包含。所以需要自己 build 一个 image 了。方法就是写一个 Dockerfile,内容如下:

FROM binux/pyspider:latest
MAINTAINER suosuopuo <suosuopuo@gmail.com># include the LeanCloud SDK
RUN pip install leancloud-sdk

然后执行 docker build -t my/pyspider – < Dockerfile,如果需要用到 LeanCloud SDK,只要用 my/pyspider 代替 binux/pyspider 就好了。

数据库和消息队列

尽管最终结果放在 LeanCloud 上,但 PySpider 各个组件运行还是需要数据库支持的。这部分主要参考这个 Deployment of demo.pyspider.org。数据库是 postgresql,消息队列用 redis。

数据库和消息队列手动用 docker 启动,不用 docker-compose 管理,这和 Deployment of demo.pyspider.org 也是一致的。

启动就两条命令:

docker run –name redis -d -p 6379:6379 redisdocker run –name postgres -v /data/postgres/:/var/lib/postgresql/data -d -e POSTGRES_PASSWORD=”” postgres

数据库和用户需要手动创建:

docker exec -it postgres bash

然后输入:

psql -U postgresCREATE USER myname  WITH PASSWORD ‘mypassword’;CREATE DATABASE taskdb WITH OWNER= myname LC_COLLATE=’en_US.utf8′ LC_CTYPE=’en_US.utf8′ ENCODING=’UTF8′ TEMPLATE=template0;CREATE DATABASE projectdb WITH OWNER= myname LC_COLLATE=’en_US.utf8′ LC_CTYPE=’en_US.utf8′ ENCODING=’UTF8′ TEMPLATE=template0;CREATE DATABASE resultdb WITH OWNER= myname LC_COLLATE=’en_US.utf8′ LC_CTYPE=’en_US.utf8′ ENCODING=’UTF8′ TEMPLATE=template0;

Docker Compose

除了数据库和消息队列,其他组件都用 docker-compose 来管理了,
docker-compose.yml 的内容主要参考这个 Running pyspider with Docker,和这个 Deployment of demo.pyspider.org。

主要是让各个组件连接外部的数据库和消息队列,限制一下内存占用,另外设置一个 WebUI 的用户名和密码。Result worker 要使用之前 build 的 image,因为它需要用到 LeanCloud。

然后 docker-compose up -d 就可以启动各组件了。

phantomjs:
  image: binux/pyspider:latest
  command: phantomjs
  mem_limit: 256m
  restart: always
result:
  image: my/pyspider
  external_links:
    – postgres
    – redis
  volumes:
    – ./share:/opt/share
  working_dir: /opt/share
  command: ‘–taskdb “sqlalchemy+postgresql+taskdb://username:password@postgres/taskdb”  –projectdb “sqlalchemy+postgresql+projectdb://username:password@postgres/projectdb” –resultdb “sqlalchemy+postgresql+resultdb://username:password@postgres/resultdb” –message-queue “redis://redis:6379/1” result_worker –result-cls=resultWorker.VResultWorker’
  mem_limit: 128m
  restart: always
processor:
  image: binux/pyspider:latest
  external_links:
    – postgres
    – redis
  command: ‘–projectdb “sqlalchemy+postgresql+projectdb://username:password@postgres/projectdb” –message-queue “redis://redis:6379/1” processor’
  mem_limit: 128m
  restart: always
fetcher:
  image: binux/pyspider:latest
  external_links:
    – redis
  links:
    – phantomjs
  command : ‘–message-queue “redis://redis:6379/1” –phantomjs-proxy “phantomjs:80” fetcher –xmlrpc’
  mem_limit: 128m
  restart: always
scheduler:
  image: binux/pyspider:latest
  external_links:
    – postgres
    – redis
  command: ‘–taskdb “sqlalchemy+postgresql+taskdb://username:password@postgres/taskdb”  –projectdb “sqlalchemy+postgresql+projectdb://username:password@postgres/projectdb” –resultdb “sqlalchemy+postgresql+resultdb://username:password@postgres/resultdb” –message-queue “redis://redis:6379/1” scheduler’
  restart: always
webui:
  image: binux/pyspider:latest
  external_links:
    – postgres
    – redis
  links:
    – scheduler
    – phantomjs
  command: ‘–taskdb “sqlalchemy+postgresql+taskdb://username:password@postgres/taskdb”  –projectdb “sqlalchemy+postgresql+projectdb://username:password@postgres/projectdb” –resultdb “sqlalchemy+postgresql+resultdb://username:password@postgres/resultdb” –message-queue “redis://redis:6379/1” webui –need-auth –username ui_username –password ui_password’
  ports:
    – “5000:5000”

ResultWorker

关于 result worker,官方文档并没有给出 demo,我这里贴一下我的 result worker。首先初始化 LeanCloud SDK,每次抓到数据的时候,去 LeanCloud 查询是不是已经存在同名的动漫(一个动漫可以有多个别名)。如果不存在,就创建这个别名,如果已经存在,就继续执行其他的逻辑(简洁起见,不全部贴出了)。

resultWorker.py 放在和 docker-compose.yml 相同的位置,在启动 result worker 的时候已经通过选项指定自定义的 VResultWorker

#!/usr/bin/env python
# -*- encoding: utf-8 -*-
# vim: set et sw=4 ts=4 sts=4 ff=unix fenc=utf8:
# Author: suosuopuo<suosuopuo@gmail.com>
#
# Created on 2017-06-15 15:37:46from pyspider.result import ResultWorker
import leancloud
from datetime import datetimeappKey = ”
appID  = ”class VResultWorker(ResultWorker):
  def __init__(self, resultdb, inqueue):
    self.resultdb = resultdb
    self.inqueue = inqueue
    self._quit = Falseleancloud.init(appID, appKey)
    leancloud.use_region(‘CN’)def on_result(self, task, result):
    if result[‘type’] == ‘anime-update’:
      self.handle_anime_update(task, result)def handle_anime_update(self, task, result):
    title = result[‘title’]try:
      alias_query = leancloud.Query(‘Alias’)
      alias_query.include(‘anime’)
      alias_query.equal_to(‘title’, title)alias = alias_query.first()
    except leancloud.LeanCloudError as e:
      if e.code == 101:
        Alias = leancloud.Object.extend(‘Alias’)
        Anime = leancloud.Object.extend(‘Anime’)alias = Alias()
        alias.set(‘title’, title)anime = Anime()
        anime.set(‘title’, title)
        anime.set(‘area’, result[‘area’])
        anime.set(‘cover’, result[‘cover’])
        anime.set(‘weekday’, result[‘weekday’])
        anime.set(‘ep_num’, 12)
        anime.set(‘is_finished’, result[‘is_finished’])
        anime.set(‘verified’, False)anime.save(fetch_when_save = True)alias.set(‘targetAnime’, anime)
        alias.save()
      return…

还有话说

我是很喜欢这样的「全家桶」式的方案的,可以快速地试验一些想法,但是很遗憾 PySpider 的代码已经很久没有更新了。好在目前为止 PySpider 还足够强大。

我没有解释每一条命令、每一个选项,因为这不是 PySpider 的文档,如果需要更详细的解释,还是需要去挖掘官方文档。

写这篇的时间距离写这个 side project 已经隔了几个月。我也懒到没有去再次验证各个配置和命令,所以「仅供参考」。

另外提醒一下,如果有人也打算用 LeanCloud 做后端,需要注意 LeanCloud 是有访问次数限制的。可以根据抓取的页面特点,用 age, itag等功能减少对 LeanCloud 的访问次数。

不过就算没有访问次数限制,对一个远程服务高频访问,也不是好的策略。

  • 用了一些版权图片

  • 在 webView 预览动漫的时候,某视频网站乱跳红包

  • 审核人员不看动漫,把鸣人的儿子当成了我山寨的一个动漫形象。


相关游戏

相关文章

香港高防服务器哪个好? Flask 与 Tornado 中的路由定义 Ansible服务部署与使用 ansible-playbook剧本 使用virtualenv搭建Python下的Flask开发环境,ubu测试有效 Centos 7 Java配置maven+jenkins+git(svn)+tomcat自动编译和部署(持续集成) Git常用命令总结

最新游戏

网友评论