51Testing软件测试论坛

标题: Pyspider快速上手 [打印本页]

作者: 测试积点老人    时间: 2018-12-3 16:23
标题: Pyspider快速上手
本帖最后由 测试积点老人 于 2018-12-3 16:25 编辑

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

pyspider是作者之前做的一个爬虫架构的开源化实现。主要的功能需求是:
        1.抓取、更新调度多站点的特定的页面
        2.需要对页面进行结构化信息提取
        3.灵活可扩展,稳定可监控

而这也是绝大多数python爬虫的需求 —— 定向抓取,结构化化解析。但是面对结构迥异的各种网站,单一的抓取模式并不一定能满足,灵活的抓取控制是必须的。为了达到这个目的,单纯的配置文件往往不够灵活,于是,通过脚本去控制抓取是我最后的选择。

而去重调度,队列,抓取,异常处理,监控等功能作为框架,提供给抓取脚本,并保证灵活性。最后加上web的编辑调试环境,以及web任务监控,即成为了这套框架。

pyspider的设计基础是:以python脚本驱动的抓取环模型爬虫

通过python脚本进行结构化信息的提取,follow链接调度抓取控制,实现最大的灵活性

开发快速上手:
通过web化的脚本编写、调试环境。web展现调度状态

抓取环模型成熟稳定,模块间相互独立,通过消息队列连接,从单进程到多机分布式灵活拓展

主要函数解释:


以爬取财经网财经热评为例:启动函数on_start:
  1.   @every(minutes=24 * 60)
  2.     def on_start(self):
  3.         self.crawl('http://comments.caijing.com.cn/hottopics/', callback=self.index_page)
复制代码
调用内置函数self.crawl,生成response对象,传给回调函数index_page
  1. @config(age=10 * 24 * 60 * 60)
  2.     def index_page(self, response):
  3.         # 选择所有href属性以http开头的a标签
  4.         for each in response.doc('a[href^="http"]').items():
  5.             # 判断该标签是否是《新闻评论》详情的url
  6.             if re.match('http://comments.caijing.com.cn/\d+', each.attr.href, re.U):
  7.                 # 再次发送请求,回调函数为最终的解析函数
  8.                 self.crawl(each.attr.href, callback=self.detail_page)
复制代码
进入解析方法,解析页面。response.etree是内置方法,它生成一个html的etree对象
  1. @config(priority=2)
  2.     def detail_page(self, response):
  3.         data = {
  4.             "url": response.url,
  5.             # 调用xpath提取title
  6.             "title": response.etree.xpath('//*[@id="cont_title"]/text()')[0]
  7.         }
  8.         return data
复制代码
全部代码:
  1. import re
  2. import json

  3. class Handler(BaseHandler):
  4.     crawl_config = {
  5.     }

  6.     @every(minutes=24 * 60)
  7.     def on_start(self):
  8.         self.crawl('http://comments.caijing.com.cn/hottopics/', callback=self.index_page, force_update=True)

  9.     @config(age=10 * 24 * 60 * 60)
  10.     def index_page(self, response):
  11.         for each in response.doc('a[href^="http"]').items():
  12.             if re.match('http://comments.caijing.com.cn/\d+', each.attr.href, re.U):
  13.                 self.crawl(each.attr.href, callback=self.detail_page)
  14.             elif re.match('http://comments.caijing.com.cn/hottopics/\d+.shtml', each.attr.href, re.U):
  15.                 self.crawl(each.attr.href, callback=self.index_page, force_update=True)

  16.     @config(priority=2)
  17.     def detail_page(self, response):
  18.         etree = response.etree
  19.         print type(etree.xpath('//*[@id="cont_title"]/text()')[0].encode('utf-8'))
  20.         data = {
  21.             "url": response.url,
  22.             "title": etree.xpath('//*[@id="cont_title"]/text()')[0].encode('utf-8'),
  23.             "content":'\n'.join(etree.xpath('//*[@id="the_content"]/p/text()')).encode('utf-8'),
  24.             "post_time":etree.xpath('//*[@id="pubtime_baidu"]/text()')[0].encode('utf-8'),
  25.             "source":etree.xpath('//span[@id="source_baidu"]//text()')[0].encode('utf-8'),
  26.         }
  27.         return data

  28.     def on_result(self, result):
  29.         if not result:
  30.             return
  31.         sql = SQL()
  32.         sql.replace('article', result)
复制代码






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