我是python的新手,我试图用lxml解析一个Html页面。我想从<p>
标记中获取文字。但在其中我有一个奇怪的标签:
<p style="margin-left:0px;padding:0 0 0 0;float:left;">
<g:plusone size="medium">
</g:plusone>
</p>
如何在<p>
内忽略此标记?我想用&#34;:&#34;切割所有标签在任何html页面内,因为lxml的另一个功能无法正常使用这样的标签。
parser=etree.HTMLParser()
tree = etree.parse('problemtags.html',parser)
root=tree.getroot()
text = [ b.text for b in root.iterfind(".//p")]
我希望在<p>
标签内部获得一些文字。但是当我看起来像这样时,它会像上面那样在片段上失败。它写道:&#34; b&#39;标记g:plusone无效&#39;&#34;。我只需要 - 它会忽略所有这样的incorect标签。我不确切知道将来有多少这样的标签,但我认为问题确实存在于&#34;:&#34;现在,因为当我使用&#34; .tag&#34;并获得名称,它只是&#34; plusone&#34;而不是&#34; g:plusone&#34;。
答案 0 :(得分:0)
这是我发现清理html的方法:
from lxml import etree
from StringIO import StringIO
s = '''<p style="margin-left:0px;padding:0 0 0 0;float:left;">
<g:plusone size="medium">
</g:plusone>
</p>'''
parser = etree.HTMLParser()
tree = etree.parse(StringIO(s), parser)
result = etree.tostring(tree.getroot(),pretty_print=True,method="html")
print result
打印
<html><body><p style="margin-left:0px;padding:0 0 0 0;float:left;">
<plusone size="medium">
</plusone>
</p></body></html>
要从etree._ElementTree获取etree.Element引用,即etree._Element,只需
root = tree.getroot()
print type(root) # prints lxml.etree._Element
根据_Element-class,lxml.etree._Element是文档实例引用的类,换句话说,它是实例化etree.Element的结果,例如
el = etree.Element("an_etree.Element_reference")
print type(el) # prints lxml.etree._Element
答案 1 :(得分:0)
g:
是名称空间前缀。实际的标记名称仅为plusone
。因此,lxml仅在返回plusone
作为标记名称时是正确的。请参阅命名空间here的摘要。
据我了解,lxml的HTML Parser不支持名称空间。但是,XML Parser是。据推测,假设这个HTML文档包含XML,它很可能实际上是一个XHTML文档(如果没有,那么它可能是一个无效的HTML文档,你不能指望lxml正确地解析它)。因此,您需要通过XML Parser而不是HTML Parser运行它。 lxml的命名空间API在tutorial。
中进行了解释但是,使用您提供的片段,解析器将返回:
>>> d = etree.fromstring('''<p style="margin-left:0px;padding:0 0 0 0;float:left;">
... <g:plusone size="medium">
... </g:plusone>
... </p>''')
Traceback (most recent call last):
File "<stdin>", line 4, in <module>
File "lxml.etree.pyx", line 3032, in lxml.etree.fromstring (src\lxml\lxml.etree.c:68121)
File "parser.pxi", line 1786, in lxml.etree._parseMemoryDocument (src\lxml\lxml.etree.c:102470)
File "parser.pxi", line 1674, in lxml.etree._parseDoc (src\lxml\lxml.etree.c:101299)
File "parser.pxi", line 1074, in lxml.etree._BaseParser._parseDoc (src\lxml\lxml.etree.c:96481)
File "parser.pxi", line 582, in lxml.etree._ParserContext._handleParseResultDoc (src\lxml\lxml.etree.c:91290)
File "parser.pxi", line 683, in lxml.etree._handleParseResult (src\lxml\lxml.etree.c:92476)
File "parser.pxi", line 622, in lxml.etree._raiseParseError (src\lxml\lxml.etree.c:91772)
lxml.etree.XMLSyntaxError: Namespace prefix g on plusone is not defined, line 2, column 23
请注意,它会抱怨&#34; Namespace prefix g on plusone is not defined
。&#34;据推测,在文档的其他位置定义了名称空间前缀。由于我不知道那是什么,我只是做一些事情并定义你的片段中的plusone
标签:
>>> d = etree.fromstring('''<p style="margin-left:0px;padding:0 0 0 0;float:left;">
... <g:plusone xmlns:g="something" size="medium">
... </g:plusone>
... </p>''')
>>> d
<Element p at 0x2563cd8>
>>> d.tag
'p'
>>> d[0]
<Element {something}plusone at 0x2563940>
>>> d[0].tag
'{something}plusone'
请注意,在这种情况下,g:
前缀替换为实际名称空间({something}
,因为我设置如下:xmlns:g="something"
)。通常命名空间实际上是URI。因此,您可能会发现您的代码看起来像这样:{http://where.it/is/from.xml}plusone
尽管如此,我觉得在没有必要时使用命名空间相当麻烦。实际上,您可能会发现使用忽略命名空间的HTML解析器更容易。现在您知道标记名为plusone
,而不是g:plusone
,您可以仅使用HTML解析器继续工作。