大数据-爬虫框架学习--scrapy

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/firehadoop/article/details/70211160
一、scrapy是什么     

       Scrapy是Python开发的一个快速,高层次的屏幕抓取和web抓取框架,用于抓取web站点并从页面中提取结构化的数据。 Scrapy用途广泛,可以用于数据挖掘、监测和自动化测试。可以应用在包括数据挖掘,信息处理或存储历史数据等一系列的程序中。最初是为了 页面抓取 (更确切来说, 网络抓取 )所设计的, 也可以应用在获取API所返回的数据(例如 Amazon Associates Web Services ) 或者通用的网络爬虫。

       Scrapy吸引人的地方在于它是一个框架,任何人都可以根据需求方便的修改。它也提供了多种类型爬虫的基类, 如BaseSpider、sitemap爬虫等,还有对web2.0爬虫的支持。Scrach是抓取的意思。

 二、安装scrapy

下列的安装步骤假定您已经安装好下列程序(操作系统最好选择linux,很多python组件在linux环境下开发对windows的支持不是非常理想,而且在linux下运行python效率非常高,python的版本主要有2.x与3.x,3.x这个版本与2.x有很多地方不一样,大部分的组件只支持2.x,不建议安装3.x):

  • Python 2.7
  • Python Package: pip and setuptools. 现在 pip 依赖 setuptools ,如果未安装,则会自动安装 setuptools 。
  • lxml. 大多数Linux发行版自带了lxml。如果缺失,请查看http://lxml.de/installation.html
  • OpenSSL. 除了Windows(请查看 平台安装指南)之外的系统都已经提供。
我的操作系统才用了centos7,也就是redhat系列, 您可以使用pip来安装Scrapy(推荐使用pip来安装Python package).使用pip安装, 下面的所有步骤都切换到root用户:
[root@cxgzs ~]# uname -a
Linux cxgzs.wl02 3.10.0-514.2.2.el7.x86_64 #1 SMP Tue Dec 6 23:06:41 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
[root@cxgzs ~]# pip install scrapy
Collecting scrapy
  Downloading Scrapy-1.3.3-py2.py3-none-any.whl (240kB)
    100% |████████████████████████████████| 245kB 66kB/s 
Collecting pyOpenSSL (from scrapy)
  Downloading pyOpenSSL-16.2.0-py2.py3-none-any.whl (43kB)
    100% |████████████████████████████████| 51kB 75kB/s 
Successfully built Twisted PyDispatcher cryptography zope.interface
Installing collected packages: asn1crypto, packaging, cryptography, pyOpenSSL, cssselect, w3lib, parsel, queuelib, attrs, pyasn1-modules, service-identity, zope.interface, constantly, incremental, Automat, Twisted, PyDispatcher, scrapy
Successfully installed Automat-0.5.0 PyDispatcher-2.0.5 Twisted-17.1.0 asn1crypto-0.22.0 attrs-16.3.0 constantly-15.1.0 cryptography-1.8.1 cssselect-1.0.1 incremental-16.10.1 packaging-16.8 parsel-1.1.0 pyOpenSSL-16.2.0 pyasn1-modules-0.0.8 queuelib-1.4.2 scrapy-1.3.3 service-identity-16.0.0 w3lib-1.17.0 zope.interface-4.3.3

验证scrapy安装是否成功,当前最新版本是1.3.3
[root@cxgzs ~]# scrapy version
Scrapy 1.3.3


三、scrapy框架工作流程介绍


  • 新建项目 (Project):新建一个新的爬虫项目
  • scrapy startproject myproject
  • 其中,myproject为项目名称。

    可以看到将会创建一个 myproject文件夹,目录结构如下:

    myproject/  
        scrapy.cfg  
        myproject/  
            __init__.py  
            items.py  
            pipelines.py  
            settings.py  
            spiders/  
                __init__.py  
                ...  

    下面来简单介绍一下各个文件的作用:

    • scrapy.cfg:项目的配置文件
    • myproject/:项目的 Python 模块,将会从这里引用代码
    • myproject/items.py:项目的 items 文件
    • myproject/pipelines.py:项目的 pipelines 文件
    • myproject/settings.py:项目的设置文件
    • myproject/spiders/:存储爬虫的目录

  • 明确目标(Items):明确你想要抓取的目标
      Scrapy 中,items 是用来加载抓取内容的容器,有点像 Python 中的 Dic,也就是字典,类似于 ORM 的映射关系,类似与java中的bean,建立爬虫获取信息的bean类。通过定义items.py文件实现。

  • 制作爬虫(Spider):制作爬虫开始爬取网页
    首先你要获取整个网页的所有内容,然后再取出其中对你有用的部分。

    确定三个强制的属性:

  • name:爬虫的识别名称,必须是唯一的,在不同的爬虫中你必须定义不同的名字。
  • start_urls:爬取的 URL 列表。爬虫从这里开始抓取数据,所以,第一次下载的数据将会从这些 urls 开始。其他子 URL 将会从这些起始 URL 中继承性生成。
  • parse():解析的方法,调用的时候传入从每一个 URL 传回的 Response 对象作为唯一参数,负责解析并匹配抓取的数据(解析为 item),跟踪更多的 URL。
  • 把 Url 存储下来并依此为起点逐步扩散开去,抓取所有符合条件的网页 Url 存储起来继续爬取。

  • 存储内容(Pipeline):设计管道存储爬取内容
  • 爬虫爬下来的内容可以存储为csv、json、xml或者直接导入到数据库中。
