我们获取数据的网站为 芝商所官网(www.cmegroup.com)。我们获取wti和布伦特的收盘数据。
收盘数据是这样的。
解题思路:
首先先打开页面链接,获取到 交易日期,然后读取下方table内的各合约月份的交易收盘数据。
这部分没有什么坑,就是selenium语法不熟悉。边写边百度。
首先是导入包
from selenium import webdriverfrom selenium.webdriver.common.by import Byimport time
这个time包 是因为载入页面需要时间,需要延时等待。
time.sleep(5)
这样的。
我没有用 chrome,我用的是firefox。因为我对chrome没有好感,我是个产品经理,用axure画原型的时候总是需要我安装插件,因为墙的原因,又总是很难安装上。更过分的是,selenium的chrome驱动,也是无法下载的。
既然写法都一样,为什么不用firefox。
下载安装驱动,然后开始copy代码。
web = webdriver.Firefox(executable_path = 'D:\\Python\\Python39\\geckodriver.exe')web.implicitly_wait(5)# 调用WebDriver 对象的get方法 可以让浏览器打开指定网址web.get('http://localhost/test.html')
这就是打开网址的用法。
1、加载驱动。
2、implicitly_wait是隐式等待,还有个显示等待。网上有介绍,然鹅我没有看懂。但是不影响我写代码。
3、打开网址
因为网络波动的原因,芝商所的网站有时能打开,有时打不开。
所以加了个异常捕获
try: web.get('https://www.cmegroup.com/trading/energy/crude-oil/brent-crude-oil-last-day_quotes_settlements_futures.html#prodType=EUR')except: print('访问超时,稍后再试吧') exit()
网页上提供过去5个工作日(美国时间)的收盘数据,因此我们在获取完了一天的之后,还要再切换日期获取过去的日期的,以方便做容错。(有几天没获取的时候,可以利用这个来补齐。)
这样就需要加一个循环和点击。我上一下完整的代码吧。
tbody_str = ''for i in range(1,6): xpath = "//select[@id='cmeTradeDate']/option[{0}]".format(i) print("i=" + str(i)) if(i>1): try: time.sleep(10) web.find_element_by_xpath(xpath).click() except: print("程序挂了,进了except 选择那个div的关闭按钮点击关掉就行了") web.find_element_by_css_selector("[class='at-cv-close at-cv-close-end']").click() print('删除掉 那个挡住的div') time.sleep(1) web.find_element_by_xpath(xpath).click() print("i=" + str(i) + '点击了option') date_str = web.find_element_by_xpath(xpath).get_attribute('value') print("数据时间:"+date_str) tbody_new = web.find_element_by_xpath("//table[@id='settlementsFuturesProductTable']/tbody").get_attribute('innerHTML') while tbody_new == tbody_str: print("获取最新的tbody") time.sleep(3) tbody_new = web.find_element_by_xpath("//table[@id='settlementsFuturesProductTable']/tbody").get_attribute('innerHTML') tbody_str = tbody_new #获取下面表格的数据 tbody = web.find_elements_by_xpath("//table[@id='settlementsFuturesProductTable']/tbody/tr") ##.get_attribute('innerHTML') table_data = [] for tr in tbody: month = tr.find_element(By.TAG_NAME, "th").get_attribute('textContent') tr_data= [] tr_data.append(month) tds = tr.find_elements(By.TAG_NAME, "td") for td in tds: bb = td.get_attribute('textContent') tr_data.append(bb) table_data.append(tr_data) for tr_data in table_data: month = tr_data[0] open = tr_data[1] high = tr_data[2] low = tr_data[3] last = tr_data[4] change = tr_data[5] settle = tr_data[6] volume = tr_data[7] interest = tr_data[8] # print('month:' + month) # print('open:' + open) # print('high:' + high) # print('low:' + low) # print('last:' + last) # print('change:' + change) # print('settle:' + settle) # print('volume:' + volume) # print('interest:' + interest) print(tr_data) print('-------------------') print("数据时间:" + date_str + "的数据执行完毕")
网页的左下角有个广告,再切换时容易出现问题,就是我要点击的click的对象被那个广告的div给挡住了,导致无法点击。我对click事件做了个异常捕获,在异常处理中,定位到那个广告的 关闭按钮,先关闭广告再点击。
同时,切换时数据加载需要时间,因为只填充数据,所以你并不知道数据是否填充上了,要是取错了数据,就没有任何意义了,因此我在取数之前,做了个数据内容比对,内容要跟上次获取的数据不一样才是获取成功了,否则要进行循环等待。
其他的没什么难的了。后面我要想在服务器上做定时任务抓取,需要在后台静默执行,不要弹出firefox的浏览器页面。
需要进行如下设置:
option = webdriver.FirefoxOptions()option.add_argument('--headless')#option.add_argument('--no-sandbox')#option.add_argument('--start-maximized')web = webdriver.Firefox(executable_path = 'D:\\Python\\Python39\\geckodriver.exe',options=option)
没有弄懂这几个参数的意思,总之能用就好。
这样就后台执行了。
下面就是数据持久化了,此处略过10000行。
后来发现芝商所的数据有接口直接返回json数据,直接请求就可以。所有这些都白费,就当是联系如何使用 selenium了。