Python Scrapy趣味爬虫

Scrapy爬虫Section1

了解更多爬虫知识,点击访问我的博客!!!

认识Scrapy爬虫

网络爬虫是指在互联网上自动爬取网站内容信息的程序,也被称作网络蜘蛛或网络机器人。大型的爬虫程序被广泛应用于搜索引擎、数据挖掘等领域,个人用户或企业也可以利用爬虫收集对自身有价值的数据。

网络爬虫的基本执行流程

在这里插入图片描述

  • 下载页面

    一个网页的内容本质上就是一个HTML文本,爬取一个网页内容之前,首先要根据网页的URL下载网页。

  • 提取页面数据

    当一个网页(HTML)下载完成后,对页面中的内容进行分析,并提取出我们感兴趣的数据,提取到的数据可以以多种形式保存起来,比如将数据以某种格式(CSV、JSON)写入文件中,或存储到数据库(MySQL、MongoDB)中。

  • 提取页面链接

    通常,我们想要获取的数据并不只在一个页面中,而是分布在多个页面中,这些页面彼此联系,一个页面中可能包含一个或多个到其他页面的链接,提取完当前页面中的数据后,还要***把页面中的某些链接也提取出来***,然后对链接页面进行爬取(循环1-3步骤)。

使用Python可以从头开始写一个爬虫程序,为了避免因制造轮子 而消耗大量时间,在实际应用中我们可以选择使用一些优秀的爬虫框 架,使用框架可以降低开发成本,提高程序质量。所以就有了***Scrapy***的出现。

Scrapy的安装

pip install scrapy

在这里插入图片描述

出现图示则代表安装成功。

编写Spider(Scrapy 爬虫程序中最核心的组件)

Scrapy框架结构及工作原理

在这里插入图片描述

对***各个组件***的介绍如下图所示

在这里插入图片描述

对框架中的***数据流***介绍如图所示

在这里插入图片描述

Request和Response是HTTP协议中的术语,即HTTP请求和 HTTP响应,Scrapy框架中定义了相应的Request和Response类,这里的Item代表Spider从页面中爬取的一项数据。

数据在框架中的流动过程

  • 当SPIDER要爬取某URL地址的页面时,需使用该URL构造一个Request对象,提交给ENGINE。

  • Request对象随后进入SCHEDULER按某种算法进行排队,之后的某个时刻SCHEDULER将其出队,送往DOWNLOADER。

  • DOWNLOADER根据Request对象中的URL地址发送一次HTTP请求 到网站服务器,之后用服务器返回的HTTP响应构造出一个Response对象,其中包含页面的HTML文本。

  • Response对象最终会被递送给SPIDER的页面解析函数(构造Request对象时指定)进行处理,页面解析函数从页面中提取数据,封装成Item后提交给ENGINE,Item之后被送往ITEM

    PIPELINES进行处理,最终可能由EXPORTER以某种数据格式写入文件(csv,json);另一方面,页面解析函数还从页面中提取链接(URL),构造出新的 Request对象提交给ENGINE。

Request对象

Request对象用来描述一个HTTP请求,下面是其构造器方法的参数列表:

Request(url[, callback, method=‘GET’, headers, body, cookies, meta, encoding=‘utf-8’, priority=0, dont_filter=False,errback,flags])

Request参数介绍:

  • url(必选)

    请求页面的url地址,bytes或str类型。

  • callback

    页面解析函数, Callable类型,Request对象请求的页面下载完成后,由该参数指定的页面解析函数被调用。如果未传递该参数,默认***调用Spider的parse***方法。

  • method

    HTTP请求的方法,默认为’GET。

在这里插入图片描述
在这里插入图片描述

虽然参数很多,但除了url参数外,其他都带有默认值。在构造Request对象时,通常我们只需传递一个url参数或再加一个callback参数,其他使用默认值即可。

