Python 爬蟲練習:使用selenium+chrome爬取球探網比賽數據(ajax非同步載入)

Python 爬蟲練習:使用selenium+chrome爬取球探網比賽數據(ajax非同步載入)

作為一名python爬蟲入門兼足球關注者,前段時間看到知乎文章用Python模擬2018世界盃奪冠之路,頓時心癢,也想照著作者的思路去爬取一些關於足球比賽的數據信息,順便練練手。無奈文章中作者主要討論數據分析部分,沒有給出從球探網爬取數據的代碼。我只好自己分析網頁,編寫爬蟲代碼,並將爬下的數據存進了csv文件。在這過程中發現遇到了很多以前沒有遇到的問題,也get到了一些新技能,故寫篇文章總結一下並分享給大家。

這裡以爬取球探網上關於2018年俄羅斯世界盃32支參賽國家隊的以往6年的比賽數據為例。

一、根據網頁內容構建爬取思路

首先在球探網世界盃主題頁(2018賽季世界盃(世界盃),賽程積分--球探網)列出了入圍分組賽的32支國家隊分組和積分情況(當然現在還沒有積分數據),點擊任意參賽國家隊(比如埃及)的名稱,可以連接到該國家隊專題頁(埃及,埃及,Egypt -- 球探網),其中包含了此隊從2011年至今所有的比賽成績和相關數據(這就是我們要爬取的內容。)

世界盃32強名稱及分組信息

埃及國家隊比賽數據統計

所以整個爬取思路擬定為:從2018賽季世界盃(世界盃),賽程積分--球探網抓取參賽國家隊名稱及其對應的國家隊數據統計鏈接,並以這些鏈接作為二級網址,抓取對應國家隊近年來的比賽數據統計信息。最後將爬取下來的信息存入到一個csv文件中。

二、網頁html分析

首先在開發者工具中找到我們要在一級網址上抓取的信息位置。我們要爬取的就是位於<table id="ScoreGroupTab"><tbody>中第三個<tr>標籤里的<a>標籤內容及href屬性。

但是在頁面點擊右鍵查看源代碼時,源代碼中並沒有上述部分的代碼。

說明這部分table標籤里的內容是通過ajax動態載入的,不是寫在源代碼里。開發者工具也顯示網頁使用了jquery框架編寫javascript腳本。(國家隊比賽數據統計所在表格也是ajax動態載入的,這裡我就不重複分析了。)

在看看請求網頁時伺服器返回的文件,其中Bomhelper.js中寫有如下信息:

網頁設置了瀏覽器版本檢查,只響應ie, firefox, chrome, opera, safari這5中瀏覽器發送的請求。所以我們在爬蟲中就需要使用selenium庫來模擬瀏覽器發送請求了。又由於限制了瀏覽器版本,所以最常用的無頭瀏覽器plantomJS也不能用了,故這裡我們選中chrome瀏覽器。

三、配置selenium和chrome

既然確定了使用selenium庫+chrome瀏覽器的方法,那麼我們首先要安裝selenium庫和相應的瀏覽器驅動(chromedriver.exe)

  1. selenium庫安裝

這個很簡單,和常用的python包安裝一樣,可以使用:

pip install selenium

2. 下載和安裝chromedriver

打開sites.google.com/a/chro,下載與瀏覽器版本相匹配的chromedriver.exe。例如:我的瀏覽器是 Chrome/60.0.3112.101,而2.33版的chromedriver剛好支持。所以就選用2.33版的。

下載的是一個zip文件,解壓後,裡面有一個chromedriver.exe文件,將該文件移動到電腦chrome瀏覽器的安裝目錄下,我的是:C:Program Files、(x86)GoogleChromeApplication,並把該路徑添加到環境變數的path中。

3. 驗證chromedriver是否可用

打開python,輸入一下內容:

from selenium import webdriverdriver = webdriver.Chrome()

點擊運行後,此時如果一個chrome瀏覽器窗口被成功打開,並且程序沒有報錯,則說明配置成功了。如果瀏覽器在打開後不久程序報錯:[WinError 10054] 遠程主機強迫關閉了一個現有的連接。則有可能是chromedriver.exe的版本低了,換個更新的版本應該就沒事了。

四、爬蟲代碼

