python scrapy拆解查看Spider类爬取优设网极细讲解

 更新时间:2021年11月15日 09:16:25   作者:梦想橡皮擦  
本篇博客为你带来 scrapy.Spider 模块中的相关函数与类,带你再一次认识 scrapy 的细节。本次采集的目标站点为:优设网,有需要的朋友可以借鉴参考下

拆解 scrapy.Spider

本次采集的目标站点为:优设网

每次创建一个 spider 文件之后,都会默认生成如下代码:

import scrapy
class UiSpider(scrapy.Spider):
    name = 'ui'
    allowed_domains = ['www.uisdc.com']
    start_urls = ['http://www.uisdc.com/']

    def parse(self, response):
        self.log()

继承的基类 scrapy.Spider 自然就成了我们要研究的第一个内容,进入其源码,发现如下内容。

scrapy.Spider 核心实现的是 start_requests 方法

Spider 主要进行的操作就是初始化 Request 请求,而这些都是通过 start_requests 实现的,详细代码为:

for url in self.start_urls:
    yield Request(url, dont_filter=True)

start_requests 方法,你可以自己编写同名函数覆盖修改,编写时发现了 make_requests_from_url 方法,该方法在最新版本的 scrapy 中已经被废除。

重写 start_requests 方法 ,需要注意重写时,必须返回一个可迭代对象,并且该对象包含 spider 用于爬取的第 1 个 Request,由于 scrapy 只调用一次该方法,所以你可以将登录站点请求放置到该方法中。

import scrapy
from scrapy.http import Request
class UiSpider(scrapy.Spider):
    name = 'ui'
    allowed_domains = ['www.uisdc.com']
    start_urls = ['http://www.uisdc.com/']

    def start_requests(self):
        print("重写 start_requests")
        yield Request(self.start_urls[0])

    def parse(self, response):
        print(response)

将登录信息放置到 start_requests 中,代码如下:

import scrapy
from scrapy.http import FormRequest
class UiSpider(scrapy.Spider):
    name = 'ui'
    allowed_domains = ['www.uisdc.com']
    start_urls = ['http://www.uisdc.com/']

    def start_requests(self):
        print("手动 start_requests")
        yield FormRequest("https://httpbin.org/post", formdata={"user": "ca"}, callback=self.parse)

    def parse(self, response):
        print(response.text)

scrapy.Spider 属性值

name 属性:

表示爬虫名称,spider 的名称用于 scrapy 定位爬虫,所以非常重要,一般常见的名称方式是使用网站域名(domain),命名 spider,例如 baidu.com 命名为 baidu,但是工作喜欢还是携带 .com 后缀。

allowed_domains 属性:

该属性需要配置 offsiteMiddleware 使用,当该中间件启用之后,待采集 URL 的域名如果不在 allowed_domains 列表中,会被禁止访问。
domains 内容添加,假设你的目标 URL 是 http://www.baidu.com/123.html,仅填写 baidu.com 即可。

start_urls 属性:

起始的 URL 列表,主要用于 start_request 方法进行迭代。

custom_settings 属性:
自定义配置,可以覆盖 settings.py 的配置,以字典格式赋值。

    custom_settings = {
        "ROBOTSTXT_OBEY": False # 不请求 robot.txt 文件
    }

crawler 属性:

该属性在爬虫启动后,由类方法 from_crawler() 设置。

settings 属性:

指定配置文件的实例。

logger 属性:

spider 日志输出对象,默认以 spider 名称创建,可以自定义。

self.logger.info('输出响应地址 %s', response.url)
logger.info('输出响应地址 %s', response.url)

补充一下 scrapy 日志级别

settings.py 中设置 log 级别,只需要增加一行代码:

LOG_LEVEL = 'WARNING'

设置为 WARNING 级别,会发现 scrapy 默认的各种调试信息,都不在控制台输出。

scrapy 日志级别与 logging 模块一致。

CRITICAL:严重错误;

ERROR :一般错误;

WARNING: 警告信息;

INFO :一般信息;

DEBUG:调试信息。

scrapy 中的 settings 中关于日志的配置如下:

LOG_ENABLED:默认: True,表示启用 logging;

