我试图使用python(使用pyquery和lxml)来改变和清理一些HTML。
Eg. html = "<div><!-- word style><bleep><omgz 1,000 tags><--><p>It’s a spicy meatball!</div>"
lxml.html.clean函数clean_html()运行良好,只不过它取代了很好的html实体,比如
’
带有一些unicode字符串
\xc2\x92
unicode在不同的浏览器中看起来很奇怪(使用自动编码的firefox和opera,utf8,latin-1等),就像一个空盒子。如何阻止lxml转换实体?如何以latin-1编码完成所有操作?看起来很奇怪,专门为html构建的模块会这样做。
我无法确定哪些角色存在,所以我无法使用
replace("\xc2\x92","’").
我尝试过使用
clean_html(html).encode('latin-1')
但是unicode仍然存在。
是的,我告诉别人不要用文字来写html,但是我会听到整个
&#34;我喜欢它,因为你不能让我变得更好。
编辑:一个美丽的解决方案:
from BeautifulSoup import BeautifulSoup, Comment
soup = BeautifulSoup(str(desc[desc_type]))
comments = soup.findAll(text=lambda text:isinstance(text, Comment))
[comment.extract() for comment in comments]
print soup
答案 0 :(得分:11)
有一些事情 - 如果你了解它们 - 将导致最简单/最好的解决方案:
clean_html()
返回与您提供的相同类型:如果您给它一个字符串,它将返回一个字符串,但如果您给它一个Element或ElementTree,它将返回一个Element或ElementTree分别
您可以通过为lxml.html.tostring()
方法或树的write()
方法提供编码选项来控制Element或ElementTree的序列化方式(顺便说一下,xml也是如此)。例如,您可以使用encoding='utf-8'
执行此操作。
任何可以在该编码中编码的内容都将作为编码字符串输出,任何不能作为实体“转义”的内容。使用encoding="ascii"
会强制任何非ascii字符成为您想要的“漂亮”实体。
放在一起,这意味着:首先将字符串解析为元素(或树,如果您愿意),清理它,并根据需要对其进行序列化:
html = lxml.html.fromstring("<div><!-- word style><bleep><omgz 1,000 tags><--><p>It’s a spicy meatball!</div>")
html = clean_html(html)
result = lxml.html.tostring(html, encoding="ascii")
(稍微脏一点的技巧是在unicode字符串的encode()
方法上使用errors参数:尝试使用s.encode('ascii', 'xmlcharrefreplace')
编码包含“特殊”字符的unicode字符串,看看它的作用。 ..)
答案 1 :(得分:2)
我认为’
应该是引号。使用chr(146)
解码的字节值为146的cp1252
的str对象是引号:
In [46]: print(chr(146).decode('cp1252'))
’
所以,你可以这样做:
import lxml.html.clean as clean
import re
html = "<div><!-- word style><bleep><omgz 1,000 tags><--><p>It’s a spicy meatball!</div>"
html=re.sub('&#(\d+);',lambda m: chr(int(m.group(1))).decode('cp1252'),html)
print(html)
# <div><!-- word style><bleep><omgz 1,000 tags><--><p>It’s a spicy meatball!</div>
print(type(html))
# <type 'unicode'>
print(clean.clean_html(html))
# <div><p>It’s a spicy meatball!</p></div>
或者,
doc=lh.fromstring(html)
clean.clean(doc)
请注意,引号的unicode代码点值为8217.即ord(chr(146).decode('cp1252'))
等于8217,因此lh.tostring
返回:
print(lh.tostring(doc))
# <div><p>It’s a spicy meatball!</p></div>
您可以在cp1252中重新编码,如下所示:
print(repr(lh.tostring(doc,encoding='cp1252')))
# '<div><p>It\x92s a spicy meatball!</p></div>'
我不知道如何哄骗lxml返回
'<div><p>It’s a spicy meatball!</p></div>'
匹配BeautifulSoup代码的输出。好吧,显然它可以用正则表达式完成(颠倒我上面做的),但我不知道这是否必要或可取,因为lxml应该已经返回其他应用程序可以理解的html。
result=re.sub('&#(\d+);',lambda m: '&#{n};'.format(
n=ord(unichr(int(m.group(1))).encode('cp1252'))),
lh.tostring(doc))
print(result)
# <div><p>It’s a spicy meatball!</p></div>
答案 2 :(得分:1)
您也可以将utf8字符串转换为带有xml字符的ascii
result = result.decode('utf-8').encode('ascii', 'xmlcharrefreplace')