利用Scrapy框架写爬虫(入门篇)

爬虫项目来自scrapy官网,解析方法由scrapy自带的css解析和xpath解析。下附scrapy官网链接。
建议在有些前端基础的条件下查看这篇博客。

scrapy官网


一.scrapy简单介绍

scrapy是爬虫的框架,使用scrapy可以编写高效的大型爬虫,安装方法可以通过pip install scrapy来进行安装。


1.scrapy框架结构解析

scrapy有7项核心组件,我们需要了解他们的功能和运行流程。

引擎(Engine):是scrapy的“大脑”,帮助我们高效爬取并行处理数据的。
调度器(Scheduler):调度器接受引擎发过来的请求,按照先后顺序,压入列队中,同时去除重复的请求。
下载器(Downloader):下载器用于下载网页内容,并返回给爬虫,就是scrapy中的Request组件。
爬虫(Spiders):用于从特定的网页中提取需要的信息,对提取出的链接,可以发起下一次请求。
项目(Item Pipelines):项目管道负责处理爬虫从网页中抽取出的实体,并且保存成文件或存入数据库中。
另外还有下载器中间件(Downloader Middlewares)和 爬虫中间体(Spider Middlewares )就不过多介绍了,详情可以查看官网链接。

  • scrapy运行流程解析

其中Spiders和pipeline 是需要我们去修改的,其他组件无需修改,框架已写好
scrapy组件运行流程

  1. 首先,引擎根据我们填写的域名(例如,要爬取豆瓣,则域名为 douban.com )找到相应的Sipders组件,然后Spiders组会对爬取的url进行发送请求,发起的信息由绿色的线先后传入到调度器,并在调度器中进行去重操作。
  2. 并根据请求的传入顺序,Scheduler会将请求再发给引擎,再由引擎发送给下载器。其中Downloader相当于requests方法,对网页真正发起请求,请求过后不论成功失败都有一个返回,也由Downloader接受返回信息。(Downloader Middlewares)是一个下载中间件,可以起到一个过滤的作用。
  3. 返回后的数据交给引擎再交给Spiders.
  4. Spiders后有两个方向,其中一个是items最终传入的是Item Pipeline,对返回数据对实体化操作,进行文件保存等。
  5. 第二个是Requests,其中反映了框架的优势,不需要再次编写requests的条件。

