想爬取https://www.aqistudy.cn/空气质量网上的河北省空气历史数据,
之前使用python写过基于scrapy的爬虫,想故技重施发现爬取不到想要的数据,仔细看过网页源代码后发现表格中的数据是动态加载的,使用开发者工具想要查看传输的数据结果
发现数据被加密了,百度过解决办法后决定选择selenium实现动态的数据爬取
一、什么是selenium?
selenium 是一个用于Web应用程序测试的工具。Selenium测试直接运行在浏览器中,就像真正的用户在操作一样,selenium用于爬虫,主要是用来解决javascript渲染的问题
二、selenium基本实现
1.声明浏览器对象
browser=webdriver.Chrome(\'C:\ProgramFiles(x86)\Google\Chrome\Application\chromedriver.exe\')
在这里需要安装相应的webdriver需要注意两点
(1)是下载时注意浏览器版本和webdriver的版本号对应
(2)网上关于webdriver安装都要求配置环境变量,本人经实验发现程序还是会报找不到path,因此我直接将webdriver放在chrome路径下,而后在声明时直接贴上路径
2.访问页面
browser.get("http://www.baidu.com")
在这里我观察了空气质量网的url,发现格式为
https://www.aqistudy.cn/historydata/daydata.php?city=城市名&month=年月
3.查找元素与selenium操作
这里selenium提供了很多函数让我们进行操作,其中很关键的两个就是通过xpath查找元素find_elements_by_xpath以及JavaScript的执行命令execute_script,而我就很厉害了,pands中有一个函数叫做read_html
pd.read_html(browser.page_source, header=0)[0]
通过它的实现我直接获得页面中表格的dataframe格式,怎么处理当然就是任我揉捏了
3.关闭browser
browser.close()
在执行过程中,出现了爬取结果为空的情况,判断原因为页面未加载完成,设置time.sleep(1)发现并不能解决问题,在使用八爪鱼采集器采集过程中,发现八爪鱼对未采集到的界面的处理是重复采集,因此在采集字段后接了一条判断语句,若结果为空,则重复采集
详见代码
1 #coding=utf-8 2 from selenium import webdriver 3 import cx_Oracle #引用模块cx_Oracle 4 import pandas as pd 5 import os 6 #若数据为空,则重复采集 7 def paqu(uurl): 8 browser.get(uurl) 9 dfs = pd.read_html(browser.page_source, header=0)[0] 10 if len(dfs)>1: 11 return dfs 12 else: 13 return paqu(uurl) 14 os.environ[\'NLS_LANG\'] = \'SIMPLIFIED CHINESE_CHINA.UTF8\' #防止oracle数据乱码 15 conn=cx_Oracle.connect(\'Xho\', \'sys\', \'localhost:1521/orcl\') #连接数据库 16 cursor=conn.cursor()#获取cursor游标 17 18 #声明浏览器对象 19 browser = webdriver.Chrome(\'C:\Program Files (x86)\Google\Chrome\Application\chromedriver.exe\') 20 base_url=\'https://www.aqistudy.cn/historydata/daydata.php?city=\' 21 city=[\'石家庄\',\'保定\',\'唐山\',\'邯郸\',\'邢台\',\'沧州\',\'衡水\',\'廊坊\',\'承德\',\'秦皇岛\',\'张家口\'] 22 23 year=[201301,201401,201501,201601,201701,201801] 24 list_data=[] 25 list_row=[] 26 for p in range(len(city)): 27 for i in year: 28 for j in range(12): 29 num = i + j 30 if num > 201311 and num < 201809: 31 uurl=base_url+city[p]+\'&month=\'+str(num) 32 dfs=paqu(uurl) 33 #time.sleep(1) 34 dfs[\'city\']=city[p] 35 for s in range(0, len(dfs)): 36 date = dfs.iloc[s, 0] 37 list_row.append(date) 38 aqi = dfs.iloc[s, 1] 39 list_row.append(aqi) 40 grade = dfs.iloc[s, 2] 41 list_row.append(grade) 42 pm25 = dfs.iloc[s, 3] 43 list_row.append(pm25) 44 pm10 = dfs.iloc[s, 4] 45 list_row.append(pm10) 46 so2 = dfs.iloc[s, 5] 47 list_row.append(so2) 48 co = dfs.iloc[s, 6] 49 list_row.append(co) 50 no2 = dfs.iloc[s, 7] 51 list_row.append(no2) 52 o3 = dfs.iloc[s, 8] 53 list_row.append(o3) 54 chsh=dfs.iloc[s,9] 55 list_row.append(chsh) 56 57 list_data.append(list_row) 58 list_row=[] 59 for n in range(len(list_data)): 60 sql = \'insert into AIR_ZL (A_DATE,AQI,GRADE,PM25,PM10,SO2,CO,NO2,O3_8H,CITY) VALUES (:A_DATE,:AQI,:GRADE,:PM25,:PM10,:SO2,:CO,:NO2,:O3_8H,:CITY)\' 61 x = cursor.execute(sql, (list_data[n][0], float(list_data[n][1]), list_data[n][2],float(list_data[n][3]),float(list_data[n][4]),float(list_data[n][5]),float(list_data[n][6]),float(list_data[n][7]),float(list_data[n][8]),list_data[n][9])) 62 conn.commit(); 63 list_data=[] 64 cursor.close() # 关闭cursor 65 conn.close() # 关闭连接 66 browser.close()