LOG_ENCODING: 默认: utf-8,logging 使用的编码;

LOG_FILE 默认: None,日志保存的文件名;

LOG_LEVEL: 默认 DEBUG ,log 的最低级别。

scrapy.Spider 实例方法与类方法

from_crawler 类方法
在查看源码之后,该方法的功能会比较清晰。

@classmethod
def from_crawler(cls, crawler, *args, **kwargs):
    spider = cls(*args, **kwargs)
    spider._set_crawler(crawler)
    return spider

def _set_crawler(self, crawler):
    self.crawler = crawler
    self.settings = crawler.settings
    crawler.signals.connect(self.close, signals.spider_closed)

该方法设置了 crawlersettings 两个属性,该方法在上一篇博客已经有所涉及,直接回顾即可。

parse 方法
当请求(Request)没有指定回调参数(callback)时,该方法是 scrapy 用来处理响应的默认回调方法。

log 方法
使用 self.log() 方法记录日志。

学习到这里,对 Spider 模块有了一个比较整体的认识。

爬取优设网

接下来进入爬虫采集相关代码编写,有了前文知识铺垫之后,采集代码就变得非常简单了。

import scrapy
from uisdc.items import UisdcItem
class UiSpider(scrapy.Spider):
    name = 'ui'
    allowed_domains = ['www.uisdc.com']
    start_urls = ['https://www.uisdc.com/archives']
    custom_settings = {
        "ROBOTSTXT_OBEY": False
    }

    def parse(self, response):
        # print(response.text)
        # self.log("测试是否有数据输出", logging.WARNING)
        items = response.xpath('//div[@id="archive_list"]/div/div[1]/div[1]/div[contains(@class,"item-article")]')
        for i in items:
            item = UisdcItem()
            title = i.xpath(".//h2[@class='item-title']/a/text()").extract_first()
            author = i.xpath(".//h3[@class='meta-name']/text()").extract_first()
            tag = i.xpath(".//div[@class='meta-tag']/a/text()").extract_first()
            item["title"] = title
            item["author"] = author
            item["tag"] = tag
            yield item

接下来修改源码,增加 ** Item Loaders** 填充容器机制。通过 from scrapy.loader import ItemLoader 导入新类,该类的构造函数如下:

def __init__(self, item=None, selector=None, response=None, parent=None, **context)

其中 item 是容器类,selector 为 Selector 对象,提取填充数据的选择器,response 为 Response 响应对象。

代码修改之后得到如下代码:

import scrapy
from uisdc.items import UisdcItem
from scrapy.loader import ItemLoader
class UiSpider(scrapy.Spider):
    name = 'ui'
    allowed_domains = ['www.uisdc.com']
    start_urls = ['https://www.uisdc.com/archives']
    custom_settings = {
        "ROBOTSTXT_OBEY": False
    }
    def parse(self, response):
        items = response.xpath('//div[@id="archive_list"]/div/div[1]/div[1]/div[contains(@class,"item-article")]')
        for i in items:
            l = ItemLoader(item=UisdcItem(), selector=i)
            l.add_xpath('title', ".//h2[@class='item-title']/a/text()")
            l.add_xpath('author', ".//h3[@class='meta-name']/text()")
            l.add_xpath('tag', ".//div[@class='meta-tag']/a/text()")
            yield l.load_item()

其中需要注意 l = ItemLoader(item=UisdcItem(), selector=i) 使用 selector 参数,并赋值为迭代变量 i,如果使用 response 会得到重复数据。

最后,当所有数据被收集起来之后, 调用 ItemLoader.load_item() 方法, 返回 Item 对象。

输出 item 对象,发现每一个数据都是列表。

{'author': ['土拨鼠'],
 'tag': ['产品设计'],
 'title': ['6000+干货!资深总监的四条产品设计工作观(附私藏神器包)']}

接下来需要处理每一项的值,ItemLoader 得到的数据,在存入 item 容器前,是支持对数据进行预处理的,即输入处理器和输出处理器,修改 items.py 文件。

from scrapy.item import Item, Field
from scrapy.loader.processors import MapCompose, TakeFirst
def ext(value):
    return "新闻:" + value
