首页 > 其他分享 >Scrapy 爬虫完全规则化的思考

Scrapy 爬虫完全规则化的思考

时间:2025-01-12 16:14:48浏览次数:1  
标签:name 子类 规则化 爬虫 Scrapy proc class ItemLoader

看了《Python3网络爬虫开发实战(第2版)》,书中15章在讲到Scrapy框架时,15.12节谈到了规则化爬虫。

作者提到的规则化思路如下:

如果我们可以保留各个站点的Spider的公共部分,提取不同的部分进行单独配置(如将爬取规则页面解析方式等抽离出来,做成一个配置文件),那么我们在新增一个爬虫的时候,只需要实现这些网站的爬取规则和提取规则,而且还可以单独管理和维护这些规则。

书中尝试着实现了规则化爬虫,最后把Spider的“设置“、“起止链接“、“Item提取方法“等抽取到json文件里,实现了可配置化。

然而书中的实现有些不完美的是,没有做到完全的可配置化,或者说没有做到完全的规则化爬虫。比如说要爬取新的站点时,除了需要创建json配置文件之外,还需要创建相应的Item子类和ItemLoader子类,也就说还是需要修改源码。

那么,有没有可能完全实现可配置化呢?想起Python的元编程,最简单的实现,貌似可以通过type创建类的方式来创建Item子类和ItemLoader子类?

使用type创建类

讲完全规则化的具体实现之前,先来了解一下使用type创建类的知识。

学过Python的人一般都知道,在Python中,可以使用内置的type来获取对象的类型。然而一般人不了解的是,type是一个元类,它不仅可以用于检查对象类型,还可以用来创建类。

type创建类的语法:type(name, bases, dict)

  • name是类的名称(字符串);
  • bases是基类的元组,可以是单个类或多个类(支持多继承);
  • dict是包含类属性和方法的字典。

使用type创建类的示例:

Point = type("Point", (), {"x": 1, "y": 2})  
p = Point()  
print(p.x, p.y)

Item子类的规则化

Item子类要实现规则化,那么就要根据字符串类名来生成相应Item子类。其实Item子类的实现挺简单的,实际上只要一行代码。当然了,虽然只有一行代码,最好还是把它封装起来,隐藏具体的实现。

可以用一个函数来封装(如果你喜欢的话,也可以用一个类来封装):

def item_class_factory(class_name: str, attrs: Iterable[str]):
    """
    Item 类工厂函数
    :param class_name: 类名
    :param attrs: 属性列表
    :return: 
    """
    return type(class_name,
                (Item,),
                {n: Field() for n in attrs})

使用的时候,只要传入类名和属性列表就可以了。这两者可以配置到配置文件里,使用的时候可以从配置文件里取出来,因为书中里已经将两者提取到配置文件里,这里便不再举出示例。

item_class_factory类的调用代码如下:

item_cls = item_class_factory(cls_name=item_conf["class"], 
                              attrs=item_conf["attrs"].keys())
item = item_cls()

ItemLoader子类的规则化

ItemLoader子类的规则化实现逻辑稍微有点复杂。书中并没有提取ItemLoader相关信息到配置文件,下面先给出相应的配置文件信息。

ItemLoader类配置

{
	...
	"loader": {
	    "class": "MovieItemLoader",
	    "attrs": {
	      "default_output_processor": ["TakeFirst"],
	      "categories_out": ["Identity"],
	      "score_out": ["Compose",["TakeFirst"], ["Strip"]],
	      "drama_out": ["Compose", ["TakeFirst"], ["Strip"]]
	    }
	}
}

在配置文件里配置ItemLoader的类名和属性信息。

每一个属性的键值对代表ItemLoader子类的属性和itemloaders.processors的类型。类型是一个列表,列表的第一个值为类型名,后续值为参数(如果有参数的话)。

Processor

