一、Scrapy简介

    Scrapy是一个为了爬取网站数据,提取结构性数据而编写的利用框架。 能够利用在包含数据挖掘,信息处理或存储历史数据等一系列的程序中。
    其最后是为了页面抓取 (更确切来说, 网络抓取 )所设计的, 也能够利用在获取API所返回的数据(例如 Amazon Associates Web Services ) 或者通用的网络爬虫。

二、架构概览

1. Scrapy Engine

    引擎负责管制数据流在零碎中所有组件中流动,并在相应动作产生时触发事件。 具体内容查看上面的数据流(Data Flow)局部。此组件相当于爬虫的“大脑”,是整个爬虫的调度核心。

2. 调度器(Scheduler)

    调度器从引擎承受request并将他们入队,以便之后引擎申请他们时提供给引擎。
    初始的爬取URL和后续在页面中获取的待爬取的URL将放入调度器中,期待爬取。同时调度器会主动去除反复的URL(如果特定的URL不须要去重也能够通过设置实现,如post申请的URL)
3. 下载器(Downloader)
    下载器负责获取页面数据并提供给引擎,而后提供给spider。
4. Spiders
    Spider是Scrapy用户编写用于剖析response并提取item(即获取到的item)或额定跟进的URL的类。 每个spider负责解决一个特定(或一些)网站。
5. Item Pipeline
    Item Pipeline负责解决被spider提取进去的item。典型的解决有清理、 验证及长久化(例如存取到数据库中)。
    当页面被爬虫解析所需的数据存入Item后,将被发送到我的项目管道(Pipeline),并通过几个特定的秩序解决数据,最初存入本地文件或存入数据库。
6. 下载器中间件(Downloader middlewares)
    下载器中间件是在引擎及下载器之间的特定钩子(specific hook),解决Downloader传递给引擎的response。 其提供了一个简便的机制,通过插入自定义代码来扩大Scrapy性能。通过设置下载器中间件能够实现爬虫主动更换user-agent、IP等性能。
7. Spider中间件(Spider middlewares)
    Spider中间件是在引擎及Spider之间的特定钩子(specific hook),解决spider的输出(response)和输入(items及requests)。 其提供了一个简便的机制,通过插入自定义代码来扩大Scrapy性能。
8. 数据流(Data flow)
    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,引擎敞开该网站。

三、创立我的项目

    在开始抓取之前,你必须建设一个新的系统我的项目。输出要在其中存储代码并运行的目录:

    创立了一个tutorial目录蕴含以下内容:
            

四、创立第一只spider

    匍匐器是定义的类,Scrapy应用它从一个网站(或一组网站)中抓取信息。它们必须是子类 Spider 并定义要做出的初始申请,可选的是如何追随页面中的链接,以及如何解析下载的页面内容以提取数据。
    创立第一只spider的代码。将其保留在tutorial/spiders 我的项目命名文件为quotes_spider.py中:
      
    Spider子类 scrapy.Spider 并定义了一些属性和办法:
    name :标识spider。它在一个我的项目中必须是惟一的,即不能为不同的匍匐器设置雷同的名称。
    start_requests() :必须返回申请的可迭代(能够返回申请列表或编写生成器函数),匍匐器将从该申请开始匍匐。后续申请将从这些初始申请中相继生成。
    parse() :将被调用以解决为每个申请下载的响应的办法。Response参数是 TextResponse 它保留页面内容,并具备进一步有用的办法来解决它。
    这个 parse() 办法通常解析响应,将抓取的数据提取为字典,还查找要遵循的新URL并创立新申请 (Request )。
    运行创立的spider,此命令运行咱们刚刚增加的spider quotes,这将发送一些 quotes.toscrape.com 畛域。将失去相似于以下内容的输入:

    当初,查看当前目录中的文件。您应该留神到曾经创立了两个新文件: quotes-1.html 和 quotes-2.HTML, 将各个URL的内容作为 parse 办法批示。
                

五、提取数据

    scrappy提取数据的最佳办法是应用 Scrapy shell :


    应用shell,能够尝试应用 CSS 对于响应对象:

    要从上述题目中提取文本,能够执行以下操作:
          
    这里有两件事须要留神:一是咱们曾经增加了 ::text 对于CSS查问,意味着咱们只想间接抉择外部的文本元素 <title> 元素。如果咱们不指定 ::text ,咱们将取得残缺的title元素,包含其标记:
            
    另一件事是呼叫的后果 .getall() 是一个列表:选择器可能返回多个后果,因而咱们提取所有后果。只想要第一个后果时,如本例所示:
            
    作为代替,能够写下:
            
    应用 .get() 间接在A上 SelectorList 实例防止了 IndexError 回报 None 当它找不到任何与所选内容匹配的元素时。
    除 getall() 和 get() 办法以外,也能够应用 re() 提取办法 regular expressions :
      
    除 CSS外 ,scrapy选择器也反对应用 XPath 表白
  
    XPath表达式是十分弱小的,是抓取选择器的根底。实际上,CSS选择器在引擎盖下转换为xpath。xpath表达式提供了更多的性能,因为除了导航构造之外,它还能够查看内容。应用xpath,您能够抉择如下内容:抉择蕴含文本“下一页”的链接,这使得xpath非常适合于抓取工作。