上面的内容都是纸上谈兵,下面我们来个实战,比上面介绍的要简单,一个python文件搞定,爬取的目标就是我的csdn博客,呵呵!

四、实战第一只爬虫

      1、构建爬虫源码文件csdn.py
import scrapy

class CsdnSpider(scrapy.Spider):
    name = 'csdn'
    start_urls = ['http://blog.csdn.net/firehadoop?viewmode=contents']

    def parse(self, response):
        for href in response.css('h1 .link_title a::attr(href)'):
                full_url = response.urljoin(href.extract())
                print full_url
                yield scrapy.Request(full_url, callback=self.parse_question)

    def parse_question(self, response):
        yield {
            'title': response.css('.link_title a::text').extract(),
            'postdate':response.css('.link_postdate ::text').extract(),
            'view':response.css('.link_view ::text').extract(),
            'link': response.url,
        }

     2、运行代码
[wangli@cxgzs ~]$scrapy runspider csdn.py --output=csdn5.txt -t jsonlines
2017-04-17 20:50:52 [scrapy.utils.log] INFO: Scrapy 1.3.3 started (bot: scrapybot)
2017-04-17 20:50:52 [scrapy.utils.log] INFO: Overridden settings: {'SPIDER_LOADER_WARN_ONLY': True, 'FEED_URI': 'csdn5.txt'}--爬虫输出文件是csdn5.txt,并且是覆盖追加模式
2017-04-17 20:50:53 [scrapy.middleware] INFO: Enabled extensions:
['scrapy.extensions.feedexport.FeedExporter',
 'scrapy.extensions.logstats.LogStats',
 'scrapy.extensions.telnet.TelnetConsole',
 'scrapy.extensions.corestats.CoreStats']
2017-04-17 20:50:53 [scrapy.middleware] INFO: Enabled downloader middlewares:
['scrapy.downloadermiddlewares.httpauth.HttpAuthMiddleware',
 'scrapy.downloadermiddlewares.downloadtimeout.DownloadTimeoutMiddleware',
 'scrapy.downloadermiddlewares.defaultheaders.DefaultHeadersMiddleware',
 'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware',
 'scrapy.downloadermiddlewares.retry.RetryMiddleware',
 'scrapy.downloadermiddlewares.redirect.MetaRefreshMiddleware',
 'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware',
 'scrapy.downloadermiddlewares.redirect.RedirectMiddleware',
 'scrapy.downloadermiddlewares.cookies.CookiesMiddleware',
 'scrapy.downloadermiddlewares.stats.DownloaderStats']
2017-04-17 20:50:53 [scrapy.middleware] INFO: Enabled spider middlewares:
['scrapy.spidermiddlewares.httperror.HttpErrorMiddleware',
 'scrapy.spidermiddlewares.offsite.OffsiteMiddleware',
 'scrapy.spidermiddlewares.referer.RefererMiddleware',
 'scrapy.spidermiddlewares.urllength.UrlLengthMiddleware',
 'scrapy.spidermiddlewares.depth.DepthMiddleware']