Item类,其属性的初始化都是Field(),所以不用另外设置。而ItemLoader类的属性不同,其初始化是processors的类,processors有不同的类,那么就要进行另外的设置,所以在配置文件里要填上相应的processors类名。

将配置文件里的processors类名转为类实例,自然也需要封装一个函数,其实现如下:

def processor_fatory(proc_list: list[Any]):
    """
    Processor 实例工厂函数
    :param proc_list: Processor类型和参数列表
    :return:
    """

    # 第一个是类型,后续的是参数,因为参数有可能为空,所以这里不使用python的解包功能
    proc_name = proc_list[0]
    args = proc_list[1:]
    match proc_name:
        case x if x in ("Identity", "TakeFirst"):
            return getattr(processors, proc_name)()

        case "Join":
            if not args:
                return getattr(processors, proc_name)()
            else:
                return getattr(processors, proc_name)(*args)

        case "SelectJmes":
            return getattr(processors, proc_name)(*args)

        case x if x in ("Compose", "MapCompose"):
            # 使用递归进行组合
            compose = getattr(processors, proc_name)
            return compose(*(processor_fatory(a) for a in args))

        # 自定义的类型
        case "Strip":
            return getattr(processors, proc_name)()

        case _:
            raise TypeError(f"不支持的Processor:{proc_name}")

Processor 工厂函数的实现有几点值得注意的,

  • 这不是创建类而是创建实例,故返回Processor时需要实例化。
  • 对于需要自定义的processor,最好仿照processors模块里的类,封装成相应功能的Processor类,这样比较统一和规范。

上面代码中的Strip类就是自定义的processor,其实现如下:

class Strip:
    """
    去除首尾空格,是对 str.strip 的包装
    """

    def __call__(self, value: str) -> str:
        return value.strip()

书中自定义的processor,没有进行封装,不够优雅。书中相关的MovieItemLoader类代码如下:

class MovieItemLoader(ItemLoader):  
    default_output_processor = TakeFirst()  
    categories_out = Identity()  
    score_out = Compose(TakeFirst(), str.strip)  
    drama_out = Compose(TakeFirst(), str.strip)

代码中,直接将str.strip作为第二个参数传给Compose,而Compose的前一个参数是TakeFirst()。两者并不统一,封装了Strip类之后就可以这样传参:Compose(TakeFirst(), Strip())。这样就优雅多了。

ItemLoader子类的规则化

讲完了前面的,终于可以讲重点“ItemLoader子类的规则化”了。

有了processor_fatory函数的辅助,ItemLoader子类的规则化函数其实也挺简单的,其实现如下:

def loader_class_factory(cls_name, attrs):
    """
    ItemLoder 类工厂函数
    :param cls_name: 类名
    :param attrs: 属性序列
    :return:
    """
    attr_dict = {key: processor_fatory(value)
                 for key, value in attrs.items()
                 }

    return type(cls_name,
                (ItemLoader,),
                attr_dict)

调用代码如下:

loader_cls = loader_class_factory(loader_conf["class"], 
								  loader_conf["attrs"])
loader = loader_cls(item, selector=sel)

总结

至此,就可以说是实现了真正意义上的爬虫完全规则化了。这样要爬取新的网站时,只要添加新的站点json配置文件,完全不需要修改源码。

本文的源码存放在GitHub上,地址:scrapy_universal_demo

标签:name,子类,规则化,爬虫,Scrapy,proc,class,ItemLoader
From: https://www.cnblogs.com/linsuiyuan/p/18666992

