2

我正在尝试从大量 html 文档(数以十万计)中提取一些文本。这些文档实际上是表格,但它们是由一大群不同的组织准备的,因此它们创建文档的方式存在显着差异。例如,文档分为章节。我可能想从每个文档中提取第 5 章的内容,以便分析该章的内容。最初我认为这很容易,但事实证明作者可能会在整个文档中使用一组非嵌套表格来保存内容,以便可以在表格中使用 td 标签显示第 n 章。或者他们可能会使用其他元素,例如 p 标签 H 标签、div 标签或任何其他块级元素。

在反复尝试使用 lxml 来帮助我识别每章的开头和结尾之后,我确定使用正则表达式要干净得多,因为在每种情况下,无论封闭的 html 元素是什么,章节标签总是在的形式

>Chapter #

它有点复杂,因为可能会有一些空白或不间断的空间以不同的方式(或只是空格)表示。尽管如此,编写一个正则表达式来标识每个部分的开头是微不足道的。(一节的开头是上一节的结尾。)

但现在我想使用 lxml 来获取文本。我的想法是,我真的别无选择,只能沿着我的字符串查找包含我用来查找相关部分的文本的元素的关闭标记。

这是一个示例,其中包含章节名称的元素是 div

<div style="DISPLAY: block; MARGIN-LEFT: 0pt; TEXT-INDENT: 0pt; MARGIN-RIGHT: 0pt" align="left"><font style="DISPLAY: inline; FONT-WEIGHT: bold; FONT-SIZE: 10pt; FONT-FAMILY: Times New Roman">Chapter 1.&#160;&#160;&#160;Our Beginnings.</font></div>

所以我想象我将从找到第 1 章匹配项的位置开始,并设置一个正则表达式来查找下一个

</div|</td|</p|</h1 . . .

所以在这一点上,我已经确定了持有我的章节标题的元素类型

我可以使用相同的逻辑来查找该元素中的所有文本,这些文本设置了一个正则表达式来帮助我标记

>Chapter 1.&#160;&#160;&#160;Our Beginnings.<

所以我已经确定了我的第 1 章从哪里开始

我可以为第 2 章做同样的事情(这是第 1 章的结尾)

现在我想象我要从我标识为元素的元素的开头开始剪切文档,该元素指示第 1 章的开始位置,并在我标识为指示章节位置的元素的开头之前结束2开始。然后,我确定的字符串将被馈送到 lxml 以使用它的能力来获取内容。

我会遇到所有这些麻烦,因为我一遍又一遍地阅读 - 永远不要使用正则表达式从 html 文档中提取内容,而且我还没有找到一种方法来准确地使用 lxml 来识别我要提取的文本。例如,我永远无法确定第一章的副标题是我们的起点,它可能是我们的红金丝雀。让我说,我花了两天时间尝试使用 lxml 来确信我有开始和结束元素,而且我只能在 <60% 的时间内准确,但是一个非常短的正则表达式给了我超过 95% 的成功率。

我倾向于使事情变得比必要的更复杂,所以我想知道是否有人已经看到或解决了类似的问题,以及他们是否有他们想要提供的方法(而不是细节介意)。

4

3 回答 3

2

在处理写得不好或不一致的 HTML 时,有时没有一条直接的路径可以获取内容。

您可能希望查看使用 lynx 或其中一种基于文本的浏览器将页面内容转储到文件中,或者将其通过管道传输到您的代码中,然后对其进行处理。或者,您可以使用 lxml 加载和解析页面,然后使用 text_content() 提取文本并通过正则表达式查找章节。

就像他们说的那样,GIGO - 垃圾进,垃圾出,作为开发人员,我们的工作就是将这些垃圾变成黄金。这样做会变得非常混乱。

于 2010-03-10T23:58:25.500 回答
1

听起来您可能做的最简单的事情是遍历 tree.getroot().iterdescendants() 寻找node.text与您所需的正则表达式匹配的节点。从那时起,您可以将节点传递给一个函数,该函数使用一些临时启发式方法来确定文本的位置。(也许如果 root 上的 iterdescendants 太慢,您可以使用您的正则表达式方法并潜入 etree 尝试找到一个f(text_position) -> node函数。)

例如,如果您发现目标是 a //tr/td,您可以将它传递给一些查找表文本的子例程,该例程在 node.parent() 中查看下一个 td 以查看它是否包含有意义的文本(大约为章节长度,包含某些单词,无论如何)。同样,您可以编写一些启发式方法来查找其他标签(如div和)中的数据p。如果您发现自己处于一个未知标签中,例如font您可以尝试冒泡有限数量的级别以找到您知道如何处理的东西——您必须小心不要冒泡太远,否则我想您可能会不小心从另一章。

问题的症结似乎在于您正在挖掘未以编程方式以编程方式呈现的数据——在这些情况下,通常在某种程度上需要人机交互。

于 2010-03-10T23:38:02.617 回答
1

正如我担心的那样,没有系统的方法可以使用 lxml 来识别和提取我需要的东西。哦,我很感谢大家的加入。注意——这不是 lxml 的错,而是不一致的 html 编码的错。例如。因为一章是文档的合理划分,所以一章中的所有内容都应该包含在某种类型的元素中。最灵活的可能是 div 标签,随后的 div 是下一章。这将使一章成为树的一个分支。不幸的是,虽然大约 20% 的文档可能结构良好,但其他文档则不然。

我可以测试应该包含我的内容的每种类型的元素(div,p)并获取它的所有子元素和所有兄弟元素,直到我到达该类型的下一个元素,该元素具有提醒我我们处于部分的结尾(下一部分的开始)。但是,当我 95% 或更多的时间都使用正则表达式时,这似乎工作量太大了。

感谢所有的答案和评论,就像我从他们那里学到的一样。

于 2010-03-17T23:47:51.440 回答