目標是抓取全部選項下的表格數據。html
目標網址:https://gkcx.eol.cn/school/searchweb
用開發者工具查看錶格及選項框的構造:正則表達式
下拉框是<ul><li>標籤組成的,用js實現動態切換,靠selenium很難實現定位和模擬點擊。api
解決方法:分析頁面網絡請求流,嘗試抓取服務器返回給客戶端的數據。服務器
選用方法步驟簡述:先打開開發者工具,點擊網絡,此時點擊切換省份,能夠查看到請求流,其中類型爲html的是咱們須要的信息。點擊的過程是客戶端向服務器發送請求的過程,後面的分數就是服務器收到請求後向客戶端返回的數據。網絡
單擊查看它的頭部信息,消息頭裏有個請求網址,咱們對它進行分析app
因此,只須要改變上述幾個參數,重構url,就能夠經過url獲取全部的數據!工具
我嘗試了用requests發送post請求,加上從頁面獲取的請求頭信息,可是服務器應該是識別出了爬蟲程序,因此訪問沒有成功,返回錯誤碼503,最終仍是決定用selenium,畢竟Selenium模擬人工很難被識別出來。post
雙擊點開開發者工具中html類型的請求,頁面中的數據就是返回的Json數據,下一步就是抓取並解析。url
參考代碼:
import re from selenium import webdriver f = open("HunanTest.txt", 'r', encoding="utf-8") # 打開抓取的url文件 univs = [] for i in f: # 用正則表達式匹配數字(學校id)存在univs列表中 univid = re.search(r'\d+', i).group() univs.append(univid) browser = webdriver.Firefox() info = [] vacant = [] # 四重for循環用於構建新的Url for univ in univs: for provId in open("prov.txt", 'r', encoding='utf-8'): # 各省份的id for typeId in range(1, 3): # 類別,理科是1,文科是2 for year in range(2016, 2019): # 年份,2016-2018 url = "https://api.eol.cn/gkcx/api/?access_token=&local_province_id=" + str( provId) + "&local_type_id=" \ + str(typeId) + "&school_id=" + str(univ) + "&signsafe=&uri=apidata/api/gk/score/province&year=" \ + str(year) browser.get(url) html = browser.page_source # 正則表達式匹配相關信息
length = len(re.findall(r'"name":(.+?),', html))
name = re.findall(r'"name":"(.+?)",', html)
prov = re.findall(r'"local_province_name":"(.+?)",', html)
typeNum = re.findall(r'"local_type_name":"(.+?)",', html)
average = re.findall(r'"average":(.+?),', html)
min = re.findall(r'"min":(.+?),', html)
max = re.findall(r'"max":(.+?),', html)
proscore = re.findall(r'"proscore":(.+?),', html)
batch = re.findall(r'"local_batch_name":"(.+?)",', html)
# 構建數據字典
for i in range(length):
data = {"學校名稱": name[i],
"學校ID": univ,
"省份": prov[i],
"年份": year,
"類別": typeNum[i],
"平均分": average[i],
"最高分": max[i],
"最低分": min[i],
"省份批次線": proscore[i],
"錄取批次": batch[i]
}
info.append(data)
browser.close()
結果: