我试图在此代码中用urllib2
替换requests
,只需从页面中提取一些信息即可。我不是100%肯定我应该如何移动库。这就是我到目前为止所犯的错误,我做错了什么?
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import requests, sys
from lxml import etree
# import urllib2
# UTF8
reload(sys)
sys.setdefaultencoding("utf-8")
# url = 'http://countrycode.org/Germany'
# opener = urllib2.build_opener()
# opener.addheaders = [('User-agent', 'USERAGENT')]
r = requests.get('http://countrycode.org/Germany')
response = r.text
htmlparser = etree.HTMLParser()
tree = etree.parse(response, htmlparser)
countryCodeXpath = '//*[@id="main_table_blue_2"]/tr[3]/td[2]'
countryCode = tree.xpath(countryCodeXpath)
destCountryCode = countryCode[0].text
print destCountryCode
Traceback (most recent call last):
File "/home/ubuntu/test.py", line 16, in <module>
tree = etree.parse(response, htmlparser)
File "lxml.etree.pyx", line 3196, in lxml.etree.parse (src/lxml/lxml.etree.c:64039)
File "parser.pxi", line 1549, in lxml.etree._parseDocument (src/lxml/lxml.etree.c:91262)
File "parser.pxi", line 1578, in lxml.etree._parseDocumentFromURL (src/lxml/lxml.etree.c:91546)
File "parser.pxi", line 1478, in lxml.etree._parseDocFromFile (src/lxml/lxml.etree.c:90613)
File "parser.pxi", line 1025, in lxml.etree._BaseParser._parseDocFromFile (src/lxml/lxml.etree.c:87527)
File "parser.pxi", line 565, in lxml.etree._ParserContext._handleParseResultDoc (src/lxml/lxml.etree.c:83101)
File "parser.pxi", line 656, in lxml.etree._handleParseResult (src/lxml/lxml.etree.c:84083)
File "parser.pxi", line 594, in lxml.etree._raiseParseError (src/lxml/lxml.etree.c:83379)
IOError: Error reading file '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<SNIP>
答案 0 :(得分:3)
除了abamert的答案之外,您可以使用原始响应修复此问题:
response = requests.get(<ur>, stream = True)
tree = etree.parse(response.raw, htmlparser)
请参阅请求包文档中的Raw Response Content。
这样,请求不应将所有数据都读入text
属性,而应将raw
响应保留为etree.parse()
可读取的类文件对象。
答案 1 :(得分:1)
问题是你用字符串调用parse
。
在ElementTree API中(无论是stdlib版本,来自PyPI的单独模块,还是lxml实现),parse
函数采用文件名或文件:
来源可以是以下任何一种:
- 文件名/路径
- 文件对象
- 类文件对象
- 使用HTTP或FTP协议的URL
所以,它试图打开一个名为<!DOCTYPE HTML PU…
的文件,当然不存在。
正如文档所说:
要从字符串中解析,请改用
fromstring()
函数。
有一些替代方案。
首先,如上所述,lxml.etree
可以为您检索网址。除非你在这里确实需要requests
的任何额外功能,否则这将更加简单。它会更快,并且不需要将整个文件读入内存,它甚至允许您自动查找DTD和其他外部引用。正如文档所说:
请注意,从文件路径或URL解析通常比从打开的文件对象或类文件对象解析更快。支持从gzip压缩源进行透明解压缩(除非在libxml2中明确禁用)。
或者你可以使用requests
流媒体协议来获取类似文件的对象而不是内容,正如塞巴斯蒂安的回答所解释的那样。这将更复杂而不是更少,并且在其他两个选项之间的速度中间......但如果您需要requests
的其他功能,并且您无法承担将整个页面保留在内存中,那么它是最佳选择
但是,对于这个小到46K的文件,没有理由避免一次性加载它。
答案 2 :(得分:1)
请求返回字符串,所以首先我们需要将该字符串转换为html:
import requests
from lxml import html
response = requests.get('http://your.url')
parsed_body = html.fromstring(response.text)