【问题标题】:How to parse HTML with source mapping?如何使用源映射解析 HTML?
【发布时间】:2021-11-18 17:34:39
【问题描述】:

我想使用 Python 来解析 HTML 标记,并给定一个生成的 DOM 树元素,获取该元素在原始、未修改的标记中的开始和结束偏移量。

例如,给定 HTML 标记(带有 \n EOL 字符)

<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en-gb">
  <head>
    <title>No Longer Human</title>
    <meta content="urn:uuid:6757faf0-eef1-45d9-b2b3-7462350db7ba" name="Adept.expected.resource"/>
    <meta content="text/html; charset=utf-8" http-equiv="Content-Type"/>
  <link href="kindle:flow:0002?mime=text/css" rel="stylesheet" type="text/css"/>
  <link href="kindle:flow:0001?mime=text/css" rel="stylesheet" type="text/css"/>
  </head>
  <body class="calibre" aid="0">
  </body>
</html>

(BeautifulSoup 示例,但我没有特别关注任何解析器)

>>> soup = bs4.BeautifulSoup(html_markup)
>>> title_tag = soup.find('title')
>>> get_offsets_in_markup(title_tag)  # <-------- how do I go about doing this?
(109, 139)  # <----- source mapping info I want to get
>>> html_markup[109:139]
'<title>No Longer Human</title>'

我没有在任何可用的 Python HTML 解析器的 API 中看到此功能。我可以将它破解到现有的解析器之一吗?我该怎么做呢?还是有其他更好的方法?

我意识到str(soup_element) 将元素序列化回标记(我可以假设我可以在树中递归保存开始和结束索引),但是这样做返回的标记,虽然在语义上等同于原始的,与原始的 char-for-char 不匹配。没有可用的 Python 解析器。

【问题讨论】:

  • 这可能是XY Problem 的情况吗?
  • @AMC 上下文是我有一堆电子书注释,我需要为每个注释找到相应的 XPath。每个注释都包含电子书的 HTML 标记中的开始和结束字节偏移量(每本电子书都表示为一个长字节串)。我没有关于注释的其他数据,除了它们的开始和结束偏移量。
  • 哎呀,听起来很难,祝你好运!
  • beautifulsoup 可以通过line numbers 为您提供行偏移,仅适用于html.parserhtml5lib

标签: python beautifulsoup html-parsing elementtree html5lib


【解决方案1】:

您可以使用正则表达式查找相应元素的开始和索引,并使用原始字符串中的这些索引来查找数据:

import re
from bs4 import BeautifulSoup
from pathlib import Path

def get_offsets_in_markup(tag, html_markup):
    elem = re.search(str(title_tag), html_markup)
    return elem.start(), elem.end()

html_markup = Path('test.html').read_text()
soup = BeautifulSoup(html_markup, 'lxml')

title_tag = soup.find('title')

indexes = get_offsets_in_markup(title_tag, html_markup)
# -> (109, 139)
given_text = html_markup[indexes[0]:indexes[1]]
# -> <title>No Longer Human</title>

这就是test.html 的样子:

<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en-gb">
  <head>
    <title>No Longer Human</title>
    <meta content="urn:uuid:6757faf0-eef1-45d9-b2b3-7462350db7ba" name="Adept.e$
    <meta content="text/html; charset=utf-8" http-equiv="Content-Type"/>
  <link href="kindle:flow:0002?mime=text/css" rel="stylesheet" type="text/css"/>
  <link href="kindle:flow:0001?mime=text/css" rel="stylesheet" type="text/css"/>
  </head>
  <body class="calibre" aid="0">
  </body>
</html>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-07-03
    • 1970-01-01
    • 2017-07-18
    • 2017-03-10
    • 2016-03-18
    • 2020-03-30
    • 2022-07-26
    相关资源
    最近更新 更多