在用正则表达式查找HTML文档内容后,如何有效地使用lxml?
我正在尝试从大量的HTML文档中提取一些文本,这些文档的数量有几十万。其实这些文档主要是表单,但它们是由很多不同的组织制作的,所以格式差异很大。例如,这些文档分成了几个章节。我可能想提取每个文档中第5章的内容,以便分析这一章的内容。起初我以为这很简单,但结果发现,作者可能在文档中使用了一些不嵌套的表格来存放内容,这样第n章的内容就可能用表格中的
标签、 在多次尝试使用lxml来帮助我识别每章的开始和结束后,我发现使用正则表达式会更简单,因为无论外层的HTML元素是什么,章节标签总是以特定的形式出现。 这稍微复杂一点,因为可能会有一些空白字符或不换行的空格,以不同的方式表示(比如 或 或只是空格)。尽管如此,写一个正则表达式来识别每个部分的开始是非常简单的。(一个部分的开始就是前一个部分的结束。) 但现在我想用lxml来提取文本。我想我别无选择,只能沿着我的字符串查找包裹我所需文本的元素的结束标签。 这里有一个例子,章节名称所在的元素是一个 所以我想象着从我找到第1章的位置开始,设置一个正则表达式来查找下一个 到目前为止,我已经确定了包含章节标题的元素类型。 我可以用同样的逻辑找到这个元素内的所有文本,并设置一个正则表达式来帮助我标记从 所以我已经找到了第1章的开始位置。 我可以对第2章做同样的事情(这就是第1章的结束位置)。 现在我想象着从我确定的第1章开始的元素打开的位置开始剪切文档,并在我确定的第2章开始的元素打开之前结束。我找到的字符串将被传递给lxml,利用它的强大功能来获取内容。 我之所以这么麻烦,是因为我反复听说——永远不要用正则表达式从HTML文档中提取内容,而我还没有找到用lxml准确识别我想提取的文本的开始和结束位置的方法。例如,我永远不能确定第1章的副标题是“我们的开始”,也可能是“我们的红色金丝雀”。我可以告诉你,我花了整整两天的时间尝试用lxml来确保我找到了开始和结束的元素,但准确率只有60%不到,而一个很短的正则表达式让我成功率超过了95%。 我有时会把事情搞得比必要的更复杂,所以我想知道是否有人见过或解决过类似的问题,如果他们有一种方法(不需要详细说明)愿意分享。 听起来你可以做的最简单的事情就是遍历树的根节点,使用 举个例子,如果你发现目标是 问题的关键似乎在于,你正在挖掘的数据并不是以编程的方式呈现的——在这种情况下,通常需要一定程度的人为干预。 有时候,处理那些写得不好或者不一致的HTML时,获取内容的方式并不是那么简单。 你可以考虑使用lynx或者其他一些基于文本的浏览器来提取页面内容,可以把内容保存到文件里,或者直接传输到你的代码中,然后再进行处理。或者,你也可以用lxml来加载和解析页面,然后用text_content()提取文本,再通过正则表达式来获取章节。 就像人们常说的,GIGO——垃圾进,垃圾出。作为开发者,我们的任务就是把这些垃圾变成有用的东西。不过,这个过程可能会变得相当麻烦。 正如我担心的那样,使用lxml来识别和提取我需要的内容并没有一个系统的方法。唉,我还是很感谢大家的参与。需要说明的是,这并不是lxml的问题,而是因为HTML编码不一致导致的。例如,一个章节是文档的合理划分,所有章节的内容应该被包裹在某种元素中。最灵活的方式可能是使用 我可以检查每种应该包含我内容的元素(比如 ),然后获取它的所有子元素和兄弟元素,直到找到下一个同类型的元素,这个元素的信息会告诉我我们已经到达了这一部分的结束(也就是下一部分的开始)。但这样做似乎太麻烦了,因为我用正则表达式处理95%以上的情况都很顺利。 感谢大家的回答和评论,像往常一样,我从中学到了很多。>Chapter #
<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.   Our Beginnings.</font></div>
</div|</td|</p|</h1 . . .
>Chapter 1.   Our Beginnings.<
3 个回答
tree.getroot().iterdescendants()
方法,寻找一个节点,它的 node.text
和你想要的正则表达式匹配。找到这个节点后,你可以把它传给一个函数,这个函数会用一些简单的规则来判断文本的位置。(如果在根节点上使用 iterdescendants
太慢,你可以用正则表达式的方法,深入到 etree 中,尝试找到一个 f(text_position) -> node
的函数。)//tr/td
,你可以把它传给一个寻找表格文本的子程序,这个子程序会查看节点的父节点中的下一个 td
,看看里面的文本是否合理(大概是章节长度,包含某些词等等)。同样的,你也可以为寻找其他标签中的数据,比如 div
和 p
,制定一些简单的规则。如果你碰到一个不熟悉的标签,比如 font
,你可以尝试向上查找有限的层级,找到一些你知道怎么处理的东西——不过要小心,不要查找得太高,否则可能会意外获取到其他章节的文本。撰写回答