51Testing软件测试论坛

 找回密码
 (注-册)加入51Testing

QQ登录

只需一步,快速开始

微信登录,快人一步

手机号码,快捷登录

查看: 1447|回复: 0
打印 上一主题 下一主题

Pyspider快速上手

[复制链接]
  • TA的每日心情
    无聊
    前天 09:06
  • 签到天数: 530 天

    连续签到: 2 天

    [LV.9]测试副司令

    跳转到指定楼层
    1#
    发表于 2018-12-3 16:23:07 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
    本帖最后由 测试积点老人 于 2018-12-3 16:25 编辑

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

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

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

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

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

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

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

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

    主要函数解释:
    • def on_start(self) 方法是入口代码。当在web控制台点击run按钮时会执行此方法。
    • self.crawl(url, callback=self.index_page)这个方法是调用API生成一个新的爬取任务,这个任务被添加到待抓取队列。
    • def index_page(self, response) 这个方法获取一个Response对象。 response.doc是pyquery对象的一个扩展方法。pyquery是一个类似于jQuery的对象选择器。
    • def detail_page(self, response)返回一个结果集对象。这个结果默认会被添加到resultdb数据库(如果启动时没有指定数据库默认调用sqlite数据库)。你也可以重写on_result(self,result)方法来指定保存位置。
    • 更多知识:
    • @every(minutes=24*60, seconds=0) 这个设置是告诉scheduler(调度器)on_start方法每天执行一次。
    • @config(age=10 * 24 * 60 * 60) 这个设置告诉scheduler(调度器)这个request(请求)过期时间是10天,10天内再遇到这个请求直接忽略。这个参数也可以在self.crawl(url, age=10*24*60*60) 和 crawl_config中设置。
    • @config(priority=2) 这个是优先级设置。数字越小越先执行。


    以爬取财经网财经热评为例:启动函数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)
    复制代码

    分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
    收藏收藏
    回复

    使用道具 举报

    本版积分规则

    关闭

    站长推荐上一条 /1 下一条

    小黑屋|手机版|Archiver|51Testing软件测试网 ( 沪ICP备05003035号 关于我们

    GMT+8, 2024-11-23 16:57 , Processed in 0.069838 second(s), 23 queries .

    Powered by Discuz! X3.2

    © 2001-2024 Comsenz Inc.

    快速回复 返回顶部 返回列表