美文网首页爬虫菜鸟Python 爬虫专栏
python爬虫的最佳实践(七)--pyspider框架的使用

python爬虫的最佳实践(七)--pyspider框架的使用

作者: Darkeril | 来源:发表于2016-05-05 19:52 被阅读9063次

    Ps:惯例ps环节,经过前面几章的学习,写一些简单的爬虫已经是手到擒来了吧。这章我们看看如何使用pyspider框架来写爬虫~

    环境配置

    在这之前简单介绍一下为什么选择这个框架:

    1. 这个框架是共和国人民写的(最强大的理由,没有之一)。
    2. 其次,有webUi的界面,如果你有服务器,那么随时随地都可以编写爬虫,在线调试的机制也做得很好。
    3. 多任务并行,健全的任务管理机制。
    4. 支持各种主流数据库。

    建议大家去看看文档,因为我这里只能介绍少部分功能,后续得还需要大家自己在使用的时候自行挖掘~pyspider文档

    • mac环境
      mac环境是很好配置的,只需要打开你的pycharm,然后直接输入pyspider安装即可~
      或者在终端pip install pyspider
    1.png
    • windows环境
      同mac环境,最好直接在pycharm中安装

    • linux环境
      因为这个框架一般都是在linux服务器上运行的,本机对框架的需求不大。
      1.ubuntu系统:
      apt-get install python-dev python-distribute libcurl4-openssl-dev libxml2-dev libxslt1-dev python-lxml
      安装上述的依赖环境,等待安装完成后执行pip install pyspider
      这样就安装完成了
      2.centos系统
      centos的话建议使用7系列的版本,这样py直接是2.7,否则还得自己安装py2.7以上的版本。
      安装依赖yum install -y gcc ruby-devel libxml2 libxml2-devel libxslt libxslt-devel
      然后同样的pip install pyspider
      即可完成安装

    在终端输入pyspider启动框架,进入http://localhost:5000/,如图所示:

    2.png

    这样就可以开始使用了~

    代码预览

    import re
    from pyspider.libs.base_handler import *
    
    class Handler(BaseHandler):
    
        @every(minutes=24 * 60)
        def on_start(self):
            self.crawl('http://www.imdb.com/search/title?count=100&title_type=feature,tv_series,tv_movie&ref_=nv_ch_mm_1', callback=self.index_page)
    
        @config(age=24 * 60 * 60)
        def index_page(self, response):
            for each in response.doc('a[href^="http"]').items():
                if re.match("http://www.imdb.com/title/tt\\d+/$", each.attr.href):
                    self.crawl(each.attr.href, callback=self.detail_page)
            self.crawl([x.attr.href for x in response.doc('#right a').items()], callback=self.index_page)
    
        @config(priority=2)
        def detail_page(self, response):
            return {
                "url": response.url,
                "title": response.doc('.header > [itemprop="name"]').text(),
                "rating": response.doc('.star-box-giga-star').text(),
                "director": [x.text() for x in response.doc('[itemprop="director"] span').items()],
            }
    

    代码剖析

    原谅博主偷了个懒,这段代码不是博主自己敲的,主要是下班回家写博客确实很累,而且这段代码在pyspider的官方demo,运行情况如下,用来做入门很不错~


    3.png

    好了,不说废话了。这次我们的目标是IMDb,非常有名的电影资料网站。首先,我们看到这段代码是否觉得和我们上次看到的unittest结构很类似?没错,首先,我们创建的class Handler继承pyspider的BaseHandler。程序的入口是on_start()函数,这段代码没有写crawl_config,一般如果 网站反爬虫机制很强的话,会带上crawl_config,结构如下:

    crawl_config = {
            "headers" : headers,
            "timeout" : 1000,
            "cookies" : Cookie
            "proxy" : 192.168.1.1:8888
        }
    

    这个我们先简单提一下,在随后的课程再详细介绍。

    我们注意到在on_start()函数上方有这样一段代码@every(minutes=24 * 60),这是告诉scheduler(调度器)每天调度一次on_start()函数。

    self.crawl('http://www.imdb.com/search/title?count=100&title_type=feature,tv_series,tv_movie&ref_=nv_ch_mm_1',callback=self.index_page)
    

    crawl()函数的两个参数,前一个指的是url,后一个指的是回调函数,也就是执行完请求之后调用的函数。

    接下来回调指向了index_page()
    @config(age=24 * 60 * 60)
    这个设置代表了在一天之内忽略已经请求过的网站,一般都会设置的比every的时间长一点,保证少做重复工作,但是这样写也没有问题,因为我们扒的网站信息是在不断更新的,并不是一成不变的。crawl会返回一个response对象,所有的返回信息都在这个对象里面。

    for each in response.doc('a[href^="http"]').items():
            if re.match("http://www.imdb.com/title/tt\\d+/$", each.attr.href):
                  self.crawl(each.attr.href, callback=self.detail_page)
            self.crawl([x.attr.href for x in response.doc('#right a').items()], callback=self.index_page)
    

    response.doc是一个PyQuery对象,支持Css Selector。
    上面第一行代码找出返回网页源代码里面所有的网页链接,然后通过re(python自带的正则模块),匹配出所有格式为http://www.imdb.com/title/tt开头后面跟着若干数字的网页。如http://www.imdb.com/title/tt3040964/
    然后挨个请求self.crawl(each.attr.href, callback=self.detail_page),回调为detail_page

    最后一行代码是一个递归的调用,就是如果这一页有翻译按钮,那么久请求下一页并递归调用index_page()函数,这样就可以把网页中所有的电影全部抓取下来。

    return {
                "url": response.url,
                "title": response.doc('.header > [itemprop="name"]').text(),
                "rating": response.doc('.star-box-giga-star').text(),
                "director": [x.text() for x in response.doc('[itemprop="director"] span').items()],
            }
    

    detail_page函数是用来吧结果储存在数据库中的,如果我们需要对数据进行过滤,还有on_result(self, result)函数,它会传入result作为参数。重写on_result的函数之后我们就可以对数据进行过滤。比如过滤掉一些无用的数据。上面的四行数据处理的代码如果看不懂可以参看前面讲过的知识。

    至此,今天的代码剖析完毕。今天只是讲了一下pyspider的简单应用,pyspider还有很多很实用的方法可以去发觉,比如和phantomJS结合,抓取ajax的动态数据,只需要你的服务器有phantomJs环境,然后再crawl函数中加入self.crawl('http://www.twitch.tv/directory/game/Dota%202', fetch_type='js', callback=self.index_page)fetch_type即可。

    最后我讲一下pyspider的管理台界面都有什么作用,参见上图的2.png,第一个group我也不是太清楚作用,只知道把group设置为delete然后status设置为stop,24小时之后任务会自动被删除。我们要开始一个任务,需要吧status设置为RUNNING然后在点击后面的run按钮。rate指的是每秒抓取多少次网页,一般情况下建议1以下,不容易被封。brust指的是并发度~后面的active Tasks可以看到现在正在执行的task的状态,最后一个就是抓取的result。

    写在最后

    今天我们讲解了pyspider的简单使用,下一章我们讲一下scrapy的简单使用,让大家能上手这个爬虫界的利器。

    最后附上我前两天讲解抓瓜子网信息的代码。

    
    #!/usr/bin/env python
    # -*- encoding: utf-8 -*-
    # Created on 2016-05-01 11:31:38
    # Project: guazi
    
    from pyspider.libs.base_handler import *
    import pymongo
    
    class Handler(BaseHandler):
        client = pymongo.MongoClient('localhost', 27017)
        guazi2 = client['guazi2']
        car = guazi2['car']
        
        crawl_config = {
        }
    
        @every(minutes=24 * 60)
        def on_start(self):
            self.crawl('http://www.guazi.com/bj/buy', callback=self.index_page)
    
        @config(age=10 * 24 * 60 * 60)
        def index_page(self, response):
            for each in response.doc('body > div.header > div.hd-top.clearfix > div.c2city > div > div > dl > dd > a').items():
                self.crawl(each.attr.href, callback=self.second_page)
    
        @config(age=10 * 24 * 60 * 60)
        def second_page(self, response):
            num = int(response.doc('div.seqBox.clearfix > p > b').text())
            urls = [response.url+'o{}/'.format(str(i)) for i in range(1,num/40+2,1)]
            for each in urls:
                self.crawl(each, callback=self.third_page)
                
        @config(age=10 * 24 * 60 * 60)
        def third_page(self, response):
            for each in response.doc('div.list > ul > li > div > a').items():
                self.crawl(each.attr.href, callback=self.detail_page)
                
        @config(priority=2)
        def detail_page(self, response):
            return {
                "url": response.url,
                "title": response.doc('body > div.w > div > div.laybox.clearfix > div.det-sumright.appoint > div.dt-titbox > h1').text(),
                "address": response.doc('body > div.w > div > div.laybox.clearfix > div.det-sumright.appoint > ul > li:nth-child(5) > b').text(),
                "cartype": response.doc('body > div.w > div > div.laybox.clearfix > div.det-sumright.appoint > ul > li:nth-child(3) > b').text(),
                "price": response.doc('body > div.w > div > div.laybox.clearfix > div.det-sumright.appoint > div.basic-box > div.pricebox > span.fc-org.pricestype > b').text().replace(u'¥',''),
                "region":response.doc('#base > ul > li.owner').text()
            }
        
        def on_result(self, result):
            self.car.insert_one(result)
    

    大家做个参考写的不好,轻喷

    有兴趣的同学可以加群498945822一起交流学习哦~~
    发现问题的同学欢迎指正,直接说就行,不用留面子,博主脸皮厚!

    相关文章

      网友评论

      • collerwang:你好,我正在用pyspider,这里面的crawl_config有个cookie,这是怎么获取的?
      • 秋桥Stacy:您好,能麻烦再解释一下如何在pycharm里面直接输入pyspider就能安装?我用的是windows系统,装了pycharm,可是不知道在哪儿直接输入,谢谢
        哇哈哈_43bf:我的Mac Pycharm,我安装了库之后,怎么使用?比如 pyspider all,启动,出现网页。怎么操作的。百度了,只是说安装好,而不知道怎么用。
        梅花鹿数据rieuse:@秋桥Stacy 百度一下pycharm的python库安装,简单粗暴
      • 5b674470f1cd:感谢分享,希望可以保持更新,qq群-Miracle
        Darkeril:@混江龙 好的,多谢支持
      • 唐宗宋祖:是小平啊,我是小白。受益良多,尤其是第五节,考虑是不是可以用在工作中,谢谢。另外是不是可以介绍下用到的库,框架的利弊,尤其是个人见解?
        Darkeril:@唐宗宋祖 你的需求是什么呢?框架的话我会继续讲scrapy,你可以继续关注。
      • 小小2020:叼毛,我关注你了
        Darkeril:看到了,谢谢你~

      本文标题:python爬虫的最佳实践(七)--pyspider框架的使用

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