相关文章

  • python中国科学院院士图片+文本爬虫代码
    1.爬取网页https://www.cae.cn/cae/html/main/col48/column_48_1.html 2.爬虫思路 1.网页源码分析,判断网页是动态网页与静态网页(改网页位静态网页)2.获取每位院士网页地址3.进入网页查看院士图片地址,与院士文本介绍内容,(利用re库解析网页)4.数据存储,图片存储,注意保存图片......
  • 深入解析:利用Java爬虫挖掘淘宝商品评论的宝藏
    在当今数字化时代,消费者的声音成为了品牌和商家决策的关键因素。淘宝作为国内领先的电商平台,其商品评论数据蕴含着巨大的商业价值。本文将带你深入了解如何利用Java爬虫技术,通过淘宝商品评论API接口(item_review),高效地获取并分析这些宝贵的用户反馈,为你的电商运营、市场调研或数据......
  • 计算机毕业设计Python深度学习游戏推荐系统 Django PySpark游戏可视化 游戏数据分析
    温馨提示:文末有CSDN平台官方提供的学长联系方式的名片!温馨提示:文末有CSDN平台官方提供的学长联系方式的名片!温馨提示:文末有CSDN平台官方提供的学长联系方式的名片!作者简介:Java领域优质创作者、CSDN博客专家、CSDN内容合伙人、掘金特邀作者、阿里云博客专家、51CTO......
  • Python网络爬虫:从入门到实战
            Python以其简洁易用和强大的库支持成为网络爬虫开发的首选语言。本文将系统介绍Python网络爬虫的开发方法,包括基础知识、常用工具以及实战案例,帮助读者从入门到精通。什么是网络爬虫?网络爬虫(WebCrawler)是一种自动化程序,用于抓取网页内容。爬虫通过模拟浏览......
  • 设计一篇利用python爬虫获取1688详情API接口的长篇软文
    在当今数字化浪潮席卷全球的背景下,数据已成为企业、研究机构乃至个人获取信息、洞察趋势、做出决策的关键资源。而1688作为国内领先的B2B电子商务平台,汇聚了海量的供应商和采购商,其商品详情数据蕴含着巨大的商业价值和研究意义。如何高效、便捷地获取这些数据?Python爬虫技......
  • Python网络爬虫简介-科普版
    Python网络爬虫简介一、什么是网络爬虫网络爬虫(WebCrawler),又称为网页蜘蛛、网页机器人,是一种按照一定规则自动抓取互联网信息的程序。它通过模拟浏览器的行为,访问网页,获取网页内容,并将这些内容存储下来,以便后续分析和处理。网络爬虫广泛应用于搜索引擎、数据分析、信息采......
  • (免费源码)计算机毕业设计必学必看 万套实战教程 java、python、php、node.js、c#、APP
    摘 要随着互联网时代的到来,同时计算机网络技术高速发展,网络管理运用也变得越来越广泛。因此,建立一个B/S结构的中医病案管理系统,会使;中医病案管理系统的管理工作系统化、规范化,也会提高平台形象,提高管理效率。本系统是针对目前中医病案管理系统的实际需求,从实际工作出发,对过......
  • (免费源码)计算机毕业设计必学必看 万套实战教程 java、python、php、node.js、c#、APP
    摘 要随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,志愿服务管理小程序被用户普遍使用,方便用户能够可以随时进行在线查看志愿服务管理的数据信息管理,特开发了志愿服务管理......
  • django网络爬虫系统-计算机设计毕业源码81040
    摘要本论文主要论述了如何开发一个网络爬虫系统,对旅游景点信息进行爬取,本系统将严格按照软件开发流程进行各个阶段的工作,面向对象编程思想进行项目开发。在引言中,作者将论述网络爬虫系统的当前背景以及系统开发的目的,后续章节将严格按照软件开发流程,对系统进行各个阶段分析设......
  • 《小白爬虫之豆瓣》
    目录前言一、爬虫是什么?二、爬虫的主要功能 三、实践1.简介 2.所需库(如果安装失败,可以选择去Settings里去手动安装)前言新手小白如何成功实现第一次爬虫,从0到1。豆瓣作为必爬之路一、爬虫是什么?爬虫(WebCrawler),也称为网络爬虫、网络蜘蛛(WebSpider)或网络机......