Scrapy学习记录

 目录

Scrapy框架的使用

Scrapy入门

1.本节目标

2.准备工作

3.创建项目

4.创建Spider

5.创建Item

6.解析Response

7.使用Item

8.后续Request

推荐书籍:·崔庆才·著的Python3网络爬虫开发实战第2版

《正版 Python3网络爬虫开发实战第2版 崔庆才网络数据采集抓取处理分析书籍教程网络爬虫项目开发》【摘要 书评 试读】- 京东图书

本人根据此书进行python爬虫的学习并记录下学习过程中的笔记

Scrapy框架的使用

Scrapy入门

1.本节目标

  • 创建一个Scrapy项目

  • 编写一个Spider来抓取站点和处理数据

  • 初步了解Item Pipeline的功能,将抓取的内容保存

  • 运行Scrapy爬虫项目

要抓取的目标站点: Quotes to Scrape

此站点内容包括:名人名言,作者和标签

2.准备工作

需要安装好Scrapy框架

pip install Scrapy

3.创建项目

首先我们需要创建一个Scrapy项目,可以直接用命令生成,可以直接在Windows下的CMD窗口下在指定文件夹下创建,也可以在pycharm的终端下创建,项目名称可以叫作scrapytutorial,创建命令如下:

scrapy startproject scrapytutorial

执行完上述命令之后,会在你所在的当前目录生成一个名为scrapytutorial的文件夹,具体文件夹结构如下图所示

scrapy.cfg              # Scrapy部署时的配置文件
scrapytutorial          # 项目的模块,引入的时候需要从这里引入
    __init__.py
    items.py            # Items的定义,定义爬取的数据结构
    middlewares.py      # Middlewares.py的定义,定义爬取时的中间件
    pipelines.py        # Pipelines的定义,定义数据管道
    settings.py         # 配置文件
    spiders             # 放置Spiders的文件夹
    __init__.py

4.创建Spider

出现如下图所示,则创建Scrapy项目完成,接下来开始创建Spider

使用命令行创建一个Spider,比如要生成Quotes这个Spider,可以执行如下命令

cd scrapytutorial

scrapy genspider quotes quotes.toscrape.com

进入刚才创建的scrapytutorial文件夹,然后执行genspider命令。第一个参数是Spider的名称,第二个参数是网站域名。执行完毕之后,spiders文件夹中多了一个quotes.py,它就是刚刚创建的Spider,内容如下所示:

如上图,QuotesSpider就是刚才命令行自动创建的Spider,它继承了scrapy的Spider类,QuotesSpider有3个属性,分别是name,allowed_domains和start_urls,还有一个方法parse。

  • name:name是每个项目唯一的名字,用来区分不同的Spider。

  • allowed_domains:allowed_domains是允许爬取的域名,如果初始或后续的请求链接不是这个域名下的,则请求链接会被过滤掉。

  • start_urls:start_urls包含了Spider在启动时爬取的URL列表,初始请求是由它来定义的。

  • parse:parse是Spider的一个方法。

5.创建Item

Item是保存爬取数据的容器,定义了爬取结果的数据结构。它的使用方法和字典类似。相比于字典,Item多了额外的保护机制,可以避免拼写错误或者是定义字段错误。

创建Item需要继承scrapy的Item类,并且定义类型为Field的字段,这个字段就是我们要爬取的字段。

观察我们要爬的目标网站,我们可以获取到的内容有下面几项。

  • text:文本,即每条名言的内容,是一个字符串。

  • authoe:作者,即每条名言的作者,是一个字符串。

  • tags:标签,即每条名言的标签,是字符串组成的列表。

这样的话,每条爬取数据就包含这3个字段,那么我们就可以定义对应的Item,此时将items.py修改如下:

import scrapy
​
class QuteItem(scrapy.Item):
    text = scrapy.Field()
    author = scrapy.Field()
    tags = scrapy.Field()

这里,我们声明了QuteItem,继承了Item类,然后使用Field定义了3个字段,接下来爬取时我们会使用这个Item

6.解析Response

前面我们看到,parse方法的参数response是start_urls里面的链接爬取后的结果,即页面请求后得到的Response,Scrapy将其转化为了一个数据对象,里面包含了页面请求后得到的Response Status,Body等内容。所以在parse方法中,我们可以直接对response变量包含的内容进行解析,比如浏览请求结果的网页源代码,进一步分析源代码内容,或者找出结果中的链接而得到下一个请求。

我们可以看到网页中既有我们想要的结果,又有下一页的链接,这两部分内容我们都要进行处理。

首先看看网页结构。如下图所示。每一页都有多个class为quote的区块,每个区块内都包含text,author,tags。那么我们先找出所有的quote,然后提取每个quote中的内容。网页结构如下:

每一个class为quote的div标签都包含有名言,作者和标签三块部分,如下图,分别为名言,作者和标签