>>> request = scrapy.Request(‘http://books.toscrape.com/’)

Response对象

Response对象用来描述一个HTTP响应,Response只是一个基类,根据响应内容的不同有如下子类:

  • TextResponse
  • HtmlResponse
  • XmlResponse

当一个页面下载完成时,下载器依据HTTP响应头部中的 Content-Type信息创建某个Response的子类对象。我们通常爬取的网页,其内容是HTML文本,创建的便是HtmlResponse对象,其 中***HtmlResponse和XmlResponse是TextResponse的子类***。实际上,这3个子类只有细微的差别

HtmlResponse对象的属性与方法
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

Spider开发流程

爬虫开发的逻辑:

在这里插入图片描述

import scrapy
from ..items import BookItem
from scrapy.linkextractors import LinkExtractor
class BooksSpider(scrapy.Spider):
    # 爬虫名,每一个爬虫的唯一标识
    name = 'books'
    # 第 1 章 1.3.4 实现 Spider
    # 定义爬虫爬取的起始点,起始点可以是多个,这里只有一个。
    #start_urls = ['http://books.toscrape.com/']

    # 第 2 章 2.3.3 设定起始爬取点
    # 实现 start_resquests 方法代替start_urls类属性
    def start_requests(self):
        yield scrapy.Request('http://books.toscrape.com/',
                             callback=self.parse,
                             headers={'User-Agent':'Mozill/5.0'},
                             dont_filter=True)

    def parse(self, response):
        # 提取数据
        # 重写
        for sel in response.css('article.product_pod'):
            book = BookItem() # from ..items import BookItem 类
            book['name'] = sel.xpath('./h3/a/@title').extract_first()
            book['price'] = sel.css('p.price_color::text').extract_first()
            yield book

        # 第 1 章 1.3.4 实现 Spider
        # 以下代码值直接保存,没有通过 Item 封装数据
        # for book in response.css('article.product_pod'):
            # name = book.xpath('./h3/a/@title').extract_first()
            # price = book.css('p.price_color::text').extract_first()
            # yield {
            #     'name': name,
            #     'price': price
            # }

        # 第 1 章 1.3.4 实现 Spider
        # 直接用 Selector 提取下一页链接 (没有用 LinkExtractor 提取链接)
        # 下一页链接在 ul.pager > li.next > a 里
        '''
        <ul class="pager">          
            <li class="current"> Page 1 of 50 </li>           
            <li class="next"><a href="catalogue/page-2.html">next</a></li>            
        </ul>
        #default > div > div > div > div > section > div:nth-child(2) > div > ul.pager > li.next > a
        '''
        # next_url = response.css('ul.pager li.next a::attr(href)').extract_first()
        # if next_url:
        #     next_url = response.urljoin(next_url)
        #     yield scrapy.Request(next_url, callback=self.parse)

        # 第6章 使用 LinkExtractor 提取链接
        # 提取下一页链接重写(用 LinkExtractor提取)
        # 说明 from scrapy.linkextractors import LinkExtractor
        le = LinkExtractor(restrict_css='ul.pager li.next')
        links = le.extract_links(response)
        # print(type(links),links)
        if links:
            # 用links[0]获取的Link对象属性是绝对链接地址,无需要用response.urljoin拼接
            next_url = links[0].url
            yield scrapy.Request(next_url, callback=self.parse)

在这里插入图片描述

继承scrapy.Spider

Scrapy框架提供了一个Spider基类,我们编写的Spider需要继承它

import scrapy

class BooksSpider(scrapy.Spider):

这个Spider基类实现了以下内容:

  • 供Scrapy引擎调用的接口,例如用来创建Spider实例的类方法from_crawler。

● 供用户使用的实用工具函数,例如可以调用log方法将调试信息输出到日志。

● 供用户访问的属性,例如可以通过settings属性访问配置文件中的配置。

为Spider命名

在一个Scrapy项目中可以实现多个Spider,每个Spider需要有一个能够区分彼此的唯一标识,Spider的类属性name便是这个唯一标识。

class BooksSpider(scrapy.Spider): 
    name = "books" 
    	...

执行scrapy crawl命令时就用到了这个标识,告诉Scrapy使用哪个Spider进行爬取。

设定起始爬取点

Spider必然要从某个或某些页面开始爬取,我们称这些页面为***起始爬取点***,可以通过类属性start_urls来设定起始爬取点:

class BooksSpider(scrapy.Spider): 
    ... 
    start_urls = ['http://books.toscrape.com/']
    ...

start_urls通常被实现成一个列表,其中放入所有起始爬取点的url。

请求页 面下载一定要提交Request对象,这时候,我们仅仅定义了URL列表,Spider基类的start_requests方法帮助我们基于URL构造并提交了Request对象。

class Spider(object_ref):
    ...
    def start_requests(self): 
        for url in self.start_urls: 
            yield self.make_requests_from_url(url)
    def make_requests_from_url(self, url): 
        return Request(url, dont_filter=True)
    def parse(self, response): 
        raise NotImplementedError ..

在这里插入图片描述

由于起始爬取点的下载请求是由引擎调用Spider对象的 start_requests方法产生的,因此我们也可以在BooksSpider中实现start_requests方法(覆盖基类Spider的start_requests方法),直接构造并提交起始爬取点的Request对象。在某些场景下使用这种方式更加灵活,例如有时想为Request添加特定的HTTP请求头部,或想为Request指定特定的页面解析函数

在这里插入图片描述

实现页面解析函数

页面解析函数也就是构造Request对象时***通过callback***的回调函数(或默认的parse方法)。页面解析函数是实现Spider中最核心的部分,它需要完成以下两项工作:

在这里插入图片描述

一个页面中可能包含多项数据以及多个链接,因此页面解析函数被要求返回一个可迭代对象(通常被实现成一个生成器函数),每次迭代返回一项数据(Item或字典)或一个Request对象。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值