此页面中的信息由 JavaScript 函数提供。当您下载页面时,您会在执行 JavaScript之前urllib
获得该页面。当您在标准浏览器中手动查看页面时,您会看到JavaScript 执行后的 HTML。
要以编程方式获取数据,您需要使用一些可以执行 JavaScript 的工具。有许多可用于 Python 的 3rd 方选项,例如selenium、WebKit或spidermonkey。
这是一个如何使用 selenium (使用phantomjs)和lxml抓取页面的示例:
import contextlib
import selenium.webdriver as webdriver
import lxml.html as LH
link = 'https://www.theice.com/productguide/ProductSpec.shtml;jsessionid=7A651D7E9437F76904BEC5623DBAB055?specId=19118104#expiry'
with contextlib.closing(webdriver.PhantomJS('phantomjs')) as driver:
driver.get(link)
content = driver.page_source
doc = LH.fromstring(content)
tds = doc.xpath(
'//table[@class="default"]//tr[@class="odd" or @class="even"]/td/text()')
print('\n'.join(map(str, zip(*[iter(tds)]*5))))
产量
('Jul13', '2/11/13', '7/26/13', '7/26/13', '7/26/13')
('Aug13', '2/11/13', '8/30/13', '8/30/13', '8/30/13')
('Sep13', '2/11/13', '9/27/13', '9/27/13', '9/27/13')
('Oct13', '2/11/13', '10/25/13', '10/25/13', '10/25/13')
...
('Aug18', '2/11/13', '8/31/18', '8/31/18', '8/31/18')
('Sep18', '2/11/13', '9/28/18', '9/28/18', '9/28/18')
('Oct18', '2/11/13', '10/26/18', '10/26/18', '10/26/18')
('Nov18', '2/11/13', '11/30/18', '11/30/18', '11/30/18')
('Dec18', '2/11/13', '12/28/18', '12/28/18', '12/28/18')
XPath 的解释:
lxml
允许您使用XPath选择标签。XPath
'//table[@class="default"]//tr[@class="odd" or @class="even"]/td/text()'
方法
//table # search recursively for <table>
[@class="default"] # with an attribute class="default"
//tr # and find inside <table> all <tr> tags
[@class="odd" or @class="even"] # that have attribute class="odd" or class="even"
/td # find the <td> tags which are direct children of the <tr> tags
/text() # return the text inside the <td> tag
解释zip(*[iter(tds)]*5)
:
是tds
一个列表。它看起来像
['Jul13', '2/11/13', '7/26/13', '7/26/13', '7/26/13', 'Aug13', '2/11/13', '8/30/13', '8/30/13', '8/30/13',...]
请注意,表格的每一行包含 5 个项目。但我们的名单是平的。因此,要将每 5 个项目组合成一个元组,我们可以使用grouper recipe。zip(*[iter(tds)]*5)
是石斑鱼配方的应用。它需要一个平面列表,例如tds
,并将其转换为每 5 个项目组合在一起的元组列表。
以下是石斑鱼食谱如何运作的解释。请阅读,如果您对此有任何疑问,我将很乐意尝试回答。
要仅获取 table 的第一列,请将 XPath 更改为:
tds = doc.xpath(
'''//table[@class="default"]
//tr[@class="odd" or @class="even"]
/td[1]/text()''')
print(tds)
例如,
import contextlib
import selenium.webdriver as webdriver
import lxml.html as LH
link = 'https://www.theice.com/productguide/ProductSpec.shtml?specId=6753474#expiry'
with contextlib.closing(webdriver.PhantomJS('phantomjs')) as driver:
driver.get(link)
content = driver.page_source
doc = LH.fromstring(content)
tds = doc.xpath(
'''//table[@class="default"]
//tr[@class="odd" or @class="even"]
/td[1]/text()''')
print(tds)
产量
['Jul13', 'Aug13', 'Sep13', 'Oct13', 'Nov13', 'Dec13', 'Jan14', 'Feb14', 'Mar14', 'Apr14', 'May14', 'Jun14', 'Jul14', 'Aug14', 'Sep14', 'Oct14', 'Nov14', 'Dec14', 'Jan15', 'Feb15', 'Mar15', 'Apr15', 'May15', 'Jun15', 'Jul15', 'Aug15', 'Sep15', 'Oct15', 'Nov15', 'Dec15']