51Testing软件测试论坛

标题: pyspider + RabbitMQ 使用记 - 上 [打印本页]

作者: 老白的释然    时间: 2019-3-7 14:19
标题: pyspider + RabbitMQ 使用记 - 上

接到一个爬虫任务,项目比较巨大,原来想用 Requests 配合正则做爬虫。后来得知了 pyspider 这个神器,才知道之前的想法 low 爆了。

按照 GitHub 上的安装教程安装好以后,我们就可以通过 pyspider 命令来启动这个神器,然后在浏览器中打开 http://localhost:5000/ 就可以看到界面了。首先是一个 Dashboard,我们在这里可以创建爬虫项目,点击 Create 然后输入项目名就可以看到代码了。

关于项目的帮助可以看文档,在 GitHub 上可以找到该项目的 Docs 链接,我们现在上来直接看代码,我用中文做下注释。

  1. from pyspider.libs.base_handler import *
  2. # 引入 pyspider 的 base_handler,这个是用来当基类的。
  3. # 以下就是我们写的类。
  4. class Handler(BaseHandler):
  5.     crawl_config = {
  6.     }
  7.     # 这个是作为整个项目的全局参数的设置,比如 proxy。
  8.     @every(minutes=24 * 60)
  9.     # 这句话是定时启动的意思,这里就是说每一天启动一次。
  10.     # 以下为爬虫的入口
  11.     def on_start(self):
  12.     # 抓 http://scrapy.org/ 的页面,将返回的内容交给 index_page 函数来处理。
  13.         self.crawl('http://scrapy.org/', callback=self.index_page)

  14.     @config(age=10 * 24 * 60 * 60)
  15.     # 每十天重启一次
  16.     def index_page(self, response):
  17.         for each in response.doc('a[href^="http"]').items():
  18.         # 这里将 on_start 抓取 scrapy 首页的返回结果进行过滤,采用了 CSS 选择器选择了 href 的值为 http 开头的所有 a 标签。
  19.         # 此处循环内的 each 即为网页中的 a 标签。
  20.             self.crawl(each.attr.href, callback=self.detail_page)
  21.             # 再次调用 crawl 函数,对 a 标签的 href 中目标网址进行抓取,返回给 detail_page 函数来处理。

  22.     def detail_page(self, response):
  23.         return {
  24.             "url": response.url,
  25.             # 返回 url 和网页 title 组成的字典。
  26.             "title": response.doc('title').text(),
  27.         }
复制代码

作者自己写的中文教程里面已经把很多操作都讲清楚了,我就不抄来了。

对于 ajax 请求的内容可以直接 crawl 那个 ajax 请求的 URL,返回的 response.json 就变成了一个 Python 的字典。

当每个函数 return 的时候,return 的内容被传递到了 BaseHandler 这个基类中的 on_result 函数,其代码如下:

  1. def on_result(self, result):
  2.         """Receiving returns from other callback, override me."""
  3.         if not result:
  4.             return
  5.         assert self.task, "on_result can't outside a callback."
  6.         if self.is_debugger():
  7.         # 当在浏览器中调试运行时:
  8.             pprint(result)
  9.         if self.__env__.get('result_queue'):
  10.         # 当被当作任务执行时,即在 Dashboard 中设置为 RUNNING 时,
  11.             self.__env__['result_queue'].put((self.task, result))
复制代码

然后我们就可以通过重写 on_result 函数,来将所有函数的返回值进行处理,再输出到 RabbitMQ 的队列中。

队列的另一端是数据库写入脚本,该脚本一条一条地从队列中取出消息,然后一个字段一个字段地插入到数据库,不用担心数据库写入时的冲突问题了。



作者: Miss_love    时间: 2020-12-30 18:05
支持分享




欢迎光临 51Testing软件测试论坛 (http://bbs.51testing.com/) Powered by Discuz! X3.2