Python中的网页抓取与urlopen
我正在尝试从这个网站获取数据:http://www.boursorama.com/includes/cours/last_transactions.phtml?symbole=1xEURUS
我发现用urlopen这个方法无法获取到网页的HTML代码,我不太明白为什么。
html = urllib.request.urlopen("http://www.boursorama.com/includes/cours/last_transactions.phtml?symbole=1xEURUS")
print (html)
我的代码是正确的,我用同样的代码可以获取其他网页的HTML源代码,但这个地址似乎不被识别。
它打印出来的是:b''
也许换个库会更合适?为什么urlopen不返回这个网页的HTML代码呢?求助,谢谢!
3 个回答
我用httplib2测试了你的网址,也在终端用curl测试过。结果都没问题:
URL = "http://www.boursorama.com/includes/cours/last_transactions.phtml?symbole=1xEURUS"
h = httplib2.Http()
resp, content = h.request(URL, "GET")
print(content)
所以在我看来,要么是urllib.request有个错误,要么就是客户端和服务器之间的互动很奇怪。
我怀疑发生的情况是,服务器在发送压缩数据时并没有告诉你。Python的标准HTTP库无法处理压缩格式。
我建议你使用httplib2,它可以处理压缩格式(而且通常比urllib要好很多)。
import httplib2
folder = httplib2.Http('.cache')
response, content = folder.request("http://www.boursorama.com/includes/cours/last_transactions.phtml?symbole=1xEURUS")
print(response)
显示了来自服务器的响应:
{'status': '200', 'content-length': '7787', 'x-sid': '26,E', 'content-language': 'fr', 'set-cookie': 'PHPSESSIONID=ed45f761542752317963ab4762ec604f; path=/; domain=.www.boursorama.com', 'expires': 'Thu, 19 Nov 1981 08:52:00 GMT', 'vary': 'Accept-Encoding,User-Agent', 'server': 'nginx', 'connection': 'keep-alive', '-content-encoding': 'gzip', 'pragma': 'no-cache', 'cache-control': 'no-store, no-cache, must-revalidate, post-check=0, pre-check=0', 'date': 'Tue, 23 Aug 2011 10:26:46 GMT', 'content-type': 'text/html; charset=ISO-8859-1', 'content-location': 'http://www.boursorama.com/includes/cours/last_transactions.phtml?symbole=1xEURUS'}
虽然这并不能确认数据是被压缩的(毕竟我们现在告诉服务器我们可以处理压缩),但这确实支持了这个理论。
实际的内容在你猜的地方,也就是 content
。简单看一下就能发现它在工作(我就粘贴一小部分):
b'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"\n\t"http://
编辑:是的,这确实会创建一个名为.cache的文件夹;我发现使用文件夹来处理httplib2总是更好,而且你可以在之后随时删除这个文件夹。
我个人是这样写的:
# Python 2.7
import urllib
url = 'http://www.boursorama.com/includes/cours/last_transactions.phtml?symbole=1xEURUS'
sock = urllib.urlopen(url)
content = sock.read()
sock.close()
print content
如果你会说法语,.. 欢迎来到 stackoverflow.com!
更新 1
其实,我现在更喜欢用下面的代码,因为它运行得更快:
# Python 2.7
import httplib
conn = httplib.HTTPConnection(host='www.boursorama.com',timeout=30)
req = '/includes/cours/last_transactions.phtml?symbole=1xEURUS'
try:
conn.request('GET',req)
except:
print 'echec de connexion'
content = conn.getresponse().read()
print content
把代码中的 httplib
改成 http.client
就可以适配到 Python 3 了。
.
我确认,使用这两段代码,我能获取到你感兴趣的数据的源代码:
<td class="L20" width="33%" align="center">11:57:44</td>
<td class="L20" width="33%" align="center">1.4486</td>
<td class="L20" width="33%" align="center">0</td>
</tr>
<tr>
<td width="33%" align="center">11:57:43</td>
<td width="33%" align="center">1.4486</td>
<td width="33%" align="center">0</td>
</tr>
更新 2
在上面的代码中添加以下代码片段,可以帮助你提取我猜测你想要的数据:
for i,line in enumerate(content.splitlines(True)):
print str(i)+' '+repr(line)
print '\n\n'
import re
regx = re.compile('\t\t\t\t\t\t<td class="(?:gras )?L20" width="33%" align="center">(\d\d:\d\d:\d\d)</td>\r\n'
'\t\t\t\t\t\t<td class="(?:gras )?L20" width="33%" align="center">([\d.]+)</td>\r\n'
'\t\t\t\t\t\t<td class="(?:gras )?L20" width="33%" align="center">(\d+)</td>\r\n')
print regx.findall(content)
结果(只显示结尾部分)
.......................................
.......................................
.......................................
.......................................
98 'window.config.graphics = {};\n'
99 'window.config.accordions = {};\n'
100 '\n'
101 "window.addEvent('domready', function(){\n"
102 '});\n'
103 '</script>\n'
104 '<script type="text/javascript">\n'
105 '\t\t\t\tsas_tmstp = Math.round(Math.random()*10000000000);\n'
106 '\t\t\t\tsas_pageid = "177/(includes/cours/last_transactions)"; // Page : boursorama.com/smartad_test\n'
107 '\t\t\t\tvar sas_formatids = "8968";\n'
108 '\t\t\t\tsas_target = "symb=1xEURUS#"; // TargetingArray\n'
109 '\t\t\t\tdocument.write("<scr"+"ipt src=\\"http://ads.boursorama.com/call2/pubjall/" + sas_pageid + "/" + sas_formatids + "/" + sas_tmstp + "/" + escape(sas_target) + "?\\"></scr"+"ipt>");\t\t\t\t\n'
110 '\t\t\t</script><div id="_smart1"><script language="javascript">sas_script(1,8968);</script></div><script type="text/javascript">\r\n'
111 "\twindow.addEvent('domready', function(){\r\n"
112 'sas_move(1,8968);\t});\r\n'
113 '</script>\n'
114 '<script type="text/javascript">\n'
115 'var _gaq = _gaq || [];\n'
116 "_gaq.push(['_setAccount', 'UA-1623710-1']);\n"
117 "_gaq.push(['_setDomainName', 'www.boursorama.com']);\n"
118 "_gaq.push(['_setCustomVar', 1, 'segment', 'WEB-VISITOR']);\n"
119 "_gaq.push(['_setCustomVar', 4, 'version', '18']);\n"
120 "_gaq.push(['_trackPageLoadTime']);\n"
121 "_gaq.push(['_trackPageview']);\n"
122 '(function() {\n'
123 "var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;\n"
124 "ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';\n"
125 "var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);\n"
126 '})();\n'
127 '</script>\n'
128 '</body>\n'
129 '</html>'
[('12:25:36', '1.4478', '0'), ('12:25:33', '1.4478', '0'), ('12:25:31', '1.4478', '0'), ('12:25:30', '1.4478', '0'), ('12:25:30', '1.4478', '0'), ('12:25:29', '1.4478', '0')]
希望你不要打算在外汇市场“玩”交易:这是快速亏钱的最佳方式之一。
更新 3
抱歉!我忘了你在用 Python 3。所以我觉得你必须这样定义正则表达式:
regx = re.compile(b'\t\t\t\t\t......)
也就是说,在字符串前面加上 b,否则你会遇到像在 这个问题 中那样的错误。