注: 最近有一小任務,需要收集水質和水雨信息,找了兩個網站:國家地表水水質自動監測實時數據發布系統和全國水雨情網。由於這兩個網站的數據都是動態加載出來的,所以我用了Selenium來完成我的數據獲取。數據的獲取過程跟人手動獲取過程類似,所以也不會對服務器造成更大負荷。這是我寫的第1個爬蟲,初次接觸,還請各位多多指教。本文的代碼見Selenium獲取動態頁面數據1.ipynb或Selenium獲取動態頁面數據1.py。
1、准備環境
工欲善其事,必先裝好環境,耐心地把下面的環境裝好。
-
安裝Selenium和其一些必要的包:
pip install pandas pip install bs4 pip install selenium
pandas
自不必多說,非常強大的數據分析庫,網上教程非常豐富。bs4
是一個比較方便的html頁面解析的包,詳細的可以自由百度教程,網上有很多,當然也有它的Beautiful Soup官網文檔,這是中文的,比較良心。selenium
能夠用於自動測試我們的網頁,模擬我們的瀏覽器,也很強大,它的說明文檔在此。 -
最后我們需要安裝瀏覽器的支持,如果電腦上已安裝有
Chrome
瀏覽器,則還需下載chromedirver,注意需要安裝與瀏覽器對應的版本,下載完成后,需要將其添加至系統的Path
中。也可以安裝PhantomJS,這是一個無界面的瀏覽器,速度更快一些,體積也不大。同樣,下載好后,需要將其添加至系統的Path
中。 -
另外,關於Python的學習環境,建議安裝一個Jupyter。
2、詳細爬取過程
2.1 分析待爬取網頁
打開我們的國家地表水水質自動監測實時數據發布系統:http://123.127.175.45:8082/如下圖2-1所示,我們可以看到它的數據是動態地在更新,每次只顯示了十多條數據,但是這只是一個假象,其實在我們打開頁面,加載完成后,所有的數據已經加載過來了,只是沒有顯示出來,不信我們可以按F12,<li></li>
標簽下的數據就是加載完成后的數據,共100條數據(有時候也只有99條)。

2.2 利用Selenium提取數據
(1)打開網頁
運行下面代碼,會自動彈出Chrome瀏覽器的窗口;如果用的browser = webdriver.PhantomJS()
,則沒有窗口出來。瀏覽器的窗口出來后,可以看到,它加載出我們的頁面了。
import datetime
import pandas as pd
from bs4 import BeautifulSoup
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
# 打開chrome瀏覽器(需提前安裝好chromedriver)
browser = webdriver.Chrome()
# browser = webdriver.PhantomJS()
print("正在打開網頁...")
browser.get("http://123.127.175.45:8082/")
(2)得到頁面源碼
網頁完成后打開完成后,還需要等待一下它的加載,只有等數據加載完成,我們才能去獲取它的HTML頁面源碼。
print("等待網頁響應...")
# 需要等一下,直到頁面加載完成
wait = WebDriverWait(browser, 10)
wait.until(EC.presence_of_element_located((By.CLASS_NAME, "grid")))
print("正在獲取網頁數據...")
soup = BeautifulSoup(browser.page_source, "lxml")
browser.close()
(3)定位數據
通過CSS選擇器定位到我們的表頭數據和表數據,如下圖2-2和圖2-3所示


# 表頭和表數據
data_head = soup.select(".panel-heading")[0]
grid_data = soup.select(".grid")[0]
# 得到表頭數據
data_colhead = data_head.findAll("td")
data_rows = grid_data.findAll("tr")
# 據表頭生成數據表
water_df = pd.DataFrame(columns=[c.text for c in data_colhead])
我們查看water_df
可以得到如下數據表頭:
斷面名稱 | 測量時間 | pH | 溶解氧 | 氨氮 | 高錳酸鹽指數 | 總有機碳 | 水質類別 | 斷面屬性 | 站點情況 |
---|
(4)提取數據
上面我們從表數據中的tr
標簽獲得所有數據行后,將其所有數據提取出來,添加到我們前面定義好的water_df
中。
print("提取網頁數據中...")
for i, data_row in enumerate(data_rows):
# 以名字為地名和時間標識符,以防止數據重復
water_loc = water_df.iloc[:, 0].values
water_date = water_df.iloc[:, 1].values
row_dat = [r.text for r in data_row]
water_df.loc[i] = row_dat
查看我獲取的數據前5行,如下表
斷面名稱 | 測量時間 | pH | 溶解氧 | 氨氮 | 高錳酸鹽指數 | 總有機碳 | 水質類別 | 斷面屬性 | 站點情況 | |
---|---|---|---|---|---|---|---|---|---|---|
0 | 四川攀枝花龍洞 | 2019-01-22 12:00 | 7.98 | 10.72 | 0.05 | -- | -- | I | 儀器故障 | |
1 | 四川宜賓涼姜溝 | 2019-01-22 12:00 | 7.75 | 10.77 | 0.07 | 2.18 | -- | II | 入長江前 | 正常 |
2 | 雲南紅河州河口 | 2019-01-22 12:00 | 7.41 | 9.09 | 0.21 | 3.4 | -- | II | 中-越出境 | 儀器故障 |
3 | 雲南昆明觀音山 | 2019-01-22 12:00 | 8.51819 | 8.69207 | 0.27 | 7.51 | -- | IV | 湖體 | 正常 |
4 | 雲南昆明西苑隧道 | 2019-01-22 12:02 | 7.9 | 8.7 | 0.24 | 3.5 | -- | II | 湖體 | 正常 |
(5)保存數據
得到數據后,一般要保存我們的數據,pandas
給我們提供了非常方便的方法,可以保存為各種常見格式的數據,下面我們將其保存為.csv
文件格式,由於這里面有中文編碼,所以另外還保存了一個GB18030
編碼格式的文件,這樣直接用excel打開,不會出現亂碼。平時如果處理數據,還里建議用下面的utf-8
編碼的文件。
data_str = datetime.datetime.now().strftime('%Y_%m_%d')
water_df.to_csv("data_water_%s_ch.csv" % (data_str),
index=None, encoding="GB18030")
water_df.to_csv("data_water_%s.csv" % (data_str), index=None)
print("數據提取完成!!")
數據提取完成后,可以看到下面2個文件:data_water_2019_01_22.csv、data_water_2019_01_22_ch.csv,直接用excel
打開第2個文件,可以看到如下圖2-4。

總結
這次,我們主要用selenium
模型瀏覽器得到動態加載的HTML頁面源碼,然后利用BeautifulSoup
解析其中的數據,最后利用Pandas
處理我們數據。
這也是我第1次寫爬蟲,還請各位不吝賜教。此次數據的獲取還比較簡單,下一篇《Python+Selenium爬取動態加載頁面(2)》再來寫一下要點擊按鈕的,稍微復雜一點點。