如何捕获HTML,不受捕获库的干扰?

2022-09-28 20:17:13 发布

您现在位置:Python中文网/ 问答频道 /正文

有没有一个Python库可以让我得到一个任意的HTML片段,而不需要修改标记?据我所知,lxml、BeautifulSoup和pyquery都使soup.find(".arbitrary-class")这样的东西变得很容易,但是它返回的HTML是格式化的。我要原始的原始标记。你知道吗

例如,假设我有:

<html>
  <head>
    <title>test</title>
  </head>
  <body>
    <div class="arbitrary-class">
      This is some<br />
      markup with <br>
      <p>some potentially problematic</p>
      stuff in it <input type="text" name="w00t">
    </div>
  </body>
</html>

我想准确地捕捉:

"
      This is some<br />
      markup with <br>
      <p>some potentially problematic</p>
      stuff in it <input type="text" name="w00t">
    "

…空格和all,并且不损坏要正确格式化的标记(例如<br />)。你知道吗

问题是,这3个库似乎都是在内部构造DOM的,只是返回一个Python对象,表示文件应该是什么,而不是它是什么,所以我不知道从哪里/如何获得我需要的原始代码片段。你知道吗


Tags: 标记brdivtitleishtmlwithbodysomethisheadclassmarkuparbitrary
1条回答
网友
1楼 ·

此代码:

from bs4 import BeautifulSoup
with open("index.html") as fp:
    soup = BeautifulSoup(fp, "html.parser")
    print soup.select(".arbitrary-class")[0].contents

将返回列表:

[u'\n      This is some', <br/>, u'\n      markup with ', <br/>, u'\n', <p>some potentially problematic</p>, u'\n      stuff in it ', <input name="w00t" type="text"/>, u'\n']

编辑:

正如Daniel在评论中指出的,这将导致规范化的标记。你知道吗

我能找到的唯一替代方法是使用解析器生成器,比如pyparsing。下面的代码是对withAttribute函数的一些example code的稍微修改。你知道吗

from pyparsing import *

html = """<html>
<head>
    <title>test</title>
</head>
<body>
    <div class="arbitrary-class">
    This is some<br />
    markup with <br>
    <p>some potentially problematic</p>
    stuff in it <input type="text" name="w00t">
    </div>
</body>
</html>"""

div,div_end = makeHTMLTags("div")

# only match div tag having a class attribute with value "arbitrary-class"
div_grid = div().setParseAction(withClass("arbitrary-class"))
grid_expr = div_grid + SkipTo(div | div_end)("body")
for grid_header in grid_expr.searchString(html):
    print repr(grid_header.body)

此代码的输出如下:

'\n    This is some<br />\n    markup with <br>\n    <p>some potentially problematic</p>\n    stuff in it <input type="text" name="w00t">'

请注意,第一个<br/>现在有一个空格,<input>标记不再有一个added/before the closing>;。与您的规范的唯一区别是缺少尾随空格。您可以通过改进此解决方案来解决此差异。你知道吗

热门问题