因此,我们可以使用CSS选择器或XPath选择器进行提取,这个过程我们可以直接借助response的css或xpath方法实现,这都是Scrapy给我们封装好的方法,直接调用即可。

在这里我们使用CSS选择器进行选择,可以将parse方法的内容进行如下改写:

def parse(self, response):
    quotes = response.css('.quote')
    for quote in quotes:
        text = quote.css('.text::text').extract_first()
        author = quote.css('.author::text').extract_first()
        tags = quote.css('.tags .tag::text').extract()

这里首先利用CSS选择器选取所有的quote并将其赋值为quotes变量,然后利用for循环遍历每个quote,解析每个quote的内容

对text来说,观察到它的class为text,所用可以用.text选择器来选取,这个结果实际上是整个带有标签的节点,要获取它的正文内容,可以加::text。这时的结果是长度为1的列表,所以还需要用extract_first方法来获取第一个元素,而对于tags来说,由于我们要获取所有的标签,所以用extract方法获取整个列表即可。

为了更好地理解以上内容的提取过程,我们以第一个quote的结果为例,看一下各个提取写法会得到怎样的提取结果。源码如下:

<div class="quote" itemscope itemtype="http://schema.org/CreativeWork">
    <span class="text" itemprop="text">“The world as we have created it is a process of our thinking. It cannot be changed without changing our thinking.”</span>
    <span>by <small class="author" itemprop="author">Albert Einstein</small>
        <a href="/author/Albert-Einstein">(about)</a>
    </span>
    <div class="tags">
        Tags:
        <meta class="keywords" itemprop="keywords" content="change,deep-thoughts,thinking,world" /    > 
        <a class="tag" href="/tag/change/page/1/">change</a>
        <a class="tag" href="/tag/deep-thoughts/page/1/">deep-thoughts</a>
        <a class="tag" href="/tag/thinking/page/1/">thinking</a>
        <a class="tag" href="/tag/world/page/1/">world</a>
    </div>
</div>

不同选择器的返回结果如下:

quote.css('.text') 
​
[<Selector xpath="descendant-or-self::*[@class and contains(concat(' ', normalize-space(@class), ' '), 'text')]"data='<span class="text"itemprop="text">"The "'>]
quote.css('.text::text') 
​
[<Selector xpath="descendant-or-self::*[@class and contains(concat(' ', normalize-space(@class), ' '), 'text')]/text()"data='"The world as we have created it is a pr'>]
quote.css('.text').extract() 
​
['span class="text"itemprop="text">"The world as we have created it is a process of our thinking.It cannot be changed without changing our thinking."</span>']
quote.css('.text::text').extract()
​
['"The world as we have created it is a process of our thinking.It cannot be changed without changing our thinking."']
quote.css('.text::text').extract_first()
​
"The world as we have created it is a process of our thinking.It cannot be changed without changing our thinking."

这里我们演示了不同提取过程的写法,其提取结果也是各不相同,比如单独调用css方法我们得到的是Selector对象组成的列表;调用extract方法会进一步从Selector对象里提取其内容,在加上::text则会从HTML代码中提取出正文文本

因此对于text,我们只需要获取结果的第一个元素即可,所以使用extract_first方法,得到的就是一个字符串。而对于tags,我们要获取所有结果组成的列表,所以使用extract方法,得到的就是所有标签字符串组成的列表。

def parse(self, response):
    quotes = response.css('.quote')
    for quote in quotes:
        text = quote.css('.text::text').extract_first()
        author = quote.css('.author::text').extract_first()
        tags = quote.css('.tags .tag::text').extract()

7.使用Item

上文我们已经定义了QuoteItem,接下来就要使用它了。

我们可以把Item理解为一个字典,和字典还不太相同,其本质是一个类,所以在使用的时候需要实例化。实例化之后,我们一次用刚才解析的结果赋值Item的每一个字段,最后将Item返回。

QuotesSpider的改写如下:

import scrapy
from scrapytutorial.items import QuoteItem
​
class QuotesSpider(scrapy.Spider):
    name = 'quotes'
    allowed_domains = ['quotes.toscrape.com']
    start_urls = ['http://quotes.toscrape.com/']
​
    def parse(self, response):
        quotes = response.css('.quote')
        for quote in quotes:
            item = QuoteItem()
            item['text'] = quote.css('.text::text').extract_first()
            item['author'] = quote.css('.author::text').extract_first()
            item['tags'] = quote.css('.tags .tag::text').extract()
            yield item

如此一来,首页的所以内容就被解析出来并被复制成一个个QuoteItem了,每个QuoteItem就代表一条名言,包含名言内容,作者和标签。

8.后续Request

上面的操作实现了从首页抓取内容,如果运行它,我们其实已经可以从首页提取到所有quote信息并转化为一个个QuoterItem对象了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

bug智造

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值