2019独角兽企业重金招聘Python工程师标准>>>
接到一个爬虫任务,项目比较巨大,原来想用 Requests 配合正则做爬虫。后来得知了 pyspider 这个神器,才知道之前的想法 low 爆了。pyspider GitHub
按照 GitHub 上的安装教程安装好以后,我们就可以通过 pyspider 命令来启动这个神器,然后在浏览器中打开 http://localhost:5000/ 就可以看到界面了。首先是一个 Dashboard,我们在这里可以创建爬虫项目,点击 Create 然后输入项目名就可以看到代码了。
关于项目的帮助可以看文档,在 GitHub 上可以找到该项目的 Docs 链接,我们现在上来直接看代码,我用中文做下注释。
from pyspider.libs.base_handler import *
# 引入 pyspider 的 base_handler,这个是用来当基类的。
# 以下就是我们写的类。
class Handler(BaseHandler):
crawl_config = {
}
# 这个是作为整个项目的全局参数的设置,比如 proxy。
@every(minutes=24 * 60)
# 这句话是定时启动的意思,这里就是说每一天启动一次。
# 以下为爬虫的入口
def on_start(self):
# 抓 http://scrapy.org/ 的页面,将返回的内容交给 index_page 函数来处理。
self.crawl('http://scrapy.org/', callback=self.index_page)
@config(age=10 * 24 * 60 * 60)
# 每十天重启一次
def index_page(self, response):
for each in response.doc('a[href^="http"]').items():
# 这里将 on_start 抓取 scrapy 首页的返回结果进行过滤,采用了 CSS 选择器选择了 href 的值为 http 开头的所有 a 标签。
# 此处循环内的 each 即为网页中的 a 标签。
self.crawl(each.attr.href, callback=self.detail_page)
# 再次调用 crawl 函数,对 a 标签的 href 中目标网址进行抓取,返回给 detail_page 函数来处理。
def detail_page(self, response):
return {
"url": response.url,
# 返回 url 和网页 title 组成的字典。
"title": response.doc('title').text(),
}
作者自己写的中文教程里面已经把很多操作都讲清楚了,我就不抄来了。
对于 ajax 请求的内容可以直接 crawl 那个 ajax 请求的 URL,返回的 response.json 就变成了一个 Python 的字典。
当每个函数 return 的时候,return 的内容被传递到了 BaseHandler 这个基类中的 on_result 函数,其代码如下:
def on_result(self, result):
"""Receiving returns from other callback, override me."""
if not result:
return
assert self.task, "on_result can't outside a callback."
if self.is_debugger():
# 当在浏览器中调试运行时:
pprint(result)
if self.__env__.get('result_queue'):
# 当被当作任务执行时,即在 Dashboard 中设置为 RUNNING 时,
self.__env__['result_queue'].put((self.task, result))
然后我们就可以通过重写 on_result 函数,来将所有函数的返回值进行处理,再输出到 RabbitMQ 的队列中。
队列的另一端是数据库写入脚本,该脚本一条一条地从队列中取出消息,然后一个字段一个字段地插入到数据库,不用担心数据库写入时的冲突问题了。