PySpider踩坑记

作者: 祗談風月 | 来源:发表于2018-05-19 18:18 被阅读33次

    没有用过框架写爬虫,有人推荐了pyspider,我也没有和别的框架比对,就直接上手先用了。

    使用感受

    框架的封装性带来的优缺点在这里显示的淋漓精致...

    优点

    • 爬虫该有的都有了——网站入口;分页查询;解析网页;保存数据(还可以发消息)
    • 爬取时间间隔设置
    • 网页有效期维护
    • 爬取多线程设置
    • 对无头浏览器phantomjs的支持
    • 支持web ui上调试代码,需求不高的情况下类似在线编写代码
    • 提供了一键式获取css selector按钮,方便获取元素

    缺点

    • 本身不支持xpath方式解析
    • 使用回调方式来运行pipline,框架把控回调的执行,不够灵活,多层爬取时需要递归方式调用index_page,导致代码可能比较混乱
    • 提供的css selector提取器实用性一般,有一些复杂一点的拿不到
    • 任务运行/关闭很多时候令人迷惑
    • 对phantomjs的调用会对电脑cpu造成较大压力,据说是每次爬取都会启停一个phantomjs线程
    • web ui没有删除任务的选项,也没有清空爬取到的数据的选项
    • web ui的方式编码很费劲,我都是在IDE里面写好再复制上去
    • web ui不能像本地IDE一样识别新加入的包

    开发环境

    • python 3.6
    • pyspider 0.3.10

    安装启动

    参考官方Quick start可以很快上手: http://docs.pyspider.org/en/latest/Quickstart/

    # 一键安装pyspider
    pip install pyspider
    
    # 会在当前目录下建立data文件夹,保存任务相关代码,数据,任务进度等,如果换了路径启动就找不到了
    # 启动所有pyspider的组件,更多命令可以 pyspider help
    pyspider all 
    

    之后可以在 http://localhost:5000/ 看到启动了一个web ui,用来调试和运行pyspider的

    默认没有phantomjs,需要自己手动下载,然后配置{phantomjs_home/bin}路径到本机的环境变量,重启pyspider即可,注意要确认环境变量生效pyspider才能找到phantomjs。

    框架机制补充

    这里不一一罗列API了,主要讲我使用过程中碰到的一些特性

    from pyspider.libs.base_handler import *
    
    
    # pyspider的实现类需要继承BaseHandler,实现基本的几个接口
    class Handler(BaseHandler):  
        # 放一些self.crawl函数请求页面时的http请求头:referer,user-agent等
        crawl_config = {
        }
    
        # pipline的起点,这里请求的url最好是下文请求的父级url,否则爬取不了,我出过这样的问题,不知道是不是就是这样的机制
        # 只会执行一次,即如果on_start中有循环self.crawl,只会执行最后一次
        @every(minutes=24 * 60)  # 任务运行之间的间隔,用来不停的补采过期的数据
        def on_start(self):  
            # 爬取网页的核心函数,支持phantomjs解析,需配置fetch_type='js'
            self.crawl('http://scrapy.org/', callback=self.index_page)
    
        #  理论上是爬取分页的,但是如果有多层爬取也得靠index_page,需要在self.crawl中设置callback为index_page,形成递归,当然如果逻辑不通,用if-else分开即可,如果有人发现了更好的多层爬取的方式,拜托告诉我一声...
        @config(age=10 * 24 * 60 * 60)  # 爬取结果的有效期
        def index_page(self, response):
            # response.doc得到一个pyquery对象,和操作一个jquery对象相似,相关api看pyquery官网即可
            for each in response.doc('a[href^="http"]').items():
                self.crawl(each.attr.href, callback=self.detail_page)
    
        # 输出解析结果,如果用默认的sqlite,只能return一个dict,如果自己复写了on_result,就可以随意返回了
        @config(priority=2)
        def detail_page(self, response):
            return {
                "url": response.url,
                "title": response.doc('title').text(),
            }
    
        # 自定义结果处理方式
        def on_result(self, result):
            ...
            # 处理结果
            ...
    
        # task结束时调用
        def on_finished(self, response, task):
            ...
            # 任务关闭时的操作,可以用来关数据库连接之类
            ...
    
    

    启停任务

    • 在 localhost:5000 的web ui上修改状态即可
    • running和debug状态没有区别
    • rate/brust rate表示每秒爬取的网页个数,brust理解为并发数

    其他

    • pyspider自带了sqlite,但是要保存到别的数据库需要自己建连接,插入,关连接,相关的包自己导入后重启pyspider即可
    • 可以通过web ui的result的on_process项的内容做简单的debug
    • phantomjs的环境变量有一种可以立即生效的办法,不赘述啦
    • web ui中看似好的缩进可能是不合法的,复制出来格式化好了再粘贴回去

    参考

    相关文章

      网友评论

        本文标题:PySpider踩坑记

        本文链接:https://www.haomeiwen.com/subject/pqjadftx.html