鋪墊了這麼多,終於來到主要內容了。不多說了,先上代碼,細節請看注釋。

#導入需要的包from selenium import webdriverimport timeimport traceback#發送url請求def getDriver(url): try: # 注意chromedriver的版本 driver = webdriver.Chrome() driver.get(url) time.sleep(1) return driver except: return #獲取子鏈接列表def getURLlist(url, teamURLlist): driver = getDriver(url) try: #找到包含子鏈接的所有a標籤 a_list = driver.find_elements_by_xpath(//table[@id="ScoreGroupTab"]/tbody/tr/td[2]/a) if a_list: for i in a_list: #teamURLlist用於存放子鏈接 teamURLlist.append(i.get_attribute(href)) driver.close() return teamURLlist else: return [] except: traceback.print_exc() return []#獲取比賽數據def getMatchInfo(teamURLlist, fpath): with open (fpath, w) as f: #注意逗號後面不要有空格 f.write(比賽,時間,主隊,比分,客隊,犯規,黃牌,紅牌,控球率,射門(射正),傳球(成功),傳球成功率,過人次數,評分
) if teamURLlist: for url in teamURLlist: driver = getDriver(url) # 表格中數據數據分了好多頁,雖然所有數據在driver.page_source中都可見。 # 但是,除第一頁以外,其他的數據style屬性都是「display:none",selenium對這些元素是無法直接操作的。 # 我們需要通過JavaScipt 修改display的值 # 編寫一段javascript代碼,讓瀏覽器執行。從而把html中的所有tr標籤的style屬性都設為display=block js = document.querySelectorAll("tr").forEach(function(tr){tr.style.display="block";}) driver.execute_script(js) #接下來,就可以把所有的比賽成績數據都爬下來 infolist = driver.find_elements_by_xpath(//div[@id="Tech_schedule"]/table/tbody/tr) # 第一個tr中包含的是表格的title信息,剔除 for tr in infolist[1:]: td_list = tr.find_elements_by_tag_name(td) matchinfo = [] for td in td_list: # 部分td的style屬性也為「display:none",info 則對應為『』, # 這些td對應的是角球,越位,頭槌,救球,鏟球等信息,不是很重要,就不爬取了。 info = td.text if info: # 去除空字元 matchinfo.append(td.text) matchinfo.append(,) #添加逗號作為分隔符 matchinfo.append(
) #在列表最後加上換行符 #將一條比賽信息寫入到文件中 f.writelines(matchinfo) #每個網頁爬完後,就把打開的瀏覽器關掉,要不最後會開著好多瀏覽器窗口。 driver.close()def main(): #一級網址:32強分組信息 start_url = http://zq.win007.com/cn/CupMatch/75.html #保存文件及路徑 output = rD:/03-CS/web scraping cases/qiutan/worldcup2018.csv startlist = [] resultlist = getURLlist(start_url, startlist) getMatchInfo(resultlist, output) print(
finished
)main()

值得提一下,爬取中涉及到獲取屬性為display:none的標籤內容,這需要編寫一段javascript代碼來修改屬性值,並交個瀏覽器來執行。

最後的爬取結果如下:

五、小結

這個過程主要用到如下知識點:

  1. 使用selenium+chrome的組合來模擬chome瀏覽器發送請求,處理ajax非同步載入數據以及伺服器對發送請求瀏覽器的限制。
  2. 解決了如何爬取屬性為display: none的標籤內容:編寫一段修改屬性的javascript代碼交個webdriver去執行。
  3. 將爬取到的數據寫入csv文件

有一個缺點就是整個爬取過程有點慢,打開瀏覽器載入數據這一消耗了很多時間,未來要想辦法改進一下!

全部內容就這樣啦,歡迎大家批評指正!


推薦閱讀:

case1_sup: 爬取豆瓣電影top250的所有分頁的網頁鏈接,並寫入txt文檔中(自定義函數)
鏈家網租房數據採集(Python)和分析:你的薪水能在上海租到怎麼樣的房子?(一)
對某8同城APP的一次抓包分析-第一彈
基於Python網易雲音樂歌詞爬取
爬蟲-使用Python3爬取360DOC文檔

TAG:python爬蟲 | Selenium | 球探 |