利用python中selenium库爬取陕西省2022年各个县的AQI数据汇总到一个excel表格
selenium库的安装与使用
selenium是一个网页自动化测试工具,使用它可以实现网页的下拉、点击等基本操作,当然也可以用来进行数据的一些抓取,并且selenium简单易学,非常适合像我这种第一次接触爬虫的新手。
selenium安装
pip install selenium
selenium需要借助浏览器来实现爬取数据,支持的浏览器也是比较多的,Edge、chrome等,需要下载其对应的驱动来可以进行使用。具体对应可以参考公子清羽的博客
https://blog.csdn.net/weixin_42550871/article/details/108831177
selenium使用
例如:
from selenium import webdriver
driver = webdriver.Chrome("chromedriver.exe")
driver.get("需要爬取的网站")
python爬取单日AQI数据
首先是我们需要导入的python库如下:
from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By
from time import sleep
import datetime
from selenium.webdriver.common.keys import Keys
import pandas as pd
打开需要爬取页面
driver = webdriver.Chrome("D:\下载\chromedriver_win32\chromedriver.exe")
driver.get("http://113.140.66.226:8024/sxAQIWeb/PageDistrict.aspx?cityCode=NjEwOTAw")
driver.implicitly_wait(10)
打开之后页面如下:
打开之后会发现,这个页面是个动态页面,就是说我们点击例如县城空气质量,还是这个页面,但是下面的内容会发生变化。所以我们需要利用selenium一步步点击到我们所需要的那个界面,才可以爬取我们所需要的数据。
模拟鼠标点击到指定界面
#找到县级城市
country = driver.find_element_by_css_selector("#aspnetForm > div.box > div.top > div > ul > li:nth-child(4) > a")
ActionChains(driver).move_to_element(country).perform()#chengshi这个只是为了后面保存文件夹方便
chengshi = driver.find_element_by_css_selector("#aspnetForm > div.box > div.top > div > ul > li:nth-child(4) > ul > li:nth-child(1) > a").text
#点击到对应城市,这里是西安市
country = driver.find_element_by_css_selector("#aspnetForm > div.box > div.top > div > ul > li:nth-child(4) > ul > li:nth-child(1) > a").click()#找到日报数据点击
day = driver.find_element_by_css_selector("#span1").click()
日期选择
从网页上可以看出来这个日期界面是比较麻烦的,需要点击选择,我们可以绕开这个,直接在查询框里面输入日期进行查询,这里我借助datetime库来生成日期进行输入,具体代码如下:
d = datetime.date(2022,2,16)
a = d.strftime("%Y-%m-%d")#点击日期那个框框
date = driver.find_element_by_css_selector("#ctl00_ContentPlaceHolder1_d12")
date.send_keys(Keys.CONTROL,'a')
date.send_keys(a)#等待两秒
sleep(2)#点击查询
look = driver.find_element(By.XPATH,"/html/body/div[1]/form/div[3]/div[6]/div/input[2]").click()#等待10秒,等待原因是网页刷新比较慢
sleep(10)
爬取数据并保存到表格中
datalist =[]
table = driver.find_elements_by_css_selector('#ctl00_ContentPlaceHolder1_GridView1 > tbody > tr')
rows =[i for i in table if i.text]# 所有内容
sleep(2)for row in rows:# 逐行获取
sleep(2)
datalist.append([i.text for i in row.find_elements_by_css_selector('tr > td')if i.text])
headers =["日期","城 市","AQI","空气质量级别","级别","首要污染物","排名"]
df = pd.DataFrame(datalist, columns=headers)
df.to_csv(f"D:\桌面\AQI/{cheengshi[0:3]}"+"/"+f"{d}AQI数据.csv",index=False)
最终保存的结果如下:
异常处理
由于网页会遇到各种问题,比如日期输入并点击查询之后,这个页面要很久才能刷新出来,甚至有的天数还没有数据,导致出现报错,所以我在这里进行了一个异常处理,防止在进行循环一年的数据时出现报错代码就停止的现象。
#异常检测的库from selenium.common.exceptions import StaleElementReferenceException
#在日期查询那里加入异常检测就不会出现问题了,但是爬取错误的数据要重新爬取
attempts =0while attempts <3:try:
date = driver.find_element_by_css_selector("#ctl00_ContentPlaceHolder1_d12")
date.send_keys(Keys.CONTROL,'a')
date.send_keys(a)
sleep(2)
look = driver.find_element(By.XPATH,"/html/body/div[1]/form/div[3]/div[6]/div/input[2]").click()
sleep(10)
datalist =[]
table = driver.find_elements_by_css_selector('#ctl00_ContentPlaceHolder1_GridView1 > tbody > tr')
rows =[i for i in table if i.text]# 所有内容
sleep(2)for row in rows:# 逐行获取
sleep(2)
datalist.append([i.text for i in row.find_elements_by_css_selector('tr > td')if i.text])breakexcept StaleElementReferenceException:
date = driver.find_element_by_css_selector("#ctl00_ContentPlaceHolder1_d12")
date.send_keys(Keys.CONTROL,'a')
date.send_keys(a)
sleep(2)
look = driver.find_element(By.XPATH,"/html/body/div[1]/form/div[3]/div[6]/div/input[2]").click()
sleep(10)
datalist =[]
table = driver.find_elements_by_css_selector('#ctl00_ContentPlaceHolder1_GridView1 > tbody > tr')
rows =[i for i in table if i.text]# 所有内容
sleep(2)for row in rows:# 逐行获取
sleep(2)
datalist.append([i.text for i in row.find_elements_by_css_selector('tr > td')if i.text])
attempts +=1
利用selenium爬取一整年的AQI数据
上面是单日数据的爬取,下面我们只需要加入一个循环就可以实现一整年的数据爬取,我这里使用的是while循环。
一整年数据爬取整个代码
以西安市县级2022年AQI数据爬取为例子。
from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By
from time import sleep
import datetime
from selenium.webdriver.common.keys import Keys
import pandas as pd
from selenium.common.exceptions import StaleElementReferenceException
driver = webdriver.Chrome("D:\下载\chromedriver_win32\chromedriver.exe")
driver.get("http://113.140.66.226:8024/sxAQIWeb/PageDistrict.aspx?cityCode=NjEwOTAw")
driver.implicitly_wait(10)#找到县级城市
country = driver.find_element_by_css_selector("#aspnetForm > div.box > div.top > div > ul > li:nth-child(4) > a")
ActionChains(driver).move_to_element(country).perform()#找到西安市点击
cheengshi = driver.find_element_by_css_selector("#aspnetForm > div.box > div.top > div > ul > li:nth-child(4) > ul > li:nth-child(1) > a").text
country = driver.find_element_by_css_selector("#aspnetForm > div.box > div.top > div > ul > li:nth-child(4) > ul > li:nth-child(1) > a").click()# ActionChains(driver).move_to_element(xian).click().perform()#找到日报数据点击
day = driver.find_element_by_css_selector("#span1").click()# 开始时间以及结束时间 这里需要修改时间,由于网页的原因会出错,改时间重新跑就好
begin = datetime.date(2022,1,1)
end = datetime.date(2022,12,31)
d = begin
delta = datetime.timedelta(days=1)while d <= end:#日期转为字符串,并订正格式
a = d.strftime("%Y-%m-%d")
date = driver.find_element_by_css_selector("#ctl00_ContentPlaceHolder1_d12")
date.send_keys(Keys.CONTROL,'a')
date.send_keys(a)
sleep(2)
attempts =0while attempts <3:try:
look = driver.find_element(By.XPATH,"/html/body/div[1]/form/div[3]/div[6]/div/input[2]").click()
sleep(15)
datalist =[]
table = driver.find_elements_by_css_selector('#ctl00_ContentPlaceHolder1_GridView1 > tbody > tr')
rows =[i for i in table if i.text]# 所有内容
sleep(2)for row in rows:# 逐行获取
sleep(2)
datalist.append([i.text for i in row.find_elements_by_css_selector('tr > td')if i.text])breakexcept StaleElementReferenceException:# date = driver.find_element_by_css_selector("#ctl00_ContentPlaceHolder1_d12")# date.send_keys(Keys.CONTROL, 'a')# date.send_keys(a)# sleep(2)
look = driver.find_element(By.XPATH,"/html/body/div[1]/form/div[3]/div[6]/div/input[2]").click()
sleep(15)
datalist =[]
table = driver.find_elements_by_css_selector('#ctl00_ContentPlaceHolder1_GridView1 > tbody > tr')
rows =[i for i in table if i.text]# 所有内容
sleep(2)for row in rows:# 逐行获取
sleep(2)
datalist.append([i.text for i in row.find_elements_by_css_selector('tr > td')if i.text])
attempts +=1
headers =["日期","城 市","AQI","空气质量级别","级别","首要污染物","排名"]
df = pd.DataFrame(datalist, columns=headers)
df.to_csv(f"D:\桌面\AQI/{cheengshi[0:3]}"+"/"+f"{d}AQI数据.csv",index=False)
d += delta
driver.quit()
这样我们就实现了西安市县级AQI数据的爬取,之后就需要我们汇总到一个表格里面。
数据汇总到一个csv表格
这个比较简单,只需要借助os库和pandas库来实现一个简单的批处理即可。
话不多说,直接上代码:
import os
import pandas as pd
filedir ="D:\桌面\AQI\咸阳市\\"
file_namelist = os.listdir(filedir)
path2 ="D:\桌面\AQI\咸阳市\整理"ifnot os.path.exists(path2):
os.mkdir(path2)
df = pd.DataFrame()for filename in file_namelist:if filename.endswith(".csv"):
filepath = filedir + filename
data = pd.read_csv(filepath)# 读取csv数据
data = data[1:25]
df = df.append(data)print({filename},"is ok!!!")
df.to_csv(path2 +"/"+"咸阳市.csv",
index=False)
总结
第一次尝试写爬虫的代码,也尝试过用request加bs4来写,但是发现对于这种动态网页,我需要的花费很大时间去学习才能实现爬取,selenium库使用比较简单,非常容易上手,我当时也是看了三天的课程基本上就可以把代码写成型了,主要花费时间还是对HTML语言的了解。但是selenium库的缺点也很明显,它要等页面全部加载出来之后才会进行下一步,这也是它的爬取速度没有那么快的原因。
最后,希望能对一些初次接触爬虫的同学带来帮助,也希望能有大佬能多提出写意见,也特别感谢在CSDN上面分享经验的各位博主。
版权归原作者 一月一博客 所有, 如有侵权,请联系我们删除。