我正在运行以下网络抓取器代码:
25 # save source page and return xpath tree
26 def scrape_Page(url, path):
27 page = requests.get(url)
28 tree = html.fromstring(page.text)
29 # save html content
30 file_name = url.split('/')[-1] + ".html"
31 with open(os.path.join(path, file_name), 'wb') as srcFile:
32 webPage = urllib.urlopen(url)
33 wPageSrc = webPage.read()
34 webPage.close()
35 # write to text file
36 srcFile.write(wPageSrc)
37 return tree
这段代码适用于某些网址,但对其他网址却很失败,而且这里有我收到的错误消息:
tree = html.fromstring(page.text)
File "/Library/Python/2.7/site-packages/lxml/html/__init__.py", line 669, in fromstring
doc = document_fromstring(html, parser=parser, base_url=base_url, **kw)
File "/Library/Python/2.7/site-packages/lxml/html/__init__.py", line 563, in document_fromstring
value = etree.fromstring(html, parser, **kw)
File "lxml.etree.pyx", line 2993, in lxml.etree.fromstring (src/lxml/lxml.etree.c:62433)
File "parser.pxi", line 1584, in lxml.etree._parseMemoryDocument (src/lxml/lxml.etree.c:91750)
ValueError: Unicode strings with encoding declaration are not supported. Please use bytes input or XML fragments without declaration.
答案 0 :(得分:0)
tl; dr:使用html.fromstring(r.content)
。
有关详细信息,请参阅Python unicode strings下的lxml
文档:
... lxml.etree中的解析器可以直接处理unicode字符串...但是,这需要unicode字符串本身不指定冲突的编码,因此谎言他们的实际编码...同样,当你尝试时会出现错误与unicode字符串中的HTML数据相同,该字符串在标头的元标记中指定字符集。您通常应该避免在将XML / HTML数据传递到解析器之前将其转换为unicode。它既慢又容易出错。
同时,如果您查看requests
文档,请Response Content下:
请求将自动解码服务器中的内容。大多数unicode字符集都是无缝解码的...当您发出请求时,Requests会根据HTTP标头对响应的编码进行有根据的猜测。访问
r.text
时会使用请求猜到的文本编码。
因此,将这些放在一起,你永远不应该调用html.fromstring(page.text)
,因为page.text
会自动解码为Unicode,lxml
不需要Unicode。 lxml
想要的是原始的未解码字节。
如何从requests
中获取原始未解码的字节?请查看requests
文档的下一部分Binary Response Content:
对于非文本请求,您还可以以字节形式访问响应正文...
r.content
如果你不理解Unicode字符串和字节字符串之间的区别,以及所有这些解码废话的含义,那么文档中的Unicode HOWTO就有了很好的解释。但基本上:网络套接字(和文件,以及许多其他东西)只以字节为单位,这意味着它们只能处理256个不同的值,但是有数十万个字符。你怎么处理那件事呢?您选择一种编码,使用它将Unicode文本转换为字节序列,通过线路发送,然后在另一端解码。这意味着您需要某种方式来指定您选择的编码,以便另一方可以对其进行解码。网页通常在标题中指定它,尽管还有其他一些方法可以做到。 requests
试图变得聪明并为您挖掘信息并负责解码,因此您不必考虑它,这通常非常酷。不幸的是,lxml
也试图变得聪明并为你找出解码,如果他们都试图这样做,他们就会互相混淆。