如何用爬蟲下載武漢市環保局空氣污染數據?

畢業季,需要用到這方面的數據,單獨一頁一頁的複製了一段時間的數據,發現很是耗時,想從武漢市環保局下載這將近三年的歷史數據。選擇日期後,頁面出現一個相應的數據表格,需要將這個表格全部保存。頁面如下:

跪謝各位!


這個問題不算麻煩,中午休息的時間簡單調試了一下。我把步驟、代碼和一個月的數據 demo 貼上,希望題主有一定的基礎,然後能自己把需要的所有數據跑出來。
最後給出的完整代碼修改起止日期以後應該是能直接使用的。我中間有短暫地無法訪問這個網站,所以在運行的時候最好不要一次跑太長的日期跨度,最好是 3~6 個月的數據這樣跑吧。

我們由內向外地來看待這個問題,想要獲取三年的歷史數據,自然要從獲取某一天入手,然後再批量化地獲取很多天的數據。獲取到數據以後為了方便後續處理,我們可以將其保存到一個 excel 的表格裡面。
所以我們要做的就是請求頁面-解析頁面-保存數據,相應用到的庫分別是:
Python3
requests
beautifulsoup
xlwt
(上面三個庫在裝完 Python3 後都可以直接用 pip install 命令安裝)

網頁不複雜,也不需要模擬登陸,下面簡單分析一下。

這個頁面里沒有找到我們需要的數據,觀察以後發現中間的表格部分寫在一個&標籤里,打開這個鏈接,跳轉到表格頁面。
隨便修改一個日期,觀察瀏覽器的請求情況。如圖。

可以看到,瀏覽器用一個 post 方法,提交的數據是日期和頁數。這個過程就很簡單了。

import requests
def get_html():
global h
s = requests.session()
url = "http://www.whepb.gov.cn/airSubair_water_lake_infoView/v_listhistroy.jspx?type=0"
headers = {
"User-Agent":"Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:44.0) Gecko/20100101 Firefox/44.0",
"Referer":"http://www.whepb.gov.cn/airSubair_water_lake_infoView/v_listhistroy.jspx?type=0",
"Host":"www.whepb.gov.cn",
"Cookie":" JSESSIONID=C7DC84CE4FF191ADB582B6C8D39F0749.tomcat; JSESSIONID=C7DC84CE4FF191ADB582B6C8D39F0749.tomcat; clientlanguage=zh_CN",
"Connection":"keep-alive",
"Accept-Language":"zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3",
"DontTrackMeHere":"gzip, deflate",
"Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
}
dt = {"cdateEnd":"2014-07-03","pageNo1":"1","pageNo2":""}
r = s.post(url, data=dt, headers=headers)
h = r.content.decode("utf-8")

就不再一一解釋和截圖了。
獲取到頁面源碼以後我們要對頁面進行解析,抽取出中間需要的表格部分。
再將其保存到 Excel 裡面。

import requests
import xlwt
from bs4 import BeautifulSoup

def get_html():
global h
s = requests.session()
url = "http://www.whepb.gov.cn/airSubair_water_lake_infoView/v_listhistroy.jspx?type=0"
headers = {
"User-Agent":"Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:44.0) Gecko/20100101 Firefox/44.0",
"Referer":"http://www.whepb.gov.cn/airSubair_water_lake_infoView/v_listhistroy.jspx?type=0",
"Host":"www.whepb.gov.cn",
"Cookie":" JSESSIONID=C7DC84CE4FF191ADB582B6C8D39F0749.tomcat; JSESSIONID=C7DC84CE4FF191ADB582B6C8D39F0749.tomcat; clientlanguage=zh_CN",
"Connection":"keep-alive",
"Accept-Language":"zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3",
"DontTrackMeHere":"gzip, deflate",
"Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
}

r = s.post(url, data=dt, headers=headers)
h = r.content.decode("utf-8")

def get_excel():
book = xlwt.Workbook(encoding = "utf-8",style_compression=0)
sheet = book.add_sheet("data",cell_overwrite_ok = True)

global dt
j = 0

dt = {"cdateEnd":"2014-07-08","pageNo1":"1","pageNo2":""}
get_html()
soup = BeautifulSoup(h)
for tabb in soup.find_all("tr"):
i=0;
for tdd in tabb.find_all("td"):
#print (tdd.get_text()+",",)
sheet.write(j,i,tdd.get_text())
i = i+1
j=j+1
book.save(r"result.xls")
get_excel()

結果:

這樣就可以完整獲取某一天的數據了,然後我們需要獲取更多的數據,只需要修改 post 數據時的 date 就可以了。
我們將指定日期間的日期生成一個列表。我用的是這裡的方法python如何生成一個日期列表? - Python。得到日期列表以後在上面的代碼中再加一層循環就好。
最終代碼:

import requests
import xlwt
from bs4 import BeautifulSoup
import datetime

def datelist(start, end):
start_date = datetime.date(*start)
end_date = datetime.date(*end)
result = []
curr_date = start_date
while curr_date != end_date:
result.append("%04d-%02d-%02d" % (curr_date.year, curr_date.month, curr_date.day))
curr_date += datetime.timedelta(1)
result.append("%04d-%02d-%02d" % (curr_date.year, curr_date.month, curr_date.day))
return result

def get_html():
global h
s = requests.session()
url = "http://www.whepb.gov.cn/airSubair_water_lake_infoView/v_listhistroy.jspx?type=0"
headers = {
"User-Agent":"Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:44.0) Gecko/20100101 Firefox/44.0",
"Referer":"http://www.whepb.gov.cn/airSubair_water_lake_infoView/v_listhistroy.jspx?type=0",
"Host":"www.whepb.gov.cn",
"Cookie":" JSESSIONID=C7DC84CE4FF191ADB582B6C8D39F0749.tomcat; JSESSIONID=C7DC84CE4FF191ADB582B6C8D39F0749.tomcat; clientlanguage=zh_CN",
"Connection":"keep-alive",
"Accept-Language":"zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3",
"DontTrackMeHere":"gzip, deflate",
"Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
}

r = s.post(url, data=dt, headers=headers)
h = r.content.decode("utf-8")

def get_excel():
book = xlwt.Workbook(encoding = "utf-8",style_compression=0)
sheet = book.add_sheet("data",cell_overwrite_ok = True)

global dt
j = 0
#修改下面的 datelist() 修改起止時間
for each in datelist((2014, 1, 1), (2014, 1, 31)):
dt = {"cdateEnd":each,"pageNo1":"1","pageNo2":""}
get_html()
soup = BeautifulSoup(h)
#j = 0
for tabb in soup.find_all("tr"):
i=0;
for tdd in tabb.find_all("td"):
#print (tdd.get_text()+",",)
sheet.write(j,i,tdd.get_text())
i = i+1
j=j+1
book.save(r"result".xls")#修改這裡更改保存的文件名
get_excel()

使用的時候直接修改起止日期就好了。
http://pan.baidu.com/s/1jH3BIFc 2014-01 和 2014-06 的數據。
wuhan_weather/weather.py at master · loveQt/wuhan_weather · GitHub

over


對於這種簡單的數據抓取需求,有很多可視化的數據抓取工具,動動滑鼠就行,入門幾分鐘。自行搜索八爪魚、火車頭採集等。


推薦閱讀:

TAG:數據分析 | 爬蟲(計算機網路) | 行業研究 | 空氣污染 | 行業數據 |