接到一个爬虫任务,项目比较巨大,原来想用 Requests 配合正则做爬虫。后来得知了 pyspider 这个神器,才知道之前的想法 low 爆了。 按照 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 的队列中。 队列的另一端是数据库写入脚本,该脚本一条一条地从队列中取出消息,然后一个字段一个字段地插入到数据库,不用担心数据库写入时的冲突问题了。
|