python - 使用 lxml 解析段落标记的子项时缺少子项

标签 python html xpath xml-parsing lxml

我正在使用 Python 库 lxml对从 this url 检索到的 HTML 执行 XML 解析.过去我在使用 lxml 时没有遇到任何问题,但是我可能刚刚遇到了一个错误,其形式是缺少子元素(在 lxml 树中),它明显出现在 HTML 中。

这是我用来解析 HTML 的 Python 代码:

from urllib.request import urlopen
from lxml import etree

html_response = urlopen("http://ohhla.com/YFA_natedogg.html")
html_parser = etree.HTMLParser()
tree = etree.parse(html_response, html_parser)
tree.xpath("//table[@id='AutoNumber7']/tr[2]/td/p[1]")[0]

我正在解析的网站 HTML 代码的简化版本如下所示:

<table id='AutoNumber7'>
    <tbody>
        <tr></tr>
        <tr>
            <td>
                # ... (irrelevant tags) ... 
                <p>
                    <a></a>
                    # The following <table> tag is what I need to target:
                    <table></table>
                </p>
                # ... (seven <p> tags identical to the above) ...
            </td>
        </tr>
    </tbody>

当我运行 tree.xpath("//table[@id='AutoNumber7']/tr[2]/td/p[1]")[0].getchildren() 在控制台中,lxml 仅检测初始 anchor 标记 <a>并忽略兄弟 <table>我需要选择的标签(由代码中的上述注释表示)。

这是控制台输出:

tree.xpath("//table[@id='AutoNumber7']/tr[2]/td/p[1]")[0].getchildren()
Out[22]: [<Element a at 0x2904a2a5808>]

我希望看到的是:

tree.xpath("//table[@id='AutoNumber7']/tr[2]/td/p[1]")[0].getchildren()
Out[22]: [<Element a at 0x2904a2a5808>, <Element table at 0x???????????>]

关于为什么 <table> 的任何想法<p> 中缺少标签标签的 child ? 我怎样才能选择这个 <table>标签?我需要解析 table 标签中的所有内容,但 lxml 似乎无法将其识别为有效的子元素。如果有人可以为所需的 <table> 提供有效的 xpath 选择器标签 我将非常感激!

注意:我知道我真的应该看到 [<Element tr at 0x??????????>, <Element tr at 0x???????????>, ...]不是 [<Element table at 0x??????????>]但我试图更简洁。

编辑:对于那些认为上述代码不可重现的人,只需将其复制并粘贴到控制台即可:

from urllib.request import urlopen
from lxml import etree

html_response = urlopen("http://ohhla.com/YFA_natedogg.html")
html_parser = etree.HTMLParser()
tree = etree.parse(html_response, html_parser)
print(tree.xpath("//table[@id='AutoNumber7']/tr[2]/td/p[1]")[0].getchildren())

和以前一样,我尝试解析的 HTML 位于 here .

我真的不知道如何比这更简洁。建设性意见表示赞赏(一如既往)。

  • 链接到我已经阅读过的页面(例如 How to create a Minimal, Complete, and Verifiable example)没有评论 不是建设性的批评。
  • 指出我可能错过了哪些步骤,或者将来(从特定资源)需要改进的地方是建设性的批评,对我自己和整个社区都有好处。
  • 我很乐意接受有关如何改进我的帖子的建议,但请提供实际的建议。请记住,多个人可能会阅读相同的资源并得出不同的结论。

最佳答案

我认为问题在于 lxml 试图按照 HTML 规则进行游戏。根据这些规则,<table> ( block 级元素)不能是 <p> 的子元素.参见 https://www.w3.org/TR/html4/struct/text.html#h-9.3.1 .

简短演示:

from lxml import html

test = """
<html>
  <p>
    <table>
      <tr>
        <td>XXX</td>
      </tr>
    </table>
  </p>
</html>"""

root = html.fromstring(test)

# Just print the string representation of the parsed HTML
print(html.tostring(root).decode("UTF-8"))

在此代码的输出中,我们可以看到 lxml 拒绝解释 <table>作为 <p> 的 child :

<html>
  <body><p>
    </p><table>
      <tr>
        <td>XXX</td>
      </tr>
    </table>

</body></html>

<a>是一个内联元素,所以它包含在 getchildren() 的返回值中是有意义的.您将不得不找到其他方法来识别 <table>您感兴趣的元素。

http://ohhla.com/YFA_natedogg.html document自称是XHTML,但错误较多,无法解析为XML文档。

关于python - 使用 lxml 解析段落标记的子项时缺少子项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44976672/

相关文章:

python - 根据列表中每个元素的内容从列表中获取元素

python - 如何检测瓷砖上的裂缝?

php - 在 <select> 标签内而不是在 <option> 上定义选择的任何方式

c# - 为什么将 xml 根目录作为 xpath 的一部分时我没有得到任何结果

xpath - 使用算术运算符的Xpath 1.0

language-agnostic - XPath 2.0 : Open implementations

python - 从 C++ 运行 python 脚本

html - 在 child 之前停止 parent 背景??可以在CSS中完成吗?

javascript - 将 DIV 拖动到水平可排序容器

python - 'METHODNAME' 作为客户端方法与扭曲的 irc _'METHODNAME'