六、提取援用和作者

    编写代码从网页中提取引号来实现spider程序。http://quotes.toscrape.com中的每个引号都由如下所示的HTML元素示意:

    关上Scrapy Shell并提取所需数据:

    失去了一个quote HTML元素的选择器列表,其中包含:

    下面查问返回的每个选择器都容许对其子元素运行进一步的查问。将第一个选择器调配给一个变量,这样咱们就能够间接在特定的引号上运行CSS选择器:
          
    提取 text , author以及 tags,其中tags是字符串列表,咱们能够应用 .getall() 办法获取所有这些参数:

    提取每个位之后,迭代所有的quotes元素,并将它们放在Python字典中:

    在spider中提取数据,应用 yield 回调response中的python关键字,如下所示:

    存储抓取的数据,最简略办法是应用 Feed exports ,应用以下命令:

    这将生成一个 quotes.json 蕴含所有抓取的我的项目的文件,序列化在JSON。

    这个 -O 命令行开关笼罩任何现有文件;应用 -o 而是将新内容附加到任何现有文件中。然而,附加到JSON文件会使文件内容有效JSON。附加到文件时,请思考应用不同的序列化格局,例如 JSON Lines ::


    JSON Lines 相似于流,能够很容易地向它附加新记录。当运行两次时,它不存在雷同的JSON问题。另外,因为每个记录都是独自的一行,能够解决大文件,而不用将所有内容都放入内存中,因而有如下工具: JQ以帮忙在命令行中执行此操作。
    从网站上所有页面的援用抓取内容。从页面中跟踪链接第一件事是提取到要跟踪的页面的链接。查看页面,能够看到有一个链接指向下一个带有以下标记的页面:

    在外壳中提取:

    获取到anchor元素,但须要该属性href ,Scrapy反对CSS扩大,容许抉择属性内容,如下所示:
      
    还有一个 attrib 可用属性
       
    将spider被批改为递归地跟踪下一页的链接,从中提取数据:

    在提取数据之后, parse() 办法查找到下一页的链接,并应用 urljoin() 办法(因为链接能够是绝对的),并生成对下一页的新申请,将本身注册为回调,以解决下一页的数据提取,并放弃匍匐在所有页中进行。
    scrapy的以下链接机制:在回调办法中生成一个申请时,scrapy将打算发送该申请,并注册一个回调办法,以便在该申请实现时执行。
    应用它能够构建简单的爬虫程序,这些爬虫程序依据定义的规定跟踪链接,并依据所拜访的页面提取不同类型的数据。
    示例中,创立了一种循环,跟踪到下一页的所有链接,直到找不到一个为止——这对于匍匐博客、论坛和其余带有分页的站点很不便。

七、创立申请的快捷方式

    作为创立申请对象的快捷方式,能够应用 response.follow ::
    
    不像Scrapy.Request, response.follow 间接反对绝对URL-无需调用URLJOIN。留神 response.follow 只返回一个申请实例;依然须要生成这个申请。
    也能够将选择器传递给 response.follow 而不是字符串;此选择器应提取必要的属性:
    
    为了元素有一个快捷方式: response.follow 主动应用其href属性。因而代码能够进一步缩短:
        
    要从iterable创立多个申请,能够应用 response.follow_all 取而代之的是:
    
    进一步缩短:

    另一个spider,演示回调和以下链接,抓取作者信息:



    这个spider将从主页开始,跟踪所有指向作者页面的链接,调用 parse_author 它们的回调,以及与 parse 像咱们以前看到的那样回拨。
    在这里,咱们将回调传递给 response.follow_all 作为地位参数,以使代码更短;它还实用于 Request 。
    这个 parse_author 回调定义了一个助手函数,用于从CSS查问中提取和清理数据,并用作者数据生成python dict。
    这个spider展现的另一个乏味的事件是,即便同一作者援用了很多话,咱们也不须要放心屡次拜访同一作者页面。默认状况下,scrapy过滤掉对曾经拜访过的URL的反复申请,防止了因为编程谬误而太多地拜访服务器的问题。这能够通过设置进行配置 DUPEFILTER_CLASS .

八、应用spider参数

    通过应用 -a 运行它们时的选项:

    这些论点被传给spider init 办法并默认成为spider属性。
    在本例中,为 tag 参数将通过 self.tag 。能够应用它的spider只获取带有特定标记的引号,并基于以下参数构建URL::
    
    如果你通过 tag=humor 对于这个spider,您会留神到它只拜访来自 humor 标记,如 http://quotes.toscrape.com/ta... .