如何解析html中的数据格式文件格式

3次阅读

beautifulsoup 提取 html 表格数据应优先使用 .find(‘table’).find_all(‘tr’) 定位行,注意处理 colspan/rowspan 合并单元格;嵌入 json 须精准匹配 script 内容并用 json5.loads() 解析;data-* 属性和 microdata 是更可靠的结构化数据源,推荐用 extruct 库提取。

如何解析html中的数据格式文件格式

BeautifulSoup 提取 HTML 表格里的结构化数据

HTML 本身不是数据格式文件,但常被当“伪数据容器”用——比如网页里嵌的 <table>、<code><ul></ul> 或带 data-* 属性的标签。想把它转成 CSV/JSON,核心是先定位、再提取、最后清洗。

别直接上正则解析 HTML,re.findall(r'<td>(.*?)</td>', html) 看似快,一遇到换行、嵌套、属性值含 就崩。用 <code>BeautifulSoup(推荐 lxml 解析器)才是稳解。

  • BeautifulSoup(html, 'lxml')'html.parser' 更准,尤其对不规范 HTML;但需额外装 lxml
  • 表格提取优先用 .find('table').find_all('tr'),别硬写循环索引——thtd 混排时索引极易错位
  • 注意 colspan/rowspan:原生 BeautifulSoup 不自动合并单元格,得自己按属性补空值

script 标签里读取 JSON 嵌入数据

很多现代网页把真实数据藏在 <script></script> 里,比如 window.__INITIAL_STATE__ = {...}var data = [...]。这是最干净的数据源,但容易漏掉或误判。

关键不是“找到 <script></script>”,而是精准定位目标变量。直接搜字符串风险高:script.String 可能为 None(内容在子节点),而 script.get_text() 会混入注释和换行。

立即学习前端免费学习笔记(深入)”;

  • soup.find('script', string=re.compile(r'INITIAL_STATE')) 比遍历所有 <script></script> 更可靠
  • 提取后别直接 json.loads():JavaScript 对象字面量允许末尾逗号、单引号、未引号键名,得先用 ast.literal_eval()json5.loads()
  • 警惕动态渲染:如果目标脚本是 JS 运行时生成的(非服务端直出),requests 拿到的 HTML 里根本不存在

处理 data-* 属性和微数据(Microdata)

当 HTML 里有 <div data-id="123" data-price="29.99"> 或 <code><div itemscope itemtype="https://schema.org/Product">,说明作者本意就是暴露结构化数据——这是最该优先抓的信号。<p>但 <code>data-* 属性名无规范,data-price 可能叫 data-cost,得看实际 HTML;而 Microdata 需要完整遍历 itemprop 树,不能只取一层。

  • 批量提取 data- 属性:用 elem.attrs 然后 {k: v for k, v in attrs.items() if k.startswith('data-')}
  • Microdata 推荐用 extruct 库(支持 JSON-LD/Microdata/RDFa),比手写 find(attrs={'itemprop': True}) 少踩 80% 的嵌套坑
  • 注意属性值类型data-count="1" 是字符串,别默认当 int 用;data-tags='["a","b"]' 看似 JSON,实则可能是字符串字面量,需 json.loads() 二次解析

避免把 HTML 当 XML 或 YAML 来解析

有人看到 <user><name>Alice</name></user> 就以为是自定义 XML 格式,试图用 xml.etree.ElementTree 解析——这会失败,因为 HTML 不是合法 XML(标签不闭合、大小写混乱、属性无引号等)。

同样,别指望 PyYAML 能读 <!--nyaml: |n name: Bobn-->:注释里的 YAML 不是标准嵌入方式,且 yaml.load() 默认禁用危险构造器。

  • HTML 就用 HTML 解析器(BeautifulSoup / lxml.html),别跨域硬套
  • 真要解析注释块里的 YAML,先用 re.findall(r'<!--(.*?)-->', html, re.DOTALL) 提取,再单独喂给 yaml.safe_load()
  • 所有解析结果必须做类型校验:if not isinstance(data, dict): raise ValueError('expected dict'),HTML 结构随时可能变

真正麻烦的从来不是怎么取数据,而是 HTML 结构没人维护、字段名随机改、同一页面多个版本共存。多加一层容错检查,比追求“一次写对”实在得多。

text=ZqhQzanResources