美文网首页我爱编程
爬虫-Scrapy 快速入门指南

爬虫-Scrapy 快速入门指南

作者: losangele | 来源:发表于2018-03-05 15:19 被阅读0次

    简介


        Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架。 可以应用在包括数据挖掘,信息处理或存储历史数据等一系列的程序中。

        其最初是为了 页面抓取 (更确切来说, 网络抓取 )所设计的, 也可以应用在获取API所返回的数据或者通用的网络爬虫。

    使用建议,爬取数据的时候为了防止ip地址被封禁,有以下几个建议:

    1.修改配置文件伪造session信息。

    2.抓取间隔时间尽量要长。

    3.通过代理使用ip地址池,循环使用,避免使用一个地址。

    4.请求透过Tor Browser,防止自身ip被禁。


    安装


        由于scrapy依赖的安装包很多,所以推荐使用pip工具实现快速安装。安装命令如下:pip install Scrapy 。其他安装方式可以参考官方文档。

        注:先下载pip安装文件,下载地址:https://bootstrap.pypa.io/get-pip.py,然后运行pip安装命令:python get-pip.py。


    实例


          将抓取quotes.toscrape.com网站数据,这是一个列出著名作家引用的网站。

        本教程将引导您完成这些任务:

        1.创建一个新的Scrapy项目

        2.编写爬虫抓取网站并提取数据

        3.使用命令行导出抓取的数据

        4.更改爬虫递归跟随链接

        5.使用爬虫参数


    创建Scrapy项目


        选择工程存放目录,创建名为tutorial的工程,然后运行如下命令:scrapy startproject tutorial.

    这将创建一个包含以下内容的tutorial目录:

    tutorial/

        scrapy.cfg  # 部署配置文件

        tutorial/ #项目的Python模块,从这里导入你的代码

            __init__.py

            items.py  # 项目提取字段定义文件

            middlewares.py # 项目中间件文件,用于定义属于自己特殊应用的中间件

            pipelines.py # 项目管道文件

            settings.py # 项目配置文件

            spiders/ #编写自己抓取各种数据方法目录

                __init__.py


    编写Spider


        Spiders是自己定义的类,Scrapy用来从网站(或一组网站)上抓取信息。 他们必须对scrapy.Spider进行子类化并定义初始请求,可选择如何关注页面中的链接,以及如何解析下载的页面内容以提取数据。

        在tutorial/spiders目录下,创建名为quotes_spider.py的文件,用于编写具体的抓取方法。

        实例代码如下:

    import scrapy

    class QuotesSpider(scrapy.Spider):

        name="quotes" #爬虫的名称,启动爬虫时需要该爬虫名称。

        def start_requests(self):

            urls=[

                'http://quotes.toscrape.com/page/1/',

                'http://quotes.toscrape.com/page/2/',

            ]

            for url in urls:

                yield scrapy.Request(url=url, callback=self.parse)

        def parse(self, response):

            page=response.url.split("/")[-2]

            filename='quotes-%s.html'%page

            with open(filename, 'wb') as f:

                f.write(response.body)

                self.log('Saved file %s'%filename)

        为Spider子类(QuotesSpider)scrapy.Spider定义了一些属性和方法:

        名称:爬虫名字。 它在项目中必须是唯一的,也就是说,不能为不同的爬虫设置相同的名称。

        start_requests():必须返回一个迭代请求(你可以返回一个请求列表或者写一个生成器函数),Spider将开始抓取它。 随后的请求将从这些初始请求中连续生成。

        parse():将被调用来处理为每个请求下载的响应的方法。 响应参数是TextResponse的一个实例,用于保存页面内容,并有更多有用的方法来处理它。

        parse()方法通常解析响应,将提取的数据提取为字符串,并找到新的URL来跟踪并创建新的请求(Request)。


    如何启动爬虫


        在工程的同级目录运行命令:scrapy crawl quotes。

         该命令使用刚刚添加的名称引号运行该爬虫,该爬虫将向quotes.toscrape.com域发送一些请求。 你会得到类似于这样的输出:

    ...(omittedforbrevity)

    2016-12-16 21:24:05[scrapy.core.engine] INFO: Spider opened

    2016-12-16 21:24:05[scrapy.extensions.logstats] INFO: Crawled 0 pages(at 0 pages/min), scraped 0 items(at 0 items/min)

    2016-12-16 21:24:05[scrapy.extensions.telnet] DEBUG: Telnet console listening on 127.0.0.1:6023

    ....

        现在,检查当前目录中的文件。 您应该注意到已经创建了两个新文件:quotes-1.html和quotes-2.html,以及相应URL的内容,正如分析方法指示的那样。


    爬虫运行的原理


        Scrapy安排由Spider的start_requests方法返回的scrapy.Request对象。 在收到每个响应后,它会实例化Response对象,并调用与请求相关的回调方法(在本例中为parse方法),将响应作为参数传递。

        除了实现从URL生成scrapy.Request对象的start_requests()方法外,您还可以使用URL列表定义start_urls类属性。 这个列表将被默认的start_requests()实现用来为你的爬虫创建初始请求:

    import    scrapy

    class    DmozSpider(scrapy.spiders.Spider):

        name="dmoz"

        allowed_domains=["dmoz.org"]

        start_urls=    ["http://www.dmoz.org/Computers/Programming/Languages/Python/Books/","http://www.dmoz.org/Computers/Programming/Languages/Python/Resources/"]   

        def    parse(self,response):    

            filename=response.url.split("/")[-2]

            with    open(filename,'wb')asf:

                    f.write(response.body)

        该实例将调用parse()方法来处理这些URL的每个请求,即使没有明确告诉Scrapy这样做。 发生这种情况是因为parse()是Scrapy的默认回调方法,该方法在未显式分配回调的情况下针对请求调用。


    提取数据


    学习如何使用Scrapy提取数据的最佳方法是使用Scrapy shell,运行:

    scrapy  shell  'http://quotes.toscrape.com/page/1/'

    输出如下:

    [...Scrapyloghere...]2016-09-1912:09:27[scrapy.core.engine]DEBUG:Crawled(200)<GEThttp://quotes.toscrape.com/page/1/>(referer:None)[s]AvailableScrapyobjects:[s]scrapyscrapymodule(containsscrapy.Request,scrapy.Selector,etc)[s]crawler<scrapy.crawler.Crawlerobjectat0x7fa91d888c90>[s]item{}[s]request<GEThttp://quotes.toscrape.com/page/1/>[s]response<200http://quotes.toscrape.com/page/1/>[s]settings<scrapy.settings.Settingsobjectat0x7fa91d888c10>[s]spider<DefaultSpider'default'at0x7fa91c8af990>[s]Usefulshortcuts:[s]shelp()Shellhelp(printthishelp)[s]fetch(req_or_url)Fetchrequest(orURL)andupdatelocalobjects[s]view(response)Viewresponseinabrowser>>>

    查看包含 [dmoz] 的输出,可以看到输出的log中包含定义在 start_urls 的初始URL,并且与spider中是一一对应的。在log中可以看到其没有指向其他页面( (referer:None) )。

    除此之外,更有趣的事情发生了。就像parse 方法指定的那样,有两个包含url所对应的内容的文件被创建了: Book , Resources 。

    刚才发生了什么?

    Scrapy为Spider的 start_urls 属性中的每个URL创建了 scrapy.Request 对象,并将 parse 方法作为回调函数(callback)赋值给了Request。

    Request对象经过调度,执行生成 scrapy.http.Response 对象并送回给spider parse() 方法。

    提取Item

    Selectors选择器简介

    从网页中提取数据有很多方法。Scrapy使用了一种基于 XPath 和 CSS 表达式机制: Scrapy Selectors。 关于selector和其他提取机制的信息请参考 Selector文档 。

    这里给出XPath表达式的例子及对应的含义:

    /html/head/title: 选择HTML文档中 <head> 标签内的 <title> 元素

    /html/head/title/text(): 选择上面提到的 <title> 元素的文字

    //td: 选择所有的 <td> 元素

    //div[@class="mine"]: 选择所有具有 class="mine" 属性的 div 元素

    上边仅仅是几个简单的XPath例子,XPath实际上要比这远远强大的多。 如果您想了解的更多,推荐官方文档。

    为了配合XPath,Scrapy除了提供了 Selector 之外,还提供了方法来避免每次从response中提取数据时生成selector的麻烦。

    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.dmoz.org/Computers/Programming/Languages/Python/Books/"

    注解

    当您在终端运行Scrapy时,请一定记得给url地址加上引号,否则包含参数的url(例如 & 字符)会导致Scrapy运行失败。

    shell的输出类似:

    [...Scrapyloghere...]2015-01-0722:01:53+0800[domz]DEBUG:Crawled(200)<GEThttp://www.dmoz.org/Computers/Programming/Languages/Python/Books/>(referer:None)[s]AvailableScrapyobjects:[s]crawler<scrapy.crawler.Crawlerobjectat0x02CE2530>[s]item{}[s]request<GEThttp://www.dmoz.org/Computers/Programming/Languages/Python/Books/>[s]response<200http://www.dmoz.org/Computers/Programming/Languages/Python/Books/>[s]sel<Selectorxpath=Nonedata=u'<html lang="en">\r\n<head>\r\n<meta http-equ'>[s]settings<CrawlerSettingsmodule=<module'tutorial.settings'from'tutorial\settings.pyc'>>[s]spider<DomzSpider'domz'at0x302e350>[s]Usefulshortcuts:[s]shelp()Shellhelp(printthishelp)[s]fetch(req_or_url)Fetchrequest(orURL)andupdatelocalobjects[s]view(response)Viewresponseinabrowser>>>

    当shell载入后,您将得到一个包含response数据的本地 response 变量。输入 response.body 将输出response的包体, 输出 response.headers 可以看到response的包头。

    更为重要的是,当输入 response.selector 时, 您将获取到一个可以用于查询返回数据的selector(选择器), 以及映射到 response.selector.xpath() 、 response.selector.css() 的 快捷方法(shortcut): response.xpath() 和 response.css() 。

    同时,shell根据response提前初始化了变量 sel 。该selector根据response的类型自动选择最合适的分析规则(XML vs HTML)。

    来试试:

    In[1]:sel.xpath('//title')

    Out[1]:[<Selectorxpath='//title'data=u'<title>Open Directory - Computers: Progr'>]

    In[2]:sel.xpath('//title').extract()

    Out[2]:[u'<title>Open Directory - Computers: Programming: Languages: Python: Books</title>']

    In[3]:sel.xpath('//title/text()')

    Out[3]:[<Selectorxpath='//title/text()'data=u'Open Directory - Computers: Programming:'>]

    In[4]:sel.xpath('//title/text()').extract()

    Out[4]:[u'Open Directory - Computers: Programming: Languages: Python: Books']

    In[5]:sel.xpath('//title/text()').re('(\w+):')

    Out[5]:[u'Computers',u'Programming',u'Languages',u'Python']

    提取数据

    现在,来尝试从这些页面中提取些有用的数据。

    您可以在终端中输入 response.body 来观察HTML源码并确定合适的XPath表达式。不过,这任务非常无聊且不易。您可以考虑使用Firefox的Firebug扩展来使得工作更为轻松。详情请参考 使用Firebug进行爬取 和 借助Firefox来爬取 。

    在查看了网页的源码后,您会发现网站的信息是被包含在 第二个 <ul> 元素中。

    可以通过这段代码选择该页面中网站列表里所有 <li> 元素:

    sel.xpath('//ul/li')

    网站的描述:

    sel.xpath('//ul/li/text()').extract()

    网站的标题:

    sel.xpath('//ul/li/a/text()').extract()

    以及网站的链接:

    sel.xpath('//ul/li/a/@href').extract()

    之前提到过,每个 .xpath() 调用返回selector组成的list,因此可以拼接更多的 .xpath() 来进一步获取某个节点。将在下边使用这样的特性:

    forselinresponse.xpath('//ul/li'):title=sel.xpath('a/text()').extract()link=sel.xpath('a/@href').extract()desc=sel.xpath('text()').extract()printtitle,link,desc

    注解

    关于嵌套selctor的更多详细信息,请参考 嵌套选择器(selectors) 以及 选择器(Selectors) 文档中的 使用相对XPaths 部分。

    在spider中加入这段代码:

    import    scrapy    

    class    DmozSpider(scrapy.Spider):

            name="dmoz"allowed_domains=["dmoz.org"]

            start_urls=    ["http://www.dmoz.org/Computers/Programming/Languages/Python/Books/","http://www.dmoz.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()

            printtitle,link,desc

    现在尝试再次爬取dmoz.org,您将看到爬取到的网站信息被成功输出:

    scrapy    crawl    dmoz

    使用item

    Item 对象是自定义的python字典。 您可以使用标准的字典语法来获取到其每个字段的值。(字段即是之前用Field赋值的属性):

    >>> item=DmozItem()>>> item['title']='Example title'>>> item['title']'Example title'

    一般来说,Spider将会将爬取到的数据以 Item 对象返回。所以为了将爬取的数据返回,最终的代码将是:

    import    scrapy    

    from    tutorial.items    import    DmozItem    

    class    DmozSpider(scrapy.Spider):

        name="dmoz"allowed_domains=["dmoz.org"]

        start_urls=    ["http://www.dmoz.org/Computers/Programming/Languages/Python/Books/","http://www.dmoz.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

    注解

    您可以在 dirbot 项目中找到一个具有完整功能的spider。该项目可以通过 https://github.com/scrapy/dirbot 找到。

    现在对dmoz.org进行爬取将会产生 DmozItem 对象:

    [dmoz]DEBUG:Scrapedfrom<200http://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']}[dmoz]DEBUG:Scrapedfrom<200http://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']}

    保存爬取到的数据

    最简单存储爬取的数据的方式是使用 Feed exports:

    scrapy    crawl    dmoz-oitems.json

    该命令将采用 JSON 格式对爬取的数据进行序列化,生成 items.json 文件。

    在类似本篇教程里这样小规模的项目中,这种存储方式已经足够。 如果需要对爬取到的item做更多更为复杂的操作,您可以编写 Item Pipeline 。 类似于我们在创建项目时对Item做的,用于您编写自己的 tutorial/pipelines.py 也被创建。 不过如果您仅仅想要保存item,您不需要实现任何的pipeline。

    相关文章

      网友评论

        本文标题:爬虫-Scrapy 快速入门指南

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