news 2026/5/1 10:03:58

12 - 数据抽取 - parsel解析库

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
12 - 数据抽取 - parsel解析库

文章目录

  • `parsel` 库
    • 安装
    • `Selector` 类
      • 构造方法
      • `css` 方法
      • `xpath` 方法
      • `jmespath` 方法
      • `re` 方法
      • `re_first` 方法
      • `get` 方法
      • `getall` 方法
      • `register_namespace` 方法
      • `remove_namespaces` 方法
      • `drop` 方法
      • `attrib` 方法
      • `extract` 方法
      • `extract_first` 方法
    • `SelectorList` 类
    • 处理 `HTML` 格式内容
      • 提取网页标题
      • `CSS` 选择器能力扩展
      • 循环提取子元素
      • 提取网页元素
      • 使用正则表达式
    • 处理 `XML` 格式内容

parsel

parsel是一个针对于htmljson以及xml格式解析并提取内容的 Python 库,它基于BSD授权协议。支持:

  • HTMLXML文档 提供基于CSSXPath的解析支持;
  • JSON文档提供JMESPath表达式处理支持;
  • 提供基于正则表达式支持。

不管是HTML或是XML格式内容,都可以使用CSSXPath表达式来选择数据。

安装

使用pip安装:

pip install parsel

使用uv安装:

uv add parsel

Selector

parsel.Selector类用于处理HTMLJSONXML格式输入数据的包装器,允许使用查询表达式来选择数据。对于HTMLXML输入,可以用CSSXPath编写查询表达式,对于JSON输入,可以用JMESPath编写查询表达式。

Selector类实例就是一个选择的节点的实例化对象,所有的方法都针对于该节点处理其子节点。当我们在传入字符串解析的时候,这时候生成的可以看做是一个根节点。

⚠️注意

parsel.SelectorXPath的支持基于lxml库; 对JSON的支持基于JMESPath库。

构造方法

函数原型:

__init__( self, text: Optional[str] = None, type: Optional[str] = None, body: bytes = b"", encoding: str = "utf-8", namespaces: Optional[Mapping[str, str]] = None, root: Optional[Any] = _NOT_SET, base_url: Optional[str] = None, _expr: Optional[str] = None, huge_tree: bool = LXML_SUPPORTS_HUGE_TREE, ) -> None

其中:

  • textstr类型,【可选】。 待处理的文本
  • typestr类型,【可选】。定义选择器类型。可选的值htmljsonxml其中之一;默认为html
  • bodybytes对象。内容体。它可以与encoding参数一起使用,而不是与text参数一起使用。
  • encodingstr类型,内容编码类型,默认为utf-8
  • namespacesMap[str,str]对象,【可选】,命名空间集合, 默认为None,如果不设定,则使用_default_namespaces
  • rootAny,【可选】, 默认为_NOT_SET
  • base_urlstr类型,【可选】。允许为文档设置URL。这在查找具有相对路径的外部实体时是需要的。
  • huge_treebool类型。控制lxml/libxml2特性,该特性禁止解析某些大文档,以防止可能的内存耗尽。如果安装的lxml版本支持该参数,默认情况下该参数为True,这将禁用允许解析此类文档的保护。如果要启用保护,将其设置为False

css方法

根据给定的CSS查询表达式查找本Selector下所有符合条件的节点并返回。函数原型:

css(self: _SelectorType, query: str) -> SelectorList[_SelectorType]

其中:

  • querystr类型,CSS格式查询表达式。

返回结果是SelectorList对象实例;包含所有查找的结果。

该方法内部处理实际上是将css查询表达式转换为xpath的查询表达式,然后使用cssselect库和运行xpath方法。

xpath方法

根据给定的XPath格式查询表达式查询本Selector下符合条件的所有节点并返回。函数原型:

xpath( self: _SelectorType, query: str, namespaces: Optional[Mapping[str, str]] = None, **kwargs: Any, ) -> SelectorList[_SelectorType]

其中:

  • querystr类型,XPath格式查询表达式;
  • namespacesMap[str,str]对象,【可选】,命名空间集合, 默认为None
  • kwargsdict类型。 其他可选的字典参数。

返回结果是SelectorList对象实例;包含所有查找的结果。

jmespath方法

根据给定的JMESPath格式的查询本Selector下表达式查询符合条件的所有节点并返回。函数原型:

jmespath( self: _SelectorType, query: str, **kwargs: Any, ) -> SelectorList[_SelectorType]

其中:

  • querystr类型,JEMSPath格式查询表达式;
  • kwargsdict类型。 其他可选的字典参数。

返回结果是SelectorList对象实例;包含所有查找的结果。

re方法

根据给定的正则表达式查询本Selector下所有符合条件的节点并返回所有结果。函数原型:

