gpt4 book ai didi

python - 当表格缺少 thead 元素时,使用 beautifulsoup/lxml 检测 HTML 表格中的 header

转载 作者:行者123 更新时间:2023-12-01 02:45:32 25 4
gpt4 key购买 nike

当 HTML 表格没有 <thead> 时,我想检测该表格的 header 元素。 (MediaWiki,它驱动维基百科,does not support <thead> elements。)我想在 BeautifulSoup 和 lxml 中使用 python 来完成此操作。假设我已经有一个 table对象,我想摆脱它 thead对象,一个tbody对象,以及 tfoot对象。

目前,parse_thead<thead> 时执行以下操作标签存在:

  • 在 BeautifulSoup 中,我使用 doc.find_all('table') 获取表对象我可以使用table.find_all('thead')
  • 在 lxml 中,我使用 doc.xpath() 获取表对象在 //table 上的 xpath_expr 上,我可以使用table.xpath('.//thead')

parse_tbodyparse_tfoot以同样的方式工作。 (我没有写这段代码,而且我对 BS 或 lxml 都没有经验。)但是,没有 <thead> , parse_thead不返回任何内容并且 parse_tbody一起返回 header 和正文。

我附加一个wikitable instance以下为例。它缺少<thead><tbody> 。相反,所有行(无论是否有标题)都包含在 <tr>...</tr> 中。 ,但标题行有 <th>元素和主体行有 <td>元素。没有<thead> ,似乎识别标题的正确标准是“从一开始,将行放入标题中,直到找到包含不是 <th> 的元素的行”。

我很感激有关如何写作 parse_thead 的建议和parse_tbody 。如果没有太多经验,我想我可以

  • 深入研究表对象并手动插入 theadtbody在解析它之前添加标签(这看起来不错,因为这样我就不必更改任何其他识别带有 <thead> 的表的代码),或者
  • 更改parse_theadparse_tbody识别仅包含 <th> 的表行元素。 (无论哪种选择,似乎我确实需要以这种方式检测头体边界。)

我不知道如何做这两件事,我很乐意就哪种选择更明智以及我如何去做提供建议。

(编辑:使用 no header rowsmultiple header rows 的示例。我不能假设它只有一个标题行。)

<table class="wikitable">
<tr>
<th>Rank</th>
<th>Score</th>
<th>Overs</th>
<th><b>Ext</b></th>
<th>b</th>
<th>lb</th>
<th>w</th>
<th>nb</th>
<th>Opposition</th>
<th>Ground</th>
<th>Match Date</th>
</tr>
<tr>
<td>1</td>
<td>437</td>
<td>136.0</td>
<td><b>64</b></td>
<td>18</td>
<td>11</td>
<td>1</td>
<td>34</td>
<td>v West Indies</td>
<td>Manchester</td>
<td>27 Jul 1995</td>
</tr>
</table>

最佳答案

使用 XPath 执行此操作 W3C MDN 希望更加通用。请注意,不包含命名空间,这可能是必需的,具体取决于您的环境。此答案已通过 this xpath tester 验证链接自 MDN。

* 对于下面的内容,假设 XPath 相对于表,即您正在 <table> 上调用 xpath 函数元素,因此 .<table> ;或者你可以在前面加上 //table//到路径。

示例

以下内容是在Python中使用lxml[1],因为这就是问题中提到的内容。 parse_thead返回<tr>所提供节点的子元素,并且仅具有 <th>细胞。 parse_tbody返回<tr>至少有一个 <td> 的元素单元格:

_TR_HEADER = './/tr[count(th)=count(th|td)]'
_TR_BODY = './/tr[count(th)<count(th|td)]'
def parse_thead(table):
return table.xpath(_TR_HEADER)
def parse_tbody(table):
return table.xpath(_TR_BODY)

默认查找 <thead> 应该相对简单。和<tbody>在采用此策略之前要考虑的因素。

处理格式错误的 HTML 表比较困难,如果您仅限于 XPath 1.0,则可能需要一些预处理和后处理。

说明

选择“标题”表行( <tr> 元素),其中所有子项均为 <th>元素:

_TR_HEADER = '//tr[count(th)=count(*)'

选择“正文”表行,其中至少有一个子项不是 <th> :

_TR_BODY = '//tr[count(th)<count(*)'

改进

  • 仅在没有 <td> 的情况下选择行作为标题细胞:

    _TR_HEADER = '//tr[count(td)=0]'
  • 如果没有行满足要求,则始终选择第一行作为标题[2]:

    _TR_HEADER = '//tr[..[count(tr[count(th)=count(*)])=0] and position()=1 or count(th)=count(*)]'
  • 始终选择 <thead> 中出现的行标记除了满足要求的行:

    _TR_HEADER = '//tr[count(th)=count(*) or ..[name()="thead"]]
  • 选择最多包含一个 <th> 的行作为正文以及至少一个<td> :

    _TR_BODY = '//tr[count(th)<2 and count(td)>1]
  • 如果没有标题,或者它们出现在标题后面,则选择行作为正文[2]:

    _TR_BODY = '//tr[..[count(tr[count(th)=count(*)])=0] or preceding-sibling::tr[count(th)=count(*)] and count(th)<count(*)]'
  • 如果行遵循问题中定义的最后一个标题行,则选择行作为正文:

    _TR_BODY = '//tr[count(th)=count(th|td)][last()]/following-sibling::tr

注意事项

  • 没有命名空间信息,但在某些环境中可能需要该信息。
  • 上面有一些关于格式良好的表的假设,如果存在例如以下情况,则可能会失败。 spans 或类似的方式包裹行或单元格元素。
  • 此答案假设问题中指定的表格仅包含 <th>标题行中的单元格,并且至少有一个 <td>在正文行中。
  • 在嵌套表上使用时,它也可能没有所需的行为。添加谓词以查找初始 <table>或者前置路径可能会有所帮助,就像指定中间节点如 <tbody> 一样。而不是使用// .
  • 它也没有专门处理 row-spancol-span属性,尽管这可以通过对所选元素进行后处理来完成。
<小时/>

[1] 请注意,这可能需要提供 namespace="http://www.w3.org/1999/xhtml"作为 {node}.xpath 的命名参数调用,我认为取决于您使用的解析器。

[2] 请注意,这很困惑,因为没有 sibling-or-self值得信赖,因此 ..[count(...)] 。我将答案限制为 XPath 1.0,因为 XPath 2.0 及更高版本的功能并不总是受支持。另外使用parent打破的情况下有一个 <thead>包装。如果原始路径没有返回节点,则运行替代选择将是一个很好的解决方案。

关于python - 当表格缺少 thead 元素时,使用 beautifulsoup/lxml 检测 HTML 表格中的 header ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45292001/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com