首页 > 技术文章 > Python-Scrapy

swda 2019-10-22 09:48 原文

一、安装Scrapy 
在安装scrapy之前有一些依赖需要安装,否则可能会安装失败,scrapy的选择器依赖于lxml,还有Twisted网络引擎,下面是ubuntu下安装的过程
linux下安装
# 1. 安装xml依赖库
$ sudo apt-get install libxml2 libxml2-dev
$ sudo apt-get install libxslt1-dev
$ sudo apt-get install python-libxml2
 
# 2. 安装lxml
$ sudo pip install lxml
 
# 3. 安装Twisted(版本可以换成最新的),用pip也可以,如果失败的话下载源码安装,如下
$ wget https://pypi.python.org/packages/6b/23/8dbe86fc83215015e221fbd861a545c6ec5c9e9cd7514af114d1f64084ab/Twisted-16.4.1.tar.bz2#md5=c6d09bdd681f538369659111f079c29d
$ tar xjf Twisted-16.4.1.tar.bz2
$ cd Twisted-16.4.1
$ sudo python setup.py install
 
# 4. 安装scrapy
$ sudo pip install scrapy
http://lxml.de/installation.html
 
Mac下安装
# 安装xml依赖库
$ xcode-select —install
 
# 其实相关依赖pip会自动帮我们装上
$ pip install scrapy
mac下安装有时候会失败,建议使用virtualenv安装在独立的环境下,可以减少一些问题,因为mac系统自带python,例如一些依赖库依赖的一些新的版本,而升级新版本会把旧版本卸载掉,卸载可能会有权限的问题
 
二、Scrapy简介
官方描述:Scrapy is a fast high-level screen scraping and web crawling framework, used to crawl websites and extract structured data from their pages. It can be used for a wide range of purposes, from data mining to monitoring and automated testing
 
官方文档对其详细描述:
“Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架。 可以应用在包括数据挖掘,信息处理或存储历史数据等一系列的程序中。其最初是为了页面抓取 (更确切来说, 网络抓取 )所设计的, 也可以应用在获取API所返回的数据(例如 Amazon Associates Web Services ) 或者通用的网络爬虫。”
 
网络爬虫,就是一个在网上到处或定向抓取数据的程序。或者,更专业的来说,网络爬虫会抓取特定网站网页的HTML数据。抓取网页的一般方法是,定义一个入口页面,然后一般一个页面会有其他页面的URL,于是从当前页面获取到这些URL加入到爬虫的抓取队列中,然后进入到新页面后再递归的进行上述的操作,其实说来就跟深度遍历(DFS)或广度(BFS)遍历一样。
 