re(self, regex: Union[str, Pattern[str]], replace_entities: bool = True) -> List[str]

其中:

  • regexstr类型或者Pattern[str]对象,正则表达式字符串或者正则表达式模式;
  • replace_entitiesbool类型。默认值为True。 默认除了歧义字符(如&<等)所有的字符实体引用都会被对应的字符替换;如果不想替换,则设置为False

返回结果是list[str]即所有匹配到的字符串列表。

re_first方法

re类似,只是re返回的是所有匹配的字符串,而re_first返回第一条匹配的字符串。函数原型:

re_first( self, regex: Union[str, Pattern[str]], default: Optional[str] = None, replace_entities: bool = True, ) -> Optional[str]

其中:

  • regexstr类型或者Pattern[str]对象,正则表达式字符串或者正则表达式模式;
  • defaultstr类型,可选,默认为None
  • replace_entitiesbool类型。默认值为True。 默认除了歧义字符(如&<等)所有的字符实体引用都会被对应的字符替换;如果不想替换,则设置为False

get方法

序列化并返回匹配的节点。对于HTMLXML,返回的是字符串。函数原型:

get(self) -> Any

getall方法

序列化并返回本Selector下包含的所有元素构成的列表。函数原型:

getall(self) -> List[str]

register_namespace方法

注册给定的命名空间,以便在Selector中使用。如果不注册名称空间,就不能从非标准名称空间中选择或提取数据。函数原型:

register_namespace(self, prefix: str, uri: str) -> None

其中:

  • prefixstr类型。命名空间键名;
  • uristr类型。命名空间链接地址。

remove_namespaces方法

删除所有的命名空间。允许使用无名称空间的XPath遍历文档。函数原型:

remove_namespaces(self) -> None

drop方法

从本Selector所属父类节点中删除本节点。函数原型:

drop(self) -> None

attrib方法

返回本Selector的所有属性。函数原型:

attrib(self) -> Dict[str, str]

返回的是一个键值字典,其中,键为属性名,值为属性值。

extract方法

等同于getall方法。

extract_first方法

等同于get方法

SelectorList

SelectorList类是选择节点的容器,由选中的节点(看作是每个Selector构成)。提供的方法和Selector一直,只是它处理的列表中的所有节点,而SelectorList是处理自己的节点及其子节点。

处理HTML格式内容

现在我们假定有以下html文本可供使用:

<html> <head> <base href='http://example.com/' /> <title>Example website</title> </head> <body> <div id='images'> <a href='image1.html'>Name: My image 1 <br /><img src='image1_thumb.jpg' /></a> <a href='image2.html'>Name: My image 2 <br /><img src='image2_thumb.jpg' /></a> <a href='image3.html'>Name: My image 3 <br /><img src='image3_thumb.jpg' /></a> <a href='image4.html'>Name: My image 4 <br /><img src='image4_thumb.jpg' /></a> <a href='image5.html'>Name: My image 5 <br /><img src='image5_thumb.jpg' /></a> </div> </body> </html>

对于HTML格式数据,我们使用cssxpath表达式来查询数据。首先导入Selector

from parsel import Selector

然后解析字符串:

html_selector = Selector(content)

提取网页标题

从现在开始,开始来逐一举例如何使用parsel操作Html格式文档。

selector2 = selector.css('title::text') print(selector2.getall())

上面的代码使用css方法解析指定的元素title::text;输出:

['Example website']

下面使用xpath方法来获取网页标题:

selector3 = selector.xpath('//title/text()') print(selector3.getall())

输出:

['Example website']

CSS选择器能力扩展

按照W3C标准,CSS选择器是不支持提取文本节点和节点属性的,但是parsel扩展了属性器:

  • 从节点中取出文本,使用::text;支持通配符,如*::text
  • 取出节点属性值,使用::attr(name)
print(selector.css("title::text").extract()) print(selector.css("a::attr('href')").extract())

输出:

['Example website'] ['image1.html', 'image2.html', 'image3.html', 'image4.html', 'image5.html']

循环提取子元素

选择器的xpathcss方法返回的是一个同类型的选择节点列表,所以可以通过循环的方式读取子节点:

links = selector.xpath('//a[contains(@href, "image")]') for index, link in enumerate(links): args = (index, link.xpath('@href').get(), link.xpath('img/@src').get()) print('Link number %d points to url %r and image %r' % args)

输出:

Link number 0 points to url 'image1.html' and image 'image1_thumb.jpg' Link number 1 points to url 'image2.html' and image 'image2_thumb.jpg' Link number 2 points to url 'image3.html' and image 'image3_thumb.jpg' Link number 3 points to url 'image4.html' and image 'image4_thumb.jpg' Link number 4 points to url 'image5.html' and image 'image5_thumb.jpg'

提取网页元素

