上个月,我需要从一个比价项目中涉及的十几个电子商务网站提取产品规格。听起来很简单,对吧?只需抓取超文本标记语言(HTML),获取 <table> 或 <dl> 标签,然后将其解析为 JavaScript 对象表示法(JSON)。
两天后,我气得想把笔记本电脑扔出窗外。每个网站的标记结构都各不相同。有的使用混乱的 <div> 嵌套,有的将数据隐藏在 JavaScript 对象中,还有少数网站将规格表以图片形式呈现。在使用正则表达式和 BeautifulSoup 库时,我在一切崩溃前仅完成了约 40% 的工作。
我尝试过但无效的方法
1. 层叠样式表(CSS)选择器和 XPath
我从 soup.select('table.specs tr') 开始。这在网站 A 上运行良好。网站 B 使用的是 ul.list。网站 C 则在影子文档对象模型(Shadow DOM)内部嵌套了 <dl> 标签。最终,我写出了一个长达 200 行、充满备用逻辑的函数,但仍然遗漏了一半的字段。
2. 对原始超文本标记语言(HTML)使用正则表达式
在绝望之中,我尝试了 re.search(r'RAM.*?(\d+ GB)', html)。它确实捕获了一些值,但当文本跨行分布或包含多余空白字符时,程序就会出错。此外,为 12 个网站维护正则表达式模式简直是一场噩梦。
3. 直接调用应用程序编程接口(API)
我发现其中一个网站有一个隐藏的 JavaScript 对象表示法(JSON)端点,但它需要我无法获取的身份验证令牌。另一个网站则使用 Cloudflare 阻止了网络爬虫。我陷入了困境。
此时,我有三个选择:为每个网站编写自定义解析器(这将花费数周时间)、付费使用结构化数据服务(价格昂贵),或者寻找一种更智能的方法,从杂乱的文本中提取所需内容。
最终奏效的方法:让大型语言模型(LLM)解析非结构化文本
我意识到,无论超文本标记语言(HTML)多么杂乱,所有这些网站呈现的信息都是相同的:产品名称、品牌、随机存取存储器(RAM)、存储空间、屏幕尺寸等。格式各异,但语义是一致的。
我不再与超文本标记语言(HTML)结构较劲,而是开始向大型语言模型(LLM)提供页面的原始文本内容(去除标签和脚本),并要求其返回包含特定字段的 JavaScript 对象表示法(JSON)对象。这时,OpenAI 应用程序编程接口(API)中的函数调用(或工具使用)功能派上了用场。
具体方法
- 使用 Readability 库或简单的
requests+BeautifulSoup组合抓取页面文本,以获取主体文本。 - 为我想要的数据定义一个 JavaScript 对象表示法(JSON)模式。
- 调用大型语言模型(LLM)(我使用了 GPT-4o-mini,因为它成本低廉),传入文本和模式,要求其提取数值。
- 解析返回的 JavaScript 对象表示法(JSON)。
以下是核心代码(使用 openai 和 pydantic 进行模式定义):
from openai import OpenAI
from pydantic import BaseModel
from typing import Optional
import json
# 定义我们要提取的内容(根据需要调整字段)
class ProductSpecs(BaseModel):
brand: Optional[str] = None
model: Optional[str] = None
免责声明:本文内容来自互联网,该文观点不代表本站观点。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,请到页面底部单击反馈,一经查实,本站将立刻删除。