class UisdcItem(Item):
    # define the fields for your item here like:
    title = Field(
        input_processor=MapCompose(ext),
        output_processor=TakeFirst()
    )
    author = Field(output_processor=TakeFirst())
    tag = Field(output_processor=TakeFirst())

Field 字段的两个参数:

输入处理器(input_processor):可以在传进来的值做一些预处理。

输出处理器(output_processor) :输出值前最后的一步处理。

其中用到了 TakeFirst(),返回第一个非空(non-null/ non-empty)值,常用于单值字段的输出处理器,无参数。

还用到了 MapCompose,能把多个函数执行的结果按顺序组合起来,产生最终的输出,通常用于输入处理器。

其余内置的处理器如下

Identity:不进行任何处理,返回原来的数据,无参数;

Join:返回用分隔符连接后的值,分隔符默认为空格;

Compose:用给定的多个函数的组合,来构造处理器,list 对象一次被传递到各个函数中,由最后一个函数返回整个处理器的输出,默认情况下遇到 None值(list 中有 None 值)的时候停止处理,可以通过传递参数 stop_on_none = False 改变这种行为;

MapCompose:输入值是被迭代的处理的,List 对象中的每一个元素被单独传入,依次执行对应函数。

关于 item loader 还有一些其它的知识点,我们后面再聊。

以上就是python scrapy拆解查看Spider类爬取优设网极细讲解的详细内容,更多关于scrapy拆解Spider类爬取优设网的资料请关注脚本之家其它相关文章!

相关文章

  • Python实现人机中国象棋游戏

    Python实现人机中国象棋游戏

    中国象棋是一种古老的棋类游戏,大约有两千年的历史。本文将介绍如何通过Python中的Pygame模块实现人机中国象棋游戏,感兴趣的可以学习一下
    2022-01-01
  • Python实现将数据框数据写入mongodb及mysql数据库的方法

    Python实现将数据框数据写入mongodb及mysql数据库的方法

    这篇文章主要介绍了Python实现将数据框数据写入mongodb及mysql数据库的方法,结合具体实例形式分析了Python针对mongodb及mysql数据库的连接、写入等操作实现技巧,需要的朋友可以参考下
    2018-04-04
  • Django Model层F,Q对象和聚合函数原理解析

    Django Model层F,Q对象和聚合函数原理解析

    这篇文章主要介绍了Django Model层F,Q对象和聚合函数原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-11-11
  • python 执行文件时额外参数获取的实例

    python 执行文件时额外参数获取的实例

    今天小编就为大家分享一篇python 执行文件时额外参数获取的实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-12-12
  • Python使用jsonpath-rw模块处理Json对象操作示例

    Python使用jsonpath-rw模块处理Json对象操作示例

    这篇文章主要介绍了Python使用jsonpath-rw模块处理Json对象操作,结合实例形式分析了Python使用requests与response处理json的方法,并给出了jsonpath_rw模块操作json对象的基本示例,需要的朋友可以参考下
    2018-07-07
  • Jupyter notebook之如何快速打开ipynb文件

    Jupyter notebook之如何快速打开ipynb文件

    这篇文章主要介绍了Jupyter notebook之如何快速打开ipynb文件问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-09-09
  • Python lambda函数使用方法深度总结

    Python lambda函数使用方法深度总结

    在本文中,小编将带大家学习一下Python中的lambda函数,并探讨使用它的优点和局限性。文中的示例代码讲解详细,感兴趣的可以了解一下
    2022-05-05
  • 详解如何使用python脚本制作生成CANdbc

    详解如何使用python脚本制作生成CANdbc

    这篇文章主要为大家详细介绍了如何使用python脚本制作生成CANdbc,文中的示例代码讲解详细,具有一定的学习价值,感兴趣的小伙伴可以了解下
    2024-01-01
  • 详解Python实现字典合并的四种方法

    详解Python实现字典合并的四种方法

    这篇文章主要为大家详细介绍了Python的合并字典的四种方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-03-03
  • 在pycharm中关掉ipython console/PyDev操作

    在pycharm中关掉ipython console/PyDev操作

    这篇文章主要介绍了在pycharm中关掉ipython console/PyDev操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-06-06

最新评论