bis*_*ark 9 python unicode lxml beautifulsoup web-scraping
我试图最终解决从尝试使用lxml抓取HTML时弹出的一些编码问题.以下是我遇到的三个示例HTML文档:
1.
<!DOCTYPE html>
<html lang='en'>
<head>
<title>Unicode Chars: ? —’</title>
<meta charset='utf-8'>
</head>
<body></body>
</html>
Run Code Online (Sandbox Code Playgroud)
2.
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ko-KR" lang="ko-KR">
<head>
<title>Unicode Chars: ? —’</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
</head>
<body></body>
</html>
Run Code Online (Sandbox Code Playgroud)
3.
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Unicode Chars: ? —’</title>
</head>
<body></body>
</html>
Run Code Online (Sandbox Code Playgroud)
我的基本脚本:
from lxml.html import fromstring
...
doc = fromstring(raw_html)
title = doc.xpath('//title/text()')[0]
print title
Run Code Online (Sandbox Code Playgroud)
结果是:
Unicode Chars: ì ââ
Unicode Chars: ? —’
Unicode Chars: ? —’
Run Code Online (Sandbox Code Playgroud)
所以,显然是样本1和缺失<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />标签的问题.此处的解决方案将正确识别样本1为utf-8,因此它在功能上等同于我的原始代码.
lxml文档似乎有冲突:
从这里开始,示例似乎建议我们应该使用UnicodeDammit将标记编码为unicode.
from BeautifulSoup import UnicodeDammit
def decode_html(html_string):
converted = UnicodeDammit(html_string, isHTML=True)
if not converted.unicode:
raise UnicodeDecodeError(
"Failed to detect encoding, tried [%s]",
', '.join(converted.triedEncodings))
# print converted.originalEncoding
return converted.unicode
root = lxml.html.fromstring(decode_html(tag_soup))
Run Code Online (Sandbox Code Playgroud)
不过在这里它说:
[Y]当您在一个unicode字符串中尝试[解析] HTML数据时会出现错误,该字符串在标题的元标记中指定字符集.您通常应该避免在将XML/HTML数据传递到解析器之前将其转换为unicode.它既慢又容易出错.
如果我尝试按照lxml文档中的第一个建议,我的代码现在是:
from lxml.html import fromstring
from bs4 import UnicodeDammit
...
dammit = UnicodeDammit(raw_html)
doc = fromstring(dammit.unicode_markup)
title = doc.xpath('//title/text()')[0]
print title
Run Code Online (Sandbox Code Playgroud)
我现在得到以下结果:
Unicode Chars: ? —’
Unicode Chars: ? —’
ValueError: Unicode strings with encoding declaration are not supported.
Run Code Online (Sandbox Code Playgroud)
样品1现在可以正常工作,但样品3会因<?xml version="1.0" encoding="utf-8"?>标签而导致错误.
有没有正确的方法来处理所有这些情况?有没有比以下更好的解决方案?
dammit = UnicodeDammit(raw_html)
try:
doc = fromstring(dammit.unicode_markup)
except ValueError:
doc = fromstring(raw_html)
Run Code Online (Sandbox Code Playgroud)
jfs*_*jfs 16
lxml有几个 与处理Unicode有关的问题.在明确指定字符编码时,最好使用字节(现在):
#!/usr/bin/env python
import glob
from lxml import html
from bs4 import UnicodeDammit
for filename in glob.glob('*.html'):
with open(filename, 'rb') as file:
content = file.read()
doc = UnicodeDammit(content, is_html=True)
parser = html.HTMLParser(encoding=doc.original_encoding)
root = html.document_fromstring(content, parser=parser)
title = root.find('.//title').text_content()
print(title)
Run Code Online (Sandbox Code Playgroud)
Unicode Chars: ? —’
Unicode Chars: ? —’
Unicode Chars: ? —’
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
9995 次 |
| 最近记录: |