2017-04-17 20:50:53 [scrapy.middleware] INFO: Enabled item pipelines:
[]--文件中没有定义pipelines进行转储,直接通过scrapy命令加output参数实现转储
2017-04-17 20:50:53 [scrapy.core.engine] INFO: Spider opened
2017-04-17 20:50:53 [scrapy.extensions.logstats] INFO: Crawled 0 pages (at 0 pages/min), scraped 0 items (at 0 items/min)
2017-04-17 20:50:53 [scrapy.extensions.telnet] DEBUG: Telnet console listening on 127.0.0.1:6023
2017-04-17 20:50:53 [scrapy.core.engine] DEBUG: Crawled (200)<GET http://blog.csdn.net/firehadoop?viewmode=contents> (referer: None)--爬虫启动的入口url,firehadoop博客的目录视图入口
http://blog.csdn.net/firehadoop/article/details/70182483--对应firehadoop上的七篇博客完整的url链接
http://blog.csdn.net/firehadoop/article/details/70162692
http://blog.csdn.net/firehadoop/article/details/69853954
http://blog.csdn.net/firehadoop/article/details/69791546
http://blog.csdn.net/firehadoop/article/details/69075792
http://blog.csdn.net/firehadoop/article/details/68981887
http://blog.csdn.net/firehadoop/article/details/68953541

2017-04-17 20:50:53 [scrapy.core.engine] DEBUG: Crawled (200) <GET http://blog.csdn.net/firehadoop/article/details/70162692> (referer: http://blog.csdn.net/firehadoop?viewmode=contents)
2017-04-17 20:50:53 [scrapy.core.engine] DEBUG: Crawled (200) <GET http://blog.csdn.net/firehadoop/article/details/68953541> (referer: http://blog.csdn.net/firehadoop?viewmode=contents)
2017-04-17 20:50:53 [scrapy.core.engine] DEBUG: Crawled (200) <GET http://blog.csdn.net/firehadoop/article/details/69791546> (referer: http://blog.csdn.net/firehadoop?viewmode=contents)
2017-04-17 20:50:53 [scrapy.core.engine] DEBUG: Crawled (200) <GET http://blog.csdn.net/firehadoop/article/details/69075792> (referer: http://blog.csdn.net/firehadoop?viewmode=contents)
2017-04-17 20:50:53 [scrapy.core.engine] DEBUG: Crawled (200) <GET http://blog.csdn.net/firehadoop/article/details/70182483> (referer: http://blog.csdn.net/firehadoop?viewmode=contents)
2017-04-17 20:50:53 [scrapy.core.engine] DEBUG: Crawled (200) <GET http://blog.csdn.net/firehadoop/article/details/68981887> (referer: http://blog.csdn.net/firehadoop?viewmode=contents)
2017-04-17 20:50:53 [scrapy.core.scraper] DEBUG: Scraped from <200 http://blog.csdn.net/firehadoop/article/details/70162692>
--上面就是scrapy最爽的地方,它同时启动了7个线程同时对七篇文章的完整url进行了爬取,这效率想想也是醉了。最关键你无需在程序中去指定这些多线程的细节,完全有scrapy框架根据实际业务情况自动调度。
{'postdate': [u'2017-04-13 22:13'], 'view': [u'15\u4eba\u9605\u8bfb'], 'link': 'http://blog.csdn.net/firehadoop/article/details/70162692', 'title': [u'\r\n        win10\u4e0b\u5b89\u88c5\u914d\u7f6ecisco vpn client            \r\n        ']}--返回解析好json格式的爬取信息
2017-04-17 20:50:53 [scrapy.core.engine] DEBUG: Crawled (200) <GET http://blog.csdn.net/firehadoop/article/details/69853954> (referer: http://blog.csdn.net/firehadoop?viewmode=contents)
2017-04-17 20:50:53 [scrapy.core.scraper] DEBUG: Scraped from <200 http://blog.csdn.net/firehadoop/article/details/68953541>
{'postdate': [u'2017-04-02 19:22'], 'view': [u'42\u4eba\u9605\u8bfb'], 'link': 'http://blog.csdn.net/firehadoop/article/details/68953541', 'title': [u'\r\n        centos7\u4e0b\u8c03\u8bd5\u96c6\u7fa4\u4e09\u53f0\u673a\u5668\u5b9e\u73b0\u514d\u5bc6\u767b\u9646--hadoop\u5b89\u88c5\u7cfb\u5217\u4e4b\u4e00            \r\n        ']}
{'postdate': [u'2017-04-09 07:15'], 'view': [u'66\u4eba\u9605\u8bfb'], 'link': 'http://blog.csdn.net/firehadoop/article/details/69791546', 'title': [u'\r\n        \u673a\u5668\u5b66\u4e60\u5165\u95e8\u7cfb\u5217-\u4e3a\u4ec0\u4e48\u8981\u673a\u5668\u5b66\u4e60            \r\n        ']}
2017-04-17 20:50:53 [scrapy.core.scraper] DEBUG: Scraped from <200 http://blog.csdn.net/firehadoop/article/details/69075792>
{'postdate': [u'2017-04-04 16:19'], 'view': [u'22\u4eba\u9605\u8bfb'], 'link': 'http://blog.csdn.net/firehadoop/article/details/69075792', 'title': [u'\r\n        hadoop\u7684dw-hive\u5b89\u88c5\u914d\u7f6e---hadoop\u5b89\u88c5\u7cfb\u5217\u4e4b\u4e09            \r\n        ']}
2017-04-17 20:50:53 [scrapy.core.scraper] DEBUG: Scraped from <200 http://blog.csdn.net/firehadoop/article/details/70182483>
{'postdate': [u'2017-04-15 09:11'], 'view': [u'30\u4eba\u9605\u8bfb'], 'link': 'http://blog.csdn.net/firehadoop/article/details/70182483', 'title': [u'\r\n        sqoop \u77e5\u8bc6\u53ca\u5b89\u88c5\u914d\u7f6e\u8bf4\u660e--hadoop\u5b89\u88c5\u7cfb\u5217\u4e4b\u56db            \r\n        ']}
2017-04-17 20:50:53 [scrapy.core.scraper] DEBUG: Scraped from <200 http://blog.csdn.net/firehadoop/article/details/68981887>
{'postdate': [u'2017-04-03 19:31'], 'view': [u'64\u4eba\u9605\u8bfb'], 'link': 'http://blog.csdn.net/firehadoop/article/details/68981887', 'title': [u'\r\n        centos7\u5168\u5206\u5e03\u6a21\u5f0f\u5b89\u88c5hadoop--hadoop\u5b89\u88c5\u7cfb\u5217\u4e4b\u4e8c            \r\n        ']}
2017-04-17 20:50:53 [scrapy.core.scraper] DEBUG: Scraped from <200 http://blog.csdn.net/firehadoop/article/details/69853954>
{'postdate': [u'2017-04-09 17:33'], 'view': [u'18\u4eba\u9605\u8bfb'], 'link': 'http://blog.csdn.net/firehadoop/article/details/69853954', 'title': [u'\r\n        \u673a\u5668\u5b66\u4e60\u5165\u95e8\u7cfb\u5217\u4e4b\u4e8c---\u7ebf\u6027\u56de\u5f52\u7b97\u6cd5\u5b66\u4e60            \r\n        ']}
2017-04-17 20:50:53 [scrapy.core.engine] INFO: Closing spider (finished)--爬虫完工了
2017-04-17 20:50:53 [scrapy.extensions.feedexport] INFO:Stored jsonlines feed (7 items) in: csdn5.txt--结果以jsonlines格式存储在csdn5.txt中,jsonlines就是每行数据一个json,如果才用json格式,会用数组嵌套的模式把这7行数据放置在一个json中。
2017-04-17 20:50:53 [scrapy.statscollectors] INFO: Dumping Scrapy stats:
{'downloader/request_bytes': 2871,
 'downloader/request_count': 8,
 'downloader/request_method_count/GET': 8,
 'downloader/response_bytes': 133247,
 'downloader/response_count': 8,
 'downloader/response_status_count/200': 8,
 'finish_reason': 'finished',
 'finish_time': datetime.datetime(2017, 4, 17, 12, 50, 53, 791299),
 'item_scraped_count': 7,
 'log_count/DEBUG': 16,
 'log_count/INFO': 8,
 'request_depth_max': 1,
 'response_received_count': 8,
 'scheduler/dequeued': 8,
 'scheduler/dequeued/memory': 8,
 'scheduler/enqueued': 8,
 'scheduler/enqueued/memory': 8,
 'start_time': datetime.datetime(2017, 4, 17, 12, 50, 53, 62819)}