Scrapy 使用 Twisted(http://twistedmatrix.com/trac/)这个异步网络库来处理网络通讯,架构清晰,并且包含了各种中间件接口,可以灵活的完成各种需求。
 

三、概述

下图表展现了Scrapy的架构,包括组件及在系统中发生的数据流的概览(绿色箭头所示)。 下面对每个组件都做了简单介绍,并给出了详细内容的链接。数据流如下所描述。

 
四、Scrapy结构说明
 
组件
Scrapy Engine
引擎负责控制数据流在系统中所有组件中流动,并在相应动作发生时触发事件。 详细内容查看下面的数据流(Data Flow)部分。
 
调度器(Scheduler)
调度器从引擎接受request并将他们入队,以便之后引擎请求他们时提供给引擎。
 
下载器(Downloader)
下载器负责获取页面数据并提供给引擎,而后提供给spider。
 
Spiders
Spider是Scrapy用户编写用于分析response并提取item(即获取到的item)或额外跟进的URL的类。 每个spider负责处理一个特定(或一些)网站。 更多内容请看 Spiders 。
 
Item Pipeline
Item Pipeline负责处理被spider提取出来的item。典型的处理有清理、 验证及持久化(例如存取到数据库中)。 更多内容查看 Item Pipeline 。
 
下载器中间件(Downloader middlewares)
下载器中间件是在引擎及下载器之间的特定钩子(specific hook),处理Downloader传递给引擎的response。 其提供了一个简便的机制,通过插入自定义代码来扩展Scrapy功能。更多内容请看 下载器中间件(Downloader Middleware) 。
 
Spider中间件(Spider middlewares)
Spider中间件是在引擎及Spider之间的特定钩子(specific hook),处理spider的输入(response)和输出(items及requests)。 其提供了一个简便的机制,通过插入自定义代码来扩展Scrapy功能。更多内容请看 Spider中间件(Middleware) 。
 
 
五、数据流(data flow)
 
Scrapy中的数据流由执行引擎控制,其过程如下:
 
1.引擎打开一个网站(open a domain),找到处理该网站的Spider并向该spider请求第一个要爬取的URL(s)。
2.引擎从Spider中获取到第一个要爬取的URL并在调度器(Scheduler)以Request调度。
3.引擎向调度器请求下一个要爬取的URL。
4.调度器返回下一个要爬取的URL给引擎,引擎将URL通过下载中间件(请求(request)方向)转发给下载器(Downloader)。
5.一旦页面下载完毕,下载器生成一个该页面的Response,并将其通过下载中间件(返回(response)方向)发送给引擎。
6.引擎从下载器中接收到Response并通过Spider中间件(输入方向)发送给Spider处理。
7.Spider处理Response并返回爬取到的Item及(跟进的)新的Request给引擎。
8.引擎将(Spider返回的)爬取到的Item给Item Pipeline,将(Spider返回的)Request给调度器。
9.(从第二步)重复直到调度器中没有更多地request,引擎关闭该网站。
 
绿线是数据流向,首先从初始 URL 开始,Scheduler 会将其交给 Downloader 进行下载,下载之后会交给 Spider 进行分析,Spider 分析出来的结果有两种:一种是需要进一步抓取的链接,例如之前分析的“下一页”的链接,这些东西会被传回 Scheduler ;另一种是需要保存的数据,它们则被送到 Item Pipeline 那里,那是对数据进行后期处理(详细分析、过滤、存储等)的地方。另外,在数据流动的通道里还可以安装各种中间件,进行必要的处理。
 
六、Scrapy入门教程
 
这个教程会交给我们以下的任务:
1.建立一个新的scrapy任务
2.写一个爬虫用来爬网站并采集信息
3.用command line来输出采集到的信息
4.创建一个爬虫来递归地爬取网站
5.使用爬虫参数
 
因为Scrapy是用python写的,对于不熟悉python而用过其他语言的,可以参考这个教程:http://www.diveintopython3.net。或者也可以参考python的教程:
https://docs.python.org/3/tutorial/ 
 
建立一个新的scrapy任务
首先要写一个directory,规定代码
 
scrapy startproject tutorial
 
这会建立一个名叫tutorial的directory并含有如下的内容:
tutorial/
    scrapy.cfg            # deploy configuration file
    tutorial/             # project's Python module, you'll import your code from here
        __init__.py
        items.py          # project items definition file
        pipelines.py      # project pipelines file
        settings.py       # project settings file
        spiders/          # a directory where you'll later put your spiders
            __init__.py
 
定义Item 
Item 是保存爬取到的数据的容器;其使用方法和python dict类似。虽然也可以在Scrapy中直接使用dict,但是 Item 提供了额外保护机制来避免拼写错误导致的未定义字段错误。也可使用Item Loaders,以便提供更方便的API. 
 
类似在ORM中做的一样,可以通过创建一个 scrapy.Item 类, 并且定义类型为 scrapy.Field 的类属性来定义一个Item。
 
首先根据需要从dmoztools.org获取到的数据对item进行建模。 我们需要从dmoztools中获取名字,url,以及网站的描述。 对此,在item中定义相应的字段。编辑 tutorial 目录中的 items.py 文件:
 
import scrapy
class DmozItem(scrapy.Item):
    title = scrapy.Field()
    link = scrapy.Field()
    desc = scrapy.Field()
 
一开始这看起来可能有点复杂,但是通过定义item, 可以很方便的使用Scrapy的其他方法。而这些方法需要知道item的定义。
 
编写第一个爬虫
Spider是用户编写用于从单个网站(或者一些网站)爬取数据的类。
其包含了一个用于下载的初始URL,如何跟进网页中的链接以及如何分析页面中的内容, 提取生成 item 的方法。
为了创建一个Spider,我们必须继承 scrapy.Spider 类, 且定义一些属性:
 • name: 用于区别Spider。 该名字必须是唯一的,我们不可以为不同的Spider设定相同的名字。
 • start_urls: 包含了Spider在启动时进行爬取的url列表。 因此,第一个被获取到的页面将是其中之一。 后续的URL则从初始的URL获取到的数据中提取。
 • parse() 是spider的一个方法。 被调用时,每个初始URL完成下载后生成的 Response 对象将会作为唯一的参数传递给该函数。 该方法负责解析返回的数据(response data),提取数据(生成item)以及生成需要进一步处理的URL的 Request 对象。
 
以下为我们的第一个Spider代码,保存在 tutorial/spiders 目录下的 dmoztools_spider.py 文件中:
 
import scrapy
class DmozSpider(scrapy.Spider):
    name = "dmoztools"
    allowed_domains = ["dmoztools.net"]
    start_urls = [
        "http://www.dmoztools.net/Computers/Programming/Languages/Python/Books/",
        "http://www.dmoztools.net/Computers/Programming/Languages/Python/Resources/"
    ]
 
    def parse(self, response):
        filename = response.url.split("/")[-2] + '.html'
        with open(filename, 'wb') as f:
            f.write(response.body)
 
爬取
 
进入项目的根目录,执行下列命令启动spider:
scrapy crawl dmoztools
 
出现问题:Unknown command: crawl 
解决方法:https://stackoverflow.com/questions/4988297/trying-to-get-scrapy-into-a-project-to-run-crawl-command
 
刚才输入的命令启动了我们刚刚添加的domztools spider,向dmoztools.org发送了一些请求,得到输出类似如下:
 
2017-07-06 15:34:43 [scrapy.utils.log] INFO: Scrapy 1.4.0 started (bot: tutorial)
2017-07-06 15:34:43 [scrapy.utils.log] INFO: Overridden settings: {}
2017-07-06 15:34:43 [scrapy.middleware] INFO: Enabled extensions:..
2017-07-06 15:34:44 [scrapy.middleware] INFO: Enabled downloader middlewares:..
2017-07-06 15:34:44 [scrapy.middleware] INFO: Enabled spider middlewares:..
2017-07-06 15:34:44 [scrapy.middleware] INFO: Enabled item pipelines:[]
2017-07-06 15:34:44 [scrapy.core.engine] INFO: Spider opened
2017-07-06 15:34:44 [scrapy.extensions.logstats] INFO: Crawled 0 pages (at 0 pages/min), scraped 0 items (at 0 items/min)
2017-07-06 15:34:44 [scrapy.extensions.telnet] DEBUG: Telnet console listening on 127.0.0.1:6023
2017-07-06 15:34:45 [scrapy.core.engine] DEBUG: Crawled (200) <GET http://www.dmoztools.net/robots.txt> (referer: None)
2017-07-06 15:34:46 [scrapy.core.engine] DEBUG: Crawled (200) <GET http://www.dmoztools.net/Computers/Programming/Languages/Python/Books/> (referer: None)
2017-07-06 15:34:46 [scrapy.core.engine] DEBUG: Crawled (200) <GET http://www.dmoztools.net/Computers/Programming/Languages/Python/Resources/> (referer: None)
2017-07-06 15:34:46 [scrapy.core.engine] INFO: Closing spider (finished)
2017-07-06 15:34:46 [scrapy.statscollectors] INFO: Dumping Scrapy stats:{}
2017-07-06 15:34:46 [scrapy.core.engine] INFO: Spider closed (finished)
Minnas-MacBook-Pro:tutorial minnawu$ scrapy crawl dmoztools
2017-07-06 15:35:16 [scrapy.utils.log] INFO: Scrapy 1.4.0 started (bot: tutorial)
2017-07-06 15:35:16 [scrapy.utils.log] INFO: Overridden settings: {'NEWSPIDER_MODULE': 'tutorial.spiders', 'SPIDER_MODULES': ['tutorial.spiders'], 'ROBOTSTXT_OBEY': True, 'BOT_NAME': 'tutorial'}
2017-07-06 15:35:16 [scrapy.middleware] INFO: Enabled extensions:..
2017-07-06 15:35:17 [scrapy.middleware] INFO: Enabled downloader middlewares:..
2017-07-06 15:35:17 [scrapy.middleware] INFO: Enabled spider middlewares:..
2017-07-06 15:35:17 [scrapy.middleware] INFO: Enabled item pipelines:[]
2017-07-06 15:35:17 [scrapy.core.engine] INFO: Spider opened
2017-07-06 15:35:17 [scrapy.extensions.logstats] INFO: Crawled 0 pages (at 0 pages/min), scraped 0 items (at 0 items/min)
2017-07-06 15:35:17 [scrapy.extensions.telnet] DEBUG: Telnet console listening on 127.0.0.1:6023
2017-07-06 15:35:17 [scrapy.core.engine] DEBUG: Crawled (200) <GET http://www.dmoztools.net/robots.txt> (referer: None)
2017-07-06 15:35:18 [scrapy.core.engine] DEBUG: Crawled (200) <GET http://www.dmoztools.net/Computers/Programming/Languages/Python/Books/> (referer: None)
2017-07-06 15:35:18 [scrapy.core.engine] DEBUG: Crawled (200) <GET http://www.dmoztools.net/Computers/Programming/Languages/Python/Resources/> (referer: None)
2017-07-06 15:35:18 [scrapy.core.engine] INFO: Closing spider (finished)
2017-07-06 15:35:18 [scrapy.statscollectors] INFO: Dumping Scrapy stats:{}
2017-07-06 15:35:18 [scrapy.core.engine] INFO: Spider closed (finished)
 
现在,查看当前目录,会注意到有两个包含url所对应的内容的文件被创建了: Book , Resources,正如parse 方法里做的一样。
 
Scrapy为Spider的 start_urls 属性中的每个URL创建了 scrapy.Request 对象,并将 parse 方法作为回调函数(callback)赋值给了Request。
Request对象经过调度,执行生成 scrapy.http.Response 对象并送回给spider parse() 方法。
 
提取Items 
 
从网页中提取数据有很多方法。Scrapy使用了一种基于 XPathCSS 表达式机制: Scrapy Selectors 。 关于selector和其他提取机制的信息请参考 Selector文档 (http://scrapy-chs.readthedocs.io/zh_CN/1.0/topics/selectors.html#topics-selectors) 
 
Selector有四个基本的方法(点击相应的方法可以看到详细的API文档):
 • xpath(): 传入xpath表达式,返回该表达式所对应的所有节点的selector list列表 。
 • css(): 传入CSS表达式,返回该表达式所对应的所有节点的selector list列表.
 • extract(): 序列化该节点为unicode字符串并返回list。
 • re(): 根据传入的正则表达式对数据进行提取,返回unicode字符串list列表。
 
 
在Shell中尝试Selector选择器
为了介绍Selector的使用方法,接下来我们将要使用内置的 Scrapy shell
Scrapy Shell需要预装好 IPython (一个扩展的Python终端)。
我们需要进入项目的根目录,执行下列命令来启动shell:
scrapy shell "http://www.dmoztools.org/Computers/Programming/Languages/Python/Books/"
 
shell的输出类似:
[ ... Scrapy log here ... ]
 
2017-07-06 17:03:14 [scrapy.core.engine] DEBUG: Crawled (403) <GET http://www.dmoz.org/Computers/Programming/Languages/Python/Books/> (referer: None)
[s] Available Scrapy objects:
[s]   scrapy     scrapy module (contains scrapy.Request, scrapy.Selector, etc)
[s]   crawler    <scrapy.crawler.Crawler object at 0x10e96fa90>
[s]   item       {}
[s]   request    <GET http://www.dmoz.org/Computers/Programming/Languages/Python/Books/>
[s]   response   <403 http://www.dmoz.org/Computers/Programming/Languages/Python/Books/>
[s]   settings   <scrapy.settings.Settings object at 0x10e96fa10>
[s]   spider     <DefaultSpider 'default' at 0x10f463690>
[s] Useful shortcuts:
[s]   fetch(url[, redirect=True]) Fetch URL and update local objects (by default, redirects are followed)
[s]   fetch(req)                  Fetch a scrapy.Request and update local objects 
[s]   shelp()           Shell help (print this help)
[s]   view(response)    View response in a browser
 
当shell载入后,将得到一个包含response数据的本地 response 变量。输入 response.body 将输出response的包体, 输出 response.headers 可以看到response的包头。
 
更为重要的是, response 拥有一个 selector 属性, 该属性是以该特定 response 初始化的类 Selector 的对象。 可以通过使用 response.selector.xpath() 或 response.selector.css() 来对 response 进行查询。 此外,scrapy也对 response.selector.xpath() 及 response.selector.css() 提供了一些快捷方式, 例如 response.xpath() 或 response.css() ,
 
同时,shell根据response提前初始化了变量 sel 。该selector根据response的类型自动选择最合适的分析规则(XML vs HTML)。
 
例子:
 
In [1]: response.xpath('//title')
Out[1]: [<Selector xpath='//title' data=u'<title>Open Directory - Computers: Progr'>]
 
In [2]: response.xpath('//title').extract()
Out[2]: [u'<title>Open Directory - Computers: Programming: Languages: Python: Books</title>']
 
In [3]: response.xpath('//title/text()')
Out[3]: [<Selector xpath='//title/text()' data=u'Open Directory - Computers: Programming:'>]
 
In [4]: response.xpath('//title/text()').extract()
Out[4]: [u'Open Directory - Computers: Programming: Languages: Python: Books']
 
In [5]: response.xpath('//title/text()').re('(\w+):')
Out[5]: [u'Computers', u'Programming', u'Languages', u'Python']
 
提取数据
现在,我们来尝试从这些页面中提取些有用的数据。
我们可以在终端中输入 response.body 来观察HTML源码并确定合适的XPath表达式。可以使用Firefox的Firebug扩展。
 
比如:我们可以通过这段代码选择该页面中网站列表里所有 <li> 元素:
response.xpath(‘//ul/li')
 
网站的描述:
response.xpath(‘//ul/li/text()').extract()
 
网站的标题:
response.xpath(‘//ul/li/a/text()').extract()
 
以及网站的链接:
response.xpath(‘//ul/li/a/@href').extract()
 
之前提到过,每个 .xpath() 调用返回selector组成的list,因此我们可以拼接更多的 .xpath() 来进一步获取某个节点。我们将在下边使用这样的特性:
for sel in response.xpath('//ul/li'):
    title = sel.xpath('a/text()').extract()
    link = sel.xpath('a/@href').extract()
    desc = sel.xpath('text()').extract()
    print title, link, desc
 
在我们的spider中加入这段代码:
import scrapy
class DmozSpider(scrapy.Spider):
    name = "dmoz"
    allowed_domains = ["dmoztools.org"]
    start_urls = [
        "http://www.dmoztools.org/Computers/Programming/Languages/Python/Books/",
        "http://www.dmoztools.org/Computers/Programming/Languages/Python/Resources/"
    ]
 
    def parse(self, response):
        for sel in response.xpath('//ul/li'):
            title = sel.xpath('a/text()').extract()
            link = sel.xpath('a/@href').extract()
            desc = sel.xpath('text()').extract()
            print title, link, desc
 
现在尝试再次爬取dmoztools.org,我们将看到爬取到的网站信息被成功输出:
scrapy crawl dmoztools
 
使用item
Item 对象是自定义的python字典。 可以使用标准的字典语法来获取到其每个字段的值。(字段即是我们之前用Field赋值的属性):
 
>>> item = DmozItem()
>>> item['title'] = 'Example title'
>>> item[‘title']
'Example title’
 
为了将爬取的数据返回,我们最终的代码将是:
 
import scrapy
from tutorial.items import DmozItem
class DmozSpider(scrapy.Spider):
    name = "dmoztools"
    allowed_domains = ["dmoztools.org"]
    start_urls = [
        "http://www.dmoztools.org/Computers/Programming/Languages/Python/Books/",
        "http://www.dmoztools.org/Computers/Programming/Languages/Python/Resources/"
    ]
 
    def parse(self, response):
        for sel in response.xpath('//ul/li'):
            item = DmozItem()
            item['title'] = sel.xpath('a/text()').extract()
            item['link'] = sel.xpath('a/@href').extract()
            item['desc'] = sel.xpath('text()').extract()
            yield item
 
现在对dmoztools.org进行爬取将会产生 DmozItem 对象:
[scrapy] DEBUG: Scraped from <200 http://www.dmoz.org/Computers/Programming/Languages/Python/Books/>
     {'desc': [u' - By David Mertz; Addison Wesley. Book in progress, full text, ASCII format. Asks for feedback. [author website, Gnosis Software, Inc.\n],
      'link': [u'http://gnosis.cx/TPiP/'],
      'title': [u'Text Processing in Python']}
[scrapy] DEBUG: Scraped from <200 http://www.dmoz.org/Computers/Programming/Languages/Python/Books/>
     {'desc': [u' - By Sean McGrath; Prentice Hall PTR, 2000, ISBN 0130211192, has CD-ROM. Methods to build XML applications fast, Python tutorial, DOM and SAX, new Pyxie open source XML processing library. [Prentice Hall PTR]\n'],
      'link': [u'http://www.informit.com/store/product.aspx?isbn=0130211192'],
      'title': [u'XML Processing with Python’]}
 
追踪链接(Following links)
接下来, 不仅仅满足于爬取 Books 及 Resources 页面, 我们想要获取获取所有 Python directory 的内容。
既然已经能从页面上爬取数据了,为什么不提取我们感兴趣的页面的链接,追踪他们, 读取这些链接的数据呢?
下面是实现这个功能的改进版spider:
 
import scrapy
from tutorial.items import DmozItem
class DmozSpider(scrapy.Spider):
    name = "dmoztools"
    allowed_domains = ["dmoztools.org"]
    start_urls = [
        "http://www.dmoztools.org/Computers/Programming/Languages/Python/",
    ]
 
    def parse(self, response):
        for href in response.css("ul.directory.dir-col > li > a::attr('href')"):
            url = response.urljoin(response.url, href.extract())
            yield scrapy.Request(url, callback=self.parse_dir_contents)
 
    def parse_dir_contents(self, response):
        for sel in response.xpath('//ul/li'):
            item = DmozItem()
            item['title'] = sel.xpath('a/text()').extract()
            item['link'] = sel.xpath('a/@href').extract()
            item['desc'] = sel.xpath('text()').extract()
            yield item
 
现在, parse() 仅仅从页面中提取我们感兴趣的链接,使用 response.urljoin 方法构造一个绝对路径的URL(页面上的链接都是相对路径的), 产生(yield)一个请求, 该请求使用 parse_dir_contents() 方法作为回调函数, 用于最终产生我们想要的数据.
 
这里展现的即是Scrpay的追踪链接的机制: 当在回调函数中yield一个Request后, Scrpay将会调度,发送该请求,并且在该请求完成时,调用所注册的回调函数。
基于此方法,我们可以根据定义的跟进链接的规则,创建复杂的crawler,并且, 根据所访问的页面,提取不同的数据.
一种常见的方法是,回调函数负责提取一些item,查找能跟进的页面的链接, 并且使用相同的回调函数yield一个 Request:
 
def parse_articles_follow_next_page(self, response):
    for article in response.xpath("//article"):
        item = ArticleItem()
 
        ... extract article data here
 
        yield item
 
    next_page = response.css("ul.navigation > li.next-page > a::attr('href')")
    if next_page:
        url = response.urljoin(next_page[0].extract())
        yield scrapy.Request(url, self.parse_articles_follow_next_page)
 
上述代码将创建一个循环,跟进所有下一页的链接,直到找不到为止 – 对于爬取博客、论坛以及其他做了分页的网站十分有效。
另一种常见的需求是从多个页面构建item的数据, 这可以使用 http://scrapy-chs.readthedocs.io/zh_CN/1.0/topics/request-response.html#topics-request-response-ref-request-callback-arguments
 
注:如果想知道如何实现一线拥有小型的规则引擎的通用spider开构建crawler, 请见CrawlSpider (http://scrapy-chs.readthedocs.io/zh_CN/1.0/topics/spiders.html#scrapy.spiders.CrawlSpider )
 
保存爬取到的数据
最简单存储爬取的数据的方式是使用 Feed exports:
scrapy crawl dmoz -o items.json
该命令将采用 JSON 格式对爬取的数据进行序列化,生成 items.json 文件。
在类似本篇教程里这样小规模的项目中,这种存储方式已经足够。 如果需要对爬取到的item做更多更为复杂的操作,可以编写 Item Pipeline 。 类似于我们在创建项目时对Item做的,用于编写自己的 tutorial/pipelines.py 也被创建。 不过如果仅仅想要保存item,我们不需要实现任何的pipeline。
 
 
还有什么?
我们已经了解了如何通过Scrapy提取存储网页中的信息,但这仅仅只是冰山一角。Scrapy提供了很多强大的特性来使得爬取更为简单高效, 例如:
 • 对HTML, XML源数据 选择及提取 的内置支持, 提供了CSS选择器(selector)以及XPath表达式进行处理, 以及一些帮助函数(helper method)来使用正则表达式来提取数据.
 • 提供 交互式shell终端 , 为测试CSS及XPath表达式,编写和调试爬虫提供了极大的方便
 • 通过 feed导出 提供了多格式(JSON、CSV、XML),多存储后端(FTP、S3、本地文件系统)的内置支持
 • 提供了一系列在spider之间共享的可复用的过滤器(即 Item Loaders),对智能处理爬取数据提供了内置支持。
 • 针对非英语语系中不标准或者错误的编码声明, 提供了自动检测以及健壮的编码支持。
 • 高扩展性。可以通过使用 signals ,设计好的API(中间件, extensions, pipelines)来定制实现我们的功能。
 • 内置的中间件及扩展为下列功能提供了支持: * cookies and session 处理 * HTTP 压缩 * HTTP 认证 * HTTP 缓存 * user-agent模拟 * robots.txt * 爬取深度限制 * 其他
 • 内置 Telnet终端 ,通过在Scrapy进程中钩入Python终端,使我们可以查看并且调试爬虫
 • 以及其他一些特性,例如可重用的,从 Sitemaps 及 XML/CSV feeds中爬取网站的爬虫、 可以 自动下载 爬取到的数据中的图片(或者其他资源)的media pipeline、 带缓存的DNS解析器,以及更多的特性。
 
References:
官方:
https://doc.scrapy.org/en/latest/index.html 
中文:
https://scrapy-chs.readthedocs.io/zh_CN/0.24/intro/tutorial.html 
https://segmentfault.com/a/1190000007073049#articleHeader13 
http://python.jobbole.com/86405/ 
通过练习来学习scrapy:
https://github.com/scrapy/quotesbot 

推荐阅读