2. scrapy爬虫目录结构解析

  1. 打开终端,再当前目录下创建了名为quotes的quotes项目$ scrapy startproject quotes
  2. 并且根据提示进入quotes文件夹内 $ cd quotes
  3. 再进入spiders文件夹内 $cd spiders
  4. 创建quote_css.py 爬虫,$ scrapy genspider quote_css "quotes.toscrape.com",其中"quotes.toscrape.com"为要爬取的网页的域名,例如,豆瓣的域名为"douban.com",会影响scrapy里的基本设置,最好根据需要填写。(注意:一个项目里可以包含多个Spiders,例如 $ scrapy genspider quote_xpath "quotes.toscrape.com"再同一个项目内创建了quote_xpath.py爬虫。

创建好后的目录结构
5.调用爬虫,scrapy框架书写的爬虫,不能直接运行,需要在终端,在quotes/quotes 目录下 $scrapy crawl quote_css运行。
6.将返回内容保存为json文件,同样也需要在quotes/quotes 目录下 $ scrapy crawl quote_css -o quotes.json

二、实战案例:quotes信息爬取

用scrapy自带的css和xpath来解析网页,目标网页是http://quotes.toscrapy.com/,爬取目标是网页中的名言,作者,和标签,即图中箭头所指的三个部分
在这里插入图片描述

1.方法一:使用css解析数据

css主要是通过css来确定位置

打开quote_css.py文件,默认内容为,其中我们需要改写parse解析方法,parse第一次请求内容是对start_urls发起的,且是默认发起的,不需要我们再去编写requests。我们需要关注的是数据本身,怎么从返回取出我们想要的结果。

目标:爬取目标网站的quote,author,tag,爬取结果保存为json文件,并且找到文末的next链接,一直跳转爬取
基本想法:找到quote, author,tag所在html中的位置,并找规律

import scrapy


class QuoteCssSpider(scrapy.Spider):
    name = 'quote_css'
    allowed_domains = ['quotes.toscrape.com']#域名
    start_urls = ['http://quotes.toscrape.com/']

    def parse(self, response):
        pass
        

1.首先利用开发者工具可以发现:每页有10条quote,每段quote都在class属性为quote的div标签下,可以利用 response.css(‘div.quote’)获取。
由开发者工具可得

为了更好的了解scrapy是如何去数的,可以使用shell启动scrapy 终端,$ scrapy shell url表示我们要爬取的网页, scrapy shell http://quotes.toscrape.com/,返回的reponse为scrapy的html对象,验证class属性为quote的div标签下是否为quotes

response.css('div.quote').getall()
response.css('div.quote').get()

结果如下图所示
在这里插入图片描述其中getall()返回的是满足条件的所有值,返回的是列表
get()返回的满足条件的第一个值

2 依次在div标签下找到text内容,author作者和tag标签的位置,并取出里面的文本内容.由开发者工具我们可以看到,text内容在div下一节的class属性为text的span标签下,先另quote为第一个div标签,再以此为节点向下探,可以通过quote.css('span.text::text')取得,并将取出的数据依次命名为text,author,tag,可以在scrapy shell中取得验证,结果如图所示
text
其中:text()表示取出其中的文本内容

同理可以取出author和tag中的内容,author在div的第二个span标签下的small标签内,其中small 的 class属性为author;tag在div的div标签下的多个标签内,其中a的class属性为tag,验证结果如下,数据解析成功
author,tag
3.为了将取出的数据反映在终端上,可以使用yield.,显示结果如下
yield{'text':text, 'author':author,'tag':tag}

4.到此我们已经完整地取出了一页的内容,之后需要实现的页面的跳转,要求需要在html中获取下一页的链接,(或者根据url自己找规律)并再链接发送请求
next
由图可以发现,下一页的链接在class属性为next的li标签下的a标签内,且发现链接是不完整的需要我们自己补全。取出内容,命名为next_url

response.css('li.next>a::attr(href)').get()
href
scrapy提供了补全url的方法,urljoin()
请求补全后的链接代码可以写为scrapy.Request(response.urljoin(next_url))

quote_css.py中的完整代码

import scrapy


class QuoteCssSpider(scrapy.Spider):
    name = 'quote_css'
    allowed_domains = ['quotes.toscrape.com']#域名
    start_urls = ['http://quotes.toscrape.com/']

    def parse(self, response):
        quotes=response.css('div.quote')
        #寻找class属性为quote的div标签
        for quote in quotes:
            text=quote.css('span.text::text').get()
            #从quote所在的div节点往下class属性为text的span标签,:text表示取出其中的文字
            #get()是将html内容转化为str
            author=quote.css('small.author::text').get()
            #从quote所在的div节点往下class属性为author的small标签,并取出其中的文字
            tag=quote.css('div.tags >  a.tag::text').getall()
            yield {
                'text':text,
                'author':author,
                'tag':tag
            }
            #找到下一页的url继续爬取内容
        next_url=response.css('li.next>a::attr(href)').get()
        if next_url is not None:
            yield scrapy.Request(response.urljoin(next_url))

在终端输入$ scrapy crawl quote_css运行爬虫,输出结果为:
quote_css
爬取成功,如果要将爬取结果保存为json文件,可以在终端输入$ scrapy crawl quote_css -o quotes.json

2.方法二:使用xpath来解析数据

目标:爬取目标网站的quote,author,tag,爬取结果保存为csv文件,并且找到文末的next链接,一直跳转爬取
步骤:
1.利用开发者工具找到需要爬取的text,author,tag所在节点的位置
2.利用scrapy验证位置
3.完整爬取一页的代码,运行查错
4.若3运行没有出错,爬取下一页的链接,并发送请求,运行查错
5.修改pipeline,item,将输出文件保存为csv文件,运行查错
quote
quote_xpath.py的完整代码
注意tag取出数据是为多个字符串组成的列表,因后续保存的需要,因转变为一项内容,可以像下面代码中操作,也可以直接在外面套[],使之成为外面大括号内的第零项

import scrapy
from quotes.items import QuotesItem


class QuoteXpathSpider(scrapy.Spider):
    name = 'quote_xpath'
    allowed_domains = ['quotes.toscrape.com']
    start_urls = ['http://quotes.toscrape.com/']

    def parse(self, response):
        items=[]
        quotes=response.xpath('//div[@class="quote"]')
        for quote in quotes:
            item = QuotesItem()
            text=quote.xpath('./span/text()').extract_first()
            author=quote.xpath('./span/small[@class="author"]/text()').extract_first()
            tag=quote.xpath('.//div[@class="tags"]/a[@class="tag"]/text()').extract()
            item['text']=text
            item['author']=author
            item['tag']=[[i.strip() for i in tag]]
            items.append(item)
            yield item

        next_url=response.xpath('//li[@class="next"]/a/@href').extract_first()
        if next_url is not None:
            next_url=response.urljoin(next_url)
            yield scrapy.Request(next_url)

items.py的完整代码
对items进行了修改,左边为我们所需要的数据,右边为固定写法

import scrapy


class QuotesItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    # pass
    text=scrapy.Field()
    author=scrapy.Field()
    tag=scrapy.Field()

pipelines.py的完整代码
在传递的item中取出所需要的text, author,tag使用pandas模块将数据以追加方式写入quotes.csv文件
注意
1.最后的return不能少,不然会报错
2.在将字典转换为DataFrame类型时,要加标签,不然会报错
3.不能直接将item转变为DataFrame类型
4.最重要的是,必须要修改settings中的一项才能保存!!!

import pandas as pd

class QuotesPipeline:
    def process_item(self, item, spider):
        df=pd.DataFrame({'text':item['text'],'author':item['author'],'tag':item['tag']},index=[0])
        df.to_csv('./quotes.csv',mode='a+',encoding='utf8',index=False,header=False)
        return item

必须要将settings中的ITEM_PIPELINES取消注释才能保存
settings
最后在终端运行$scrapy crawl quote_xpath命令检查输出
最后输出结果如下
output


总结

scrapy 框架在进行大型爬取工作时比较方便,scrapy内部有自己的解析工具,运行效率较高。掌握scrapy爬虫的前提应该需要了解scrapy各组件的功能和实际工作时的搭配。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值