2017-04-17 20:50:53 [scrapy.core.engine] INFO: Spider closed (finished)

    3、查看输出文件内容

[wangli@cxgzs ~]$ cat csdn5.txt 
{"postdate": ["2017-04-13 22:13"], "title": ["\r\n        win10\u4e0b\u5b89\u88c5\u914d\u7f6ecisco vpn client            \r\n        "], "link": "http://blog.csdn.net/firehadoop/article/details/70162692", "view": ["15\u4eba\u9605\u8bfb"]}
{"postdate": ["2017-04-02 19:22"], "title": ["\r\n        centos7\u4e0b\u8c03\u8bd5\u96c6\u7fa4\u4e09\u53f0\u673a\u5668\u5b9e\u73b0\u514d\u5bc6\u767b\u9646--hadoop\u5b89\u88c5\u7cfb\u5217\u4e4b\u4e00            \r\n        "], "link": "http://blog.csdn.net/firehadoop/article/details/68953541", "view": ["42\u4eba\u9605\u8bfb"]}
{"postdate": ["2017-04-09 07:15"], "title": ["\r\n        \u673a\u5668\u5b66\u4e60\u5165\u95e8\u7cfb\u5217-\u4e3a\u4ec0\u4e48\u8981\u673a\u5668\u5b66\u4e60            \r\n        "], "link": "http://blog.csdn.net/firehadoop/article/details/69791546", "view": ["66\u4eba\u9605\u8bfb"]}
{"postdate": ["2017-04-04 16:19"], "title": ["\r\n        hadoop\u7684dw-hive\u5b89\u88c5\u914d\u7f6e---hadoop\u5b89\u88c5\u7cfb\u5217\u4e4b\u4e09            \r\n        "], "link": "http://blog.csdn.net/firehadoop/article/details/69075792", "view": ["22\u4eba\u9605\u8bfb"]}
{"postdate": ["2017-04-15 09:11"], "title": ["\r\n        sqoop \u77e5\u8bc6\u53ca\u5b89\u88c5\u914d\u7f6e\u8bf4\u660e--hadoop\u5b89\u88c5\u7cfb\u5217\u4e4b\u56db            \r\n        "], "link": "http://blog.csdn.net/firehadoop/article/details/70182483", "view": ["30\u4eba\u9605\u8bfb"]}
{"postdate": ["2017-04-03 19:31"], "title": ["\r\n        centos7\u5168\u5206\u5e03\u6a21\u5f0f\u5b89\u88c5hadoop--hadoop\u5b89\u88c5\u7cfb\u5217\u4e4b\u4e8c            \r\n        "], "link": "http://blog.csdn.net/firehadoop/article/details/68981887", "view": ["64\u4eba\u9605\u8bfb"]}
{"postdate": ["2017-04-09 17:33"], "title": ["\r\n        \u673a\u5668\u5b66\u4e60\u5165\u95e8\u7cfb\u5217\u4e4b\u4e8c---\u7ebf\u6027\u56de\u5f52\u7b97\u6cd5\u5b66\u4e60            \r\n        "], "link": "http://blog.csdn.net/firehadoop/article/details/69853954", "view": ["18\u4eba\u9605\u8bfb"]}
 可以看到,七篇博文需要爬取的内容以七组json数据的形式保存在指定的文件中。
    4、代码重点部分解释
      start_urls = ['http://blog.csdn.net/firehadoop?viewmode=contents']--函数执行入口
     执行步骤如下:
     首先加载start_urls中定义的url,启动一个线程打开url,将其中的内容全部送给第一个response,就是for循环中的的response,通过后面的css选择器对符合特征HTML标签 h1 当前节点名为link_title的 超链接进行取值,最后存入一个数组,用于给href取值用,这里应该保存了七个博客文章的不完全url(就是不包含博客请求域名的完整url)
     response.css('h1 .link_title a::attr(href)')
     使用urljoin函数将不完整的url信息补全,并且存入变量full_url
     full_url = response.urljoin(href.extract())
      运行scrapy runspider csdn.py这条语句的时候,Scrapy会去寻找源文件中定义的一个spider并且交给爬虫引擎来执行它。 start_urls属性定义了开始的URL,爬虫会通过它来构建初始的请求,返回response后再调用默认的回调方法parse并传入这个response。 我们在parse回调方法中通过使用css选择器提取每个提问页面链接的href属性值,然后yield另外一个请求, 并注册parse_question回调方法,在这个请求完成后被执行。
    七个完整的full_url被同时放入七个爬虫,同时爬取页面,内容返回到回调函数parse_question处理,在这个函数中我们定义了博客标题title,博客发表日期postdate,博客阅读次数view,博客完整url-link,四个数据项,分别通过css选择器与定义在后面的不同属性来分别获取对应的爬取数值。这时的爬虫实际上相当于人工同时打开了firehadoop的七篇博客,并从中读取记录了上面定义的四项数据,然后将记录信息以json的格式保存在指定文件中。
   5、爬虫学习总结

    scrapy这个爬虫框架非常强大,可定制化程序很高,但是学习起来需要了解的东西也很多,需要配置的项目也比较多,如果心情比较着急,也可以通过上面这个python的自制小程序快速上手,测试一下,实际工程项目中还是建议认真完整的学习一下scrapy框架,通过模块化定制完成数据爬取。
    爬虫框架让你可以聚焦到业务层面,完全无需关注了解具体的爬取过程,与网络、操作系统、各种网络协议打交道的底层由爬虫框架完成,这大大的解放了开发人员。
 

猜你喜欢

转载自blog.csdn.net/firehadoop/article/details/70211160