首先示例使用css方法提取:

selector1 = selector.css("div[id='images'] a::attr(href)") print(selector1.getall())

输出:

['image1.html', 'image2.html', 'image3.html', 'image4.html', 'image5.html']

然后使用xpath方法来提取:

selector2 = selector.xpath('//div[@id="images"]/a/@href') print(selector2.getall())

输出:

['image1.html', 'image2.html', 'image3.html', 'image4.html', 'image5.html']

最后我们使用混合模式来提取:

selector1 = selector.css("div[id='images']").xpath("//a/@href") print(selector1.getall())

输出:

['image1.html', 'image2.html', 'image3.html', 'image4.html', 'image5.html']

使用正则表达式

parsel.Selector提供的rere_first方法支持正则表达式:

print(selector.xpath('//a[contains(@href, "image")]/text()').re(r'Name:\s*(.*)'))

输出:

['My image 1 ', 'My image 2 ', 'My image 3 ', 'My image 4 ', 'My image 5 ']

处理XML格式内容

首先,我们准备一段文本,如下:

<bookstore> <book category="科幻"> <title>Python 库使用</title> <author>胡伯</author> <price>68.00</price> </book> <book category="经典"> <title>一起学习网络爬虫</title> <author>张磊</author> <price>39.50</price> </book> </bookstore>

然后我们提取节点:

from parsel import Selector xml_content = """ <bookstore> <book category="科幻"> <title>Python 库使用</title> <author>胡伯</author> <price>68.00</price> </book> <book category="经典"> <title>一起学习网络爬虫</title> <author>张磊</author> <price>39.50</price> </book> </bookstore> """ # 创建Selector对象 selector = Selector(text=xml_content,type="xml") selector1 = selector.xpath("//bookstore/book/title/text()") print(selector1.getall())

输出:

['Python 库使用', '一起学习网络爬虫']
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/24 16:42:21

Miniconda创建环境时遇到‘ UnsatisfiableError’怎么办?

Miniconda创建环境时遇到‘UnsatisfiableError’怎么办&#xff1f; 在现代AI和数据科学项目中&#xff0c;一个常见的场景是&#xff1a;你刚刚启动了一个基于Miniconda的开发环境&#xff0c;信心满满地输入一行命令来创建新的虚拟环境——比如 conda create -n myproject py…

作者头像 李华
网站建设 2026/5/1 6:19:28

使用GitHub Actions自动化测试Miniconda-Python3.10环境

使用 GitHub Actions 自动化测试 Miniconda-Python3.10 环境 在数据科学和人工智能项目中&#xff0c;你是否曾遇到过这样的场景&#xff1a;本地运行完美的模型代码&#xff0c;在同事或 CI 环境中却因依赖冲突、Python 版本不兼容而失败&#xff1f;更糟的是&#xff0c;论文…

作者头像 李华
网站建设 2026/5/1 6:18:53

构建可分享的技术博客:以Miniconda部署为例吸引流量

构建可分享的技术博客&#xff1a;以 Miniconda 部署为例吸引流量 在数据科学与人工智能项目日益复杂的今天&#xff0c;一个常见的尴尬场景是&#xff1a;“代码在我机器上跑得好好的&#xff0c;怎么到了别人环境就报错&#xff1f;”这种“在我机器上能运行”的问题&#xf…

作者头像 李华
网站建设 2026/5/1 4:43:42

Jupyter Notebook自动保存与Miniconda环境备份策略

Jupyter Notebook自动保存与Miniconda环境备份策略 在数据科学和AI研发的日常工作中&#xff0c;我们常常面临这样的窘境&#xff1a;连续调试模型两小时后&#xff0c;突然断电重启&#xff0c;发现最新的代码变更全部丢失&#xff1b;或者将项目分享给同事时&#xff0c;对方…

作者头像 李华
网站建设 2026/5/1 4:44:53

使用Miniconda环境运行LLaMA系列模型的初步尝试

使用Miniconda环境运行LLaMA系列模型的初步尝试 在本地部署和调试大语言模型&#xff08;LLMs&#xff09;时&#xff0c;最让人头疼的往往不是模型本身&#xff0c;而是“环境配置”这个前置步骤。你是否经历过这样的场景&#xff1a;从GitHub拉下一份LLaMA推理代码&#xff0…

作者头像 李华
网站建设 2026/5/1 4:46:39

在Miniconda环境中集成MLflow跟踪实验结果

在Miniconda环境中集成MLflow跟踪实验结果 在机器学习项目的开发过程中&#xff0c;一个常见的困境是&#xff1a;明明在本地训练时模型表现优异&#xff0c;但换一台设备或几天后再运行&#xff0c;结果却大相径庭。这种“在我机器上能跑”的问题&#xff0c;往往源于环境依赖…

作者头像 李华