網(wǎng)站簡(jiǎn)介
QS世界大學(xué)排名 是由教育組織Quacquarelli Symonds(簡(jiǎn)稱QS)每年發(fā)布的全球各地大學(xué)排名情況的系列排名之一。該排名是根據(jù)大學(xué)的學(xué)術(shù)水平、研究質(zhì)量、國(guó)際化程度、教師素質(zhì)、學(xué)生滿意度等多項(xiàng)指標(biāo)綜合評(píng)估得出的,參考數(shù)據(jù)來(lái)源廣泛,包括了全球各大權(quán)威研究機(jī)構(gòu)的數(shù)據(jù)統(tǒng)計(jì)和排名情況。
QS世界大學(xué)排名分為多個(gè)子排名,包括綜合排名、學(xué)科排名、地區(qū)排名等。其中,綜合排名按照學(xué)術(shù)水平、教學(xué)質(zhì)量、研究產(chǎn)出、國(guó)際化程度等指標(biāo)對(duì)全球大學(xué)進(jìn)行排名,參考數(shù)據(jù)來(lái)源為全球各大權(quán)威研究機(jī)構(gòu)的數(shù)據(jù)統(tǒng)計(jì)和排名情況。學(xué)科排名按照學(xué)科領(lǐng)域?qū)θ虼髮W(xué)進(jìn)行排名,包括了商科、工程、生命科學(xué)、醫(yī)學(xué)、法律等多個(gè)領(lǐng)域。地區(qū)排名則按照地理位置和學(xué)術(shù)水平對(duì)全球大學(xué)進(jìn)行排名,涵蓋了全球多個(gè)地區(qū)。
除了以上的排名系列,QS還發(fā)布了一些其他相關(guān)的大學(xué)排名,如根據(jù)畢業(yè)生就業(yè)率、教師滿意度等指標(biāo)的QS世界大學(xué)畢業(yè)生就業(yè)排名和根據(jù)國(guó)際留學(xué)生比例、教師國(guó)際化程度等指標(biāo)的QS世界大學(xué)國(guó)際化排名等。
總的來(lái)說(shuō),QS世界大學(xué)排名是全球最具權(quán)威性和影響力的大學(xué)排名之一,被認(rèn)為是評(píng)估全球大學(xué)綜合實(shí)力和學(xué)術(shù)水平的重要指標(biāo)之一。
爬蟲方法概述
使用工具
爬蟲相關(guān):selenium,requests,lxml,xpath
數(shù)據(jù)處理:pandas
IDE:vscode + jupyter
爬蟲概述
本案例共分為三個(gè)部分:
-
第一部分:爬取排名指標(biāo)下面的,排名、大學(xué)名稱、大學(xué)詳情鏈接地址、綜合得分、學(xué)術(shù)聲譽(yù)、雇主聲譽(yù)、每位教員引用率、師生比、國(guó)際學(xué)生占比、國(guó)際教師占比,中的前1000名的數(shù)據(jù)。使用selenium來(lái)模擬瀏覽器爬取。
-
第二部分:爬取大學(xué)詳情中的數(shù)據(jù),高校性質(zhì)、研究成果、學(xué)生人數(shù)、教師人數(shù)、國(guó)際學(xué)生人數(shù)。由于這些網(wǎng)址都是獨(dú)立的,所以直接使用requests+xpath來(lái)獲取數(shù)據(jù)。
-
第三部分:數(shù)據(jù)合并,把前兩部分獲取的數(shù)據(jù),使用pandas來(lái)把數(shù)據(jù)合并到一起。
話不多說(shuō),開始干活。
第一部分
導(dǎo)入需要用到的python包
導(dǎo)入需要用到的python包,第一部分主要使用selenium 來(lái)獲取數(shù)據(jù),所以導(dǎo)入selenium包中使用到的部分,控制爬蟲時(shí)間我使用的是time模塊,用起來(lái)比較簡(jiǎn)單,數(shù)據(jù)保存使用pandas。
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
import time
import pandas as pd
設(shè)置selenium控制瀏覽器打開網(wǎng)頁(yè)
使用selenium打開操作打開瀏覽器網(wǎng)址。
網(wǎng)址:https://www.qschina.cn/university-rankings/world-university-rankings/2023
設(shè)置完成后就可以使用selenium來(lái)打開瀏覽器和網(wǎng)址了。
# 設(shè)置瀏覽器內(nèi)核路徑
servic = Service(executable_path =r'****/chromedriver.exe')
driver = webdriver.Chrome(service=servic)
# 獲取網(wǎng)頁(yè)
driver.get("https://www.qschina.cn/university-rankings/world-university-rankings/2023")
# 通過(guò)設(shè)置sleep時(shí)間來(lái)控制爬蟲的速度,根據(jù)情況,也可不用。
time.sleep(1)
效果如下:
控制鼠標(biāo)操作
完成上一步后,就可以打開網(wǎng)頁(yè)了,但是網(wǎng)頁(yè)默認(rèn)顯示的是排名榜單,里面只有學(xué)校的名稱和排名,如下圖。
但是我們要獲取的數(shù)據(jù)實(shí)在排名指標(biāo)下面。如下圖。
需要通過(guò)鼠標(biāo)點(diǎn)擊排名指標(biāo),才能顯示出需要爬取的數(shù)據(jù)信息。
所以需要我們通過(guò)selenium來(lái)控制鼠標(biāo)實(shí)現(xiàn)點(diǎn)擊的動(dòng)作。需要先定位鼠標(biāo)點(diǎn)擊的節(jié)點(diǎn)(xpath定位),然后通過(guò)selenium實(shí)現(xiàn)點(diǎn)擊。
定位節(jié)點(diǎn)
打開網(wǎng)址:https://www.qschina.cn/university-rankings/world-university-rankings/2023
然后在頁(yè)面點(diǎn)擊右鍵,選擇最下方檢查來(lái)打開開發(fā)者工具。
然后頁(yè)面是這樣:在右邊,開發(fā)這工具的左上角元素檢查的圖標(biāo),如下圖紅圈位置。點(diǎn)擊后鼠標(biāo)挪到左側(cè)網(wǎng)頁(yè)上面(先不要點(diǎn)擊)。
鼠標(biāo)就會(huì)變成一個(gè)選區(qū)的工具,鼠標(biāo)所指示的地方都會(huì)有藍(lán)色方塊來(lái)顯示元素的區(qū)域。把鼠標(biāo)移動(dòng)到排名指標(biāo)位置,會(huì)有藍(lán)色選中的樣式。如下圖
選中后點(diǎn)擊鼠標(biāo)左鍵,在右側(cè)開發(fā)者工具中就會(huì)顯示出這個(gè)元素的位置信息。在此處(下圖紅框位置)點(diǎn)擊鼠標(biāo)右鍵。
可以通過(guò)鼠標(biāo)右鍵-復(fù)制-復(fù)制xpath來(lái)獲取元素的定位信息。
檢查定位信息是否準(zhǔn)確,可以在打開開發(fā)者工具模式下,鍵盤按鍵 ctrl + f
來(lái)打開搜索工具框,然后把剛才復(fù)制的xpath
信息粘貼進(jìn)去,所定位的元素就會(huì)有綠色高亮來(lái)標(biāo)記出來(lái),并且搜索框后面會(huì)顯示出xpath
定位的元素個(gè)數(shù)(綠圈標(biāo)記)。此處應(yīng)該是位置的所以后面會(huì)顯示1 of 1。
獲取到元素定位后,就開始寫代碼啦,完成鼠標(biāo)點(diǎn)擊只需要一行代碼就可以了。代碼如下:
driver.find_element(By.XPATH,'//*[@id="qs-rankings-datatables"]/div[1]/ul/li[2]/a').click()
# 通過(guò)設(shè)置sleep時(shí)間來(lái)控制爬蟲的速度,根據(jù)情況,也可不用??葱那?/span>
time.sleep(1)
提取數(shù)據(jù)
前面的步驟完成后,頁(yè)面就能顯示出需要爬取的數(shù)據(jù)了,接下來(lái)就開始研究如何提取頁(yè)面的數(shù)據(jù)了。
先定位數(shù)據(jù)的元素位置,如何選擇參考前面。
找到數(shù)據(jù)的位置后,復(fù)制xpath
路徑,在使用ctrl+f
來(lái)檢驗(yàn)是否正確。
確定定位沒(méi)問(wèn)題后,那么就表示其他需要獲取的數(shù)據(jù)也在此處,分析查看上下代碼后可知道,需要的數(shù)據(jù)確實(shí)都在同一個(gè)tr
中,那么下面就可以逐個(gè)去獲取數(shù)據(jù)了。
開始編寫獲取數(shù)據(jù)的代碼。
我們需要獲取的數(shù)據(jù)內(nèi)容分別是 排名、大學(xué)名稱、大學(xué)詳情鏈接地址、綜合得分、學(xué)術(shù)聲譽(yù)、雇主聲譽(yù)、每位教員引用率、師生比、國(guó)際學(xué)生占比、國(guó)際教師占比
先編寫獲取一個(gè)的代碼,其他的都可以以此為例之改變定位信息就可以了。
以排名為例:
# 新建一個(gè)空的列表用來(lái)儲(chǔ)存獲取的數(shù)據(jù)
rank_all = []
#在selenium中使用xpath定位,
#因?yàn)槎ㄎ坏氖嵌鄠€(gè)元素,所以此處要使用find_elements,不能使用find_element
list_rank = driver.find_elements(By.XPATH,'//*[@id="qs-rankings-indicators"]/tbody/tr//td[@class=" rank"]')
# 遍歷每個(gè)元素提取數(shù)據(jù)信息
for li_rank in list_rank:
rank = li_rank.find_element(By.XPATH,'./div/div').text
# 數(shù)據(jù)保存到列表中
rank_all.append(rank)
根據(jù)上面的代碼,逐個(gè)編寫獲取其他數(shù)據(jù)的代碼。
由于網(wǎng)頁(yè)上面每一頁(yè)只有25條數(shù)據(jù),需要翻頁(yè)然后多次調(diào)用獲取數(shù)據(jù)信息的代碼,所以把獲取數(shù)據(jù)信息的代碼打包為一個(gè)def
來(lái)方便多次調(diào)用。代碼如下
# 創(chuàng)建空的數(shù)據(jù)列表用來(lái)保存數(shù)據(jù)
# 排名
rank_all = []
# 大學(xué)名稱
name_all = []
# 大學(xué)詳情鏈接地址
href_all = []
# 綜合得分
scor_all = []
# 學(xué)術(shù)聲譽(yù)
xueshu_all = []
# 雇主聲譽(yù)
guzhu_all = []
# 每位教員引用率
jiaoyuan_all = []
# 師生比
shishengbi_all = []
# 國(guó)際學(xué)生占比
guoji_xuesheng_all = []
# 國(guó)際教師占比
guoji_jiaoshi_all = []
def get_text():
# rank 排名
list_rank = driver.find_elements(By.XPATH,'//*[@id="qs-rankings-indicators"]/tbody/tr//td[@class=" rank"]')
for li_rank in list_rank:
rank = li_rank.find_element(By.XPATH,'./div/div').text
# 保存數(shù)據(jù)到列表
rank_all.append(rank)
# name 大學(xué)名稱
list_name = driver.find_elements(By.XPATH,'//*[@id="qs-rankings-indicators"]/tbody/tr//td[@class=" uni"]/div/div')
for li_name in list_name:
name = li_name.find_element(By.XPATH,'./a').text
# 保存數(shù)據(jù)到列表
name_all.append(name)
# href 大學(xué)詳情鏈接地址
list_href = driver.find_elements(By.XPATH,'//*[@id="qs-rankings-indicators"]/tbody/tr//td[@class=" uni"]/div/div')
for li_href in list_href:
href = li_href.find_element(By.XPATH,'./a').get_attribute('href')
# 保存數(shù)據(jù)到列表
href_all.append(href)
# 綜合得分
list_scor = driver.find_elements(By.XPATH,'//*[@id="qs-rankings-indicators"]/tbody/tr//td[@class="ind-col ind-overall sorting_1"]')
for li_scor in list_scor:
scor = li_scor.text
# 保存數(shù)據(jù)到列表
scor_all.append(scor)
# 學(xué)術(shù)聲譽(yù)
list_xueshu = driver.find_elements(By.XPATH,'//*[@id="qs-rankings-indicators"]/tbody/tr//td[@class=" ind-col ind-76"]')
for li_xueshu in list_xueshu:
xueshu = li_xueshu.find_element(By.XPATH,'./div/div').text
# 保存數(shù)據(jù)到列表
xueshu_all.append(xueshu)
# 雇主聲譽(yù)
list_guzhu = driver.find_elements(By.XPATH,'//*[@id="qs-rankings-indicators"]/tbody/tr//td[@class=" ind-col ind-77"]')
for li_guzhu in list_guzhu:
guzhu = li_xueshu.find_element(By.XPATH,'./div/div').text
# 保存數(shù)據(jù)到列表
guzhu_all.append(guzhu)
# 每位教員引用率
list_jiaoyuan = driver.find_elements(By.XPATH,'//*[@id="qs-rankings-indicators"]/tbody/tr//td[@class=" ind-col ind-73"]')
for li_jiaoyuan in list_jiaoyuan:
jiaoyuan = li_jiaoyuan.find_element(By.XPATH,'./div/div').text
# 保存數(shù)據(jù)到列表
jiaoyuan_all.append(jiaoyuan)
# 師生比
list_shishengbi = driver.find_elements(By.XPATH,'//*[@id="qs-rankings-indicators"]/tbody/tr//td[@class=" ind-col ind-36"]')
for li_shishengbi in list_shishengbi:
shishengbi = li_shishengbi.find_element(By.XPATH,'./div/div').text
# 保存數(shù)據(jù)到列表
shishengbi_all.append(shishengbi)
# 國(guó)際學(xué)生占比
list_guoji_xuesheng = driver.find_elements(By.XPATH,'//*[@id="qs-rankings-indicators"]/tbody/tr//td[@class=" ind-col ind-14"]')
for li_guoji_xuesheng in list_guoji_xuesheng:
guoji_xuesheng = li_guoji_xuesheng.find_element(By.XPATH,'./div/div').text
# 保存數(shù)據(jù)到列表
guoji_xuesheng_all.append(guoji_xuesheng)
# 國(guó)際教師占比
list_guoji_jiaoshi = driver.find_elements(By.XPATH,'//*[@id="qs-rankings-indicators"]/tbody/tr//td[@class=" ind-col ind-14"]')
for li_guoji_jiaoshi in list_guoji_jiaoshi:
guoji_jiaoshi = li_guoji_jiaoshi.find_element(By.XPATH,'./div/div').text
# 保存數(shù)據(jù)到列表
guoji_jiaoshi_all.append(guoji_jiaoshi)
滾輪翻頁(yè)
前面我們已經(jīng)完成了頁(yè)面數(shù)據(jù)的獲取,不過(guò)獲取的只是第一頁(yè)的25條數(shù)據(jù),想要獲取更多的數(shù)據(jù),需要我們?nèi)?shí)現(xiàn)翻頁(yè)然后再調(diào)用獲取數(shù)據(jù)信息的代碼來(lái)去獲取新的數(shù)據(jù),從而實(shí)現(xiàn)我們1000條數(shù)據(jù)的目標(biāo)。
如何實(shí)現(xiàn)翻頁(yè)呢?
我么看下頁(yè)面(下圖),想要實(shí)現(xiàn)翻頁(yè),首先要操作右側(cè)的滾動(dòng)條下拉,到達(dá)能顯示翻頁(yè)元素的位置,然后獲取向后翻頁(yè)的元素按鈕,點(diǎn)擊實(shí)現(xiàn)翻頁(yè)。
第一步 :先實(shí)現(xiàn)滾動(dòng)條下滑
通過(guò)selenium控制滾動(dòng)條,實(shí)現(xiàn)向下滑動(dòng)。
# 滾動(dòng)滑輪下滑, = 2500 為向下滑動(dòng)的距離,這個(gè)數(shù)值可以根據(jù)實(shí)際情況調(diào)整。
driver.execute_script("document.documentElement.scrollTop=2500")
# 通過(guò)設(shè)置sleep時(shí)間來(lái)控制爬蟲的速度,根據(jù)情況,也可不用。看心情
time.sleep(1)
效果如下:
第二步:實(shí)現(xiàn)翻頁(yè)
實(shí)現(xiàn)翻頁(yè)只需要獲取到下一頁(yè)按鈕元素的定位信息,然后再操作鼠標(biāo)點(diǎn)擊,就完成了向下翻頁(yè)的效果。不需要去獲取頁(yè)碼,那樣太麻煩。
通過(guò)selenium實(shí)現(xiàn)鼠標(biāo)點(diǎn)擊,進(jìn)行翻頁(yè)。
# 控制鼠標(biāo)點(diǎn)擊進(jìn)行翻頁(yè)
driver.find_element(By.XPATH,'//*[@id="qs-rankings-indicators_next"]').click()
# 通過(guò)設(shè)置sleep時(shí)間來(lái)控制爬蟲的速度,根據(jù)情況,也可不用。看心情
time.sleep(1)
滾動(dòng)翻頁(yè)效果:
到這一步基本上已經(jīng)把獲取數(shù)據(jù)的操作功能全部都實(shí)現(xiàn)了,后面只需要構(gòu)建循環(huán),讓爬蟲自動(dòng)去爬取數(shù)據(jù)就ok了。
構(gòu)建循環(huán)自動(dòng)爬取數(shù)據(jù)
在構(gòu)建循環(huán)的時(shí)候遇到一個(gè)問(wèn)題,在滾動(dòng)條下滑翻頁(yè)的時(shí)候,第一次翻頁(yè)需要向下滑動(dòng)的距離長(zhǎng)一些,之后所有的下滑距離都是一樣的,那么就需要把第一次翻頁(yè)單獨(dú)的執(zhí)行后,之后的翻頁(yè)可以用循環(huán)的形式來(lái)不停的實(shí)現(xiàn)翻頁(yè)。
具體代碼如下(截止目前所有代碼):
# 導(dǎo)入需要的模塊
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
import time
import pandas as pd
# 創(chuàng)建空的數(shù)據(jù)列表用來(lái)保存數(shù)據(jù)
# 排名
rank_all = []
# 大學(xué)名稱
name_all = []
# 大學(xué)詳情鏈接地址
href_all = []
# 綜合得分
scor_all = []
# 學(xué)術(shù)聲譽(yù)
xueshu_all = []
# 雇主聲譽(yù)
guzhu_all = []
# 每位教員引用率
jiaoyuan_all = []
# 師生比
shishengbi_all = []
# 國(guó)際學(xué)生占比
guoji_xuesheng_all = []
# 國(guó)際教師占比
guoji_jiaoshi_all = []
def get_text():
# rank 排名
list_rank = driver.find_elements(By.XPATH,'//*[@id="qs-rankings-indicators"]/tbody/tr//td[@class=" rank"]')
for li_rank in list_rank:
rank = li_rank.find_element(By.XPATH,'./div/div').text
# 保存數(shù)據(jù)到列表
rank_all.append(rank)
# name 大學(xué)名稱
list_name = driver.find_elements(By.XPATH,'//*[@id="qs-rankings-indicators"]/tbody/tr//td[@class=" uni"]/div/div')
for li_name in list_name:
name = li_name.find_element(By.XPATH,'./a').text
# 保存數(shù)據(jù)到列表
name_all.append(name)
# href 大學(xué)詳情鏈接地址
list_href = driver.find_elements(By.XPATH,'//*[@id="qs-rankings-indicators"]/tbody/tr//td[@class=" uni"]/div/div')
for li_href in list_href:
href = li_href.find_element(By.XPATH,'./a').get_attribute('href')
# 保存數(shù)據(jù)到列表
href_all.append(href)
# 綜合得分
list_scor = driver.find_elements(By.XPATH,'//*[@id="qs-rankings-indicators"]/tbody/tr//td[@class="ind-col ind-overall sorting_1"]')
for li_scor in list_scor:
scor = li_scor.text
# 保存數(shù)據(jù)到列表
scor_all.append(scor)
# 學(xué)術(shù)聲譽(yù)
list_xueshu = driver.find_elements(By.XPATH,'//*[@id="qs-rankings-indicators"]/tbody/tr//td[@class=" ind-col ind-76"]')
for li_xueshu in list_xueshu:
xueshu = li_xueshu.find_element(By.XPATH,'./div/div').text
# 保存數(shù)據(jù)到列表
xueshu_all.append(xueshu)
# 雇主聲譽(yù)
list_guzhu = driver.find_elements(By.XPATH,'//*[@id="qs-rankings-indicators"]/tbody/tr//td[@class=" ind-col ind-77"]')
for li_guzhu in list_guzhu:
guzhu = li_xueshu.find_element(By.XPATH,'./div/div').text
# 保存數(shù)據(jù)到列表
guzhu_all.append(guzhu)
# 每位教員引用率
list_jiaoyuan = driver.find_elements(By.XPATH,'//*[@id="qs-rankings-indicators"]/tbody/tr//td[@class=" ind-col ind-73"]')
for li_jiaoyuan in list_jiaoyuan:
jiaoyuan = li_jiaoyuan.find_element(By.XPATH,'./div/div').text
# 保存數(shù)據(jù)到列表
jiaoyuan_all.append(jiaoyuan)
# 師生比
list_shishengbi = driver.find_elements(By.XPATH,'//*[@id="qs-rankings-indicators"]/tbody/tr//td[@class=" ind-col ind-36"]')
for li_shishengbi in list_shishengbi:
shishengbi = li_shishengbi.find_element(By.XPATH,'./div/div').text
# 保存數(shù)據(jù)到列表
shishengbi_all.append(shishengbi)
# 國(guó)際學(xué)生占比
list_guoji_xuesheng = driver.find_elements(By.XPATH,'//*[@id="qs-rankings-indicators"]/tbody/tr//td[@class=" ind-col ind-14"]')
for li_guoji_xuesheng in list_guoji_xuesheng:
guoji_xuesheng = li_guoji_xuesheng.find_element(By.XPATH,'./div/div').text
# 保存數(shù)據(jù)到列表
guoji_xuesheng_all.append(guoji_xuesheng)
# 國(guó)際教師占比
list_guoji_jiaoshi = driver.find_elements(By.XPATH,'//*[@id="qs-rankings-indicators"]/tbody/tr//td[@class=" ind-col ind-14"]')
for li_guoji_jiaoshi in list_guoji_jiaoshi:
guoji_jiaoshi = li_guoji_jiaoshi.find_element(By.XPATH,'./div/div').text
# 保存數(shù)據(jù)到列表
guoji_jiaoshi_all.append(guoji_jiaoshi)
# 設(shè)置瀏覽器路徑
servic = Service(executable_path =r'***/chromedriver.exe')
driver = webdriver.Chrome(service=servic)
# 獲取網(wǎng)頁(yè)
driver.get("https://www.qschina.cn/university-rankings/world-university-rankings/2023")
time.sleep(2)
# 定位要找的元素
# 調(diào)用鼠標(biāo)操作方法
driver.find_element(By.XPATH,'//*[@id="qs-rankings-datatables"]/div[1]/ul/li[2]/a').click()
time.sleep(2)
# 獲取第一頁(yè)數(shù)據(jù) #####################
get_text()
# 獲取第二頁(yè)數(shù)據(jù) #########################
# 滾動(dòng)?xùn)|滑輪下滑
driver.execute_script("document.documentElement.scrollTop=2500")
time.sleep(2)
# 進(jìn)行翻頁(yè)
driver.find_element(By.XPATH,'//*[@id="qs-rankings-indicators_next"]').click()
# 獲取第二頁(yè)數(shù)據(jù)
get_text()
time.sleep(1.5)
# 從第三頁(yè)開始 循環(huán)爬取#######
# 此處page設(shè)置需要的頁(yè)數(shù)
page = 40
i = 1
# 由于前面已經(jīng)獲取了兩頁(yè)數(shù)據(jù),用page-2 來(lái)把頁(yè)數(shù)統(tǒng)一
while i <= page-2:
driver.execute_script("document.documentElement.scrollTop=2100")
time.sleep(2)
# 進(jìn)行翻頁(yè)
driver.find_element(By.XPATH,'//*[@id="qs-rankings-indicators_next"]').click()
# 獲取第三頁(yè)數(shù)據(jù)
get_text()
time.sleep(0.5)
i += 1
數(shù)據(jù)儲(chǔ)存
前面已經(jīng)完成了所有的數(shù)據(jù)獲取,并且都儲(chǔ)存在指定的列表中了,下面就只需要把這些數(shù)據(jù)導(dǎo)出保存到電腦中。python中處理數(shù)據(jù),尤其是表的形式,用pandas最方便一些。
代碼如下():
# 數(shù)據(jù)合并為數(shù)據(jù)表
data = pd.DataFrame({
'排名':rank_all,
'中文名稱':name_all,
'詳情鏈接':href_all,
'綜合得分':scor_all,
'學(xué)術(shù)聲譽(yù)':xueshu_all,
'雇主聲譽(yù)':guzhu_all,
'每位教員引用率':jiaoyuan_all,
'師生比':shishengbi_all,
'國(guó)際學(xué)生占比':guoji_xuesheng_all,
'國(guó)際教師占比':guoji_jiaoshi_all
})
# 保存為CSV文件
data.to_csv('QS世界大學(xué)排名.csv',index=False)
# 下面代碼可用可不用
#查看數(shù)據(jù)前5行,可以檢查下數(shù)據(jù)看是想要的樣子
data.head()
第二部分
前面第一部分?jǐn)?shù)據(jù)獲取完畢之后,第二部分就比較簡(jiǎn)單了,就是通過(guò)前面獲取到的每個(gè)學(xué)校的詳情頁(yè)鏈接中的:高校性質(zhì)、研究成果、學(xué)生人數(shù)、教員人數(shù)、國(guó)際學(xué)生人數(shù)。
使用requests
配合xpath
就可以完成數(shù)據(jù)獲取了。
導(dǎo)入需要用到的python包
import pandas as pd
import requests
from lxml import etree
import time
獲取網(wǎng)頁(yè)
使用requests
時(shí)最好設(shè)置請(qǐng)求頭,也算是一種最簡(jiǎn)單的防止反扒的措施,關(guān)于反扒每個(gè)網(wǎng)站都不一樣,比如第一部分使用selenium來(lái)獲取數(shù)據(jù),也是一種防止反扒的手段,因?yàn)橛煤?jiǎn)單requests
是獲取不到想要的數(shù)據(jù),頁(yè)面數(shù)據(jù)是動(dòng)態(tài)加載的。
設(shè)置請(qǐng)求頭
如何設(shè)置請(qǐng)求頭,可以到網(wǎng)上搜索很容易就找到設(shè)置方法。就不再細(xì)說(shuō)這塊了。
# 設(shè)置請(qǐng)求頭
header = {
'user-agent':'****'
}
讀取鏈接
使用pandas
讀取前面獲取到的數(shù)據(jù),其實(shí)我們只需要兩列數(shù)據(jù),中文名稱和詳情鏈接。名稱用來(lái)在合并數(shù)據(jù)的時(shí)候去對(duì)應(yīng)數(shù)據(jù)不會(huì)弄亂,詳情鏈接就是我們需要獲取數(shù)據(jù)的目標(biāo)地址了。
# 讀取數(shù)據(jù)
df = pd.read_csv('./QS世界大學(xué)排名.csv')
# 只保留需要用到的兩列數(shù)據(jù)
df = df[['中文名稱','詳情鏈接']]
# 查看數(shù)據(jù)前5行
df.head()
獲取網(wǎng)頁(yè)信息
在獲取網(wǎng)頁(yè)數(shù)據(jù)的時(shí)候,我們可以先用其中一個(gè)鏈接去構(gòu)建爬蟲代碼,只要一個(gè)網(wǎng)頁(yè)的數(shù)據(jù)獲取到了,那么其他的網(wǎng)頁(yè)格式只要是一樣的,就可以構(gòu)建循環(huán)去遍歷全部的地址獲取數(shù)據(jù)就可以了。
下面就拿第一個(gè)鏈接來(lái)去獲取數(shù)據(jù)信息。
# 先用一個(gè)鏈接去搭建代碼
url = df['詳情鏈接'][0]
# 請(qǐng)求網(wǎng)頁(yè)
html = requests.get(url=link,headers=header)
# 把請(qǐng)求到的網(wǎng)頁(yè)轉(zhuǎn)換為xpath提取樣式,方便下面通過(guò)xpath直接提取數(shù)據(jù)信息。
text = etree.HTML(html.text)
定位節(jié)點(diǎn)獲取數(shù)據(jù)
通過(guò)選取節(jié)點(diǎn),然后查看頁(yè)面代碼,可以看到,這些數(shù)據(jù)都在同一個(gè)ul
中,不同的信息存在不同的li
中,下面我們就可以編寫代碼來(lái)獲取數(shù)據(jù)。
# 同樣我們要新建幾個(gè)空列表用來(lái)存儲(chǔ)不同的數(shù)據(jù)信息。
name_all = []
title_all = []
info_all = []
# 獲取要爬取內(nèi)容的所有標(biāo)簽
list_all = text.xpath('//div[@class="uni_snapshot"]/ul/li')
for li in list_all:
title = li.xpath('./span/text()')[0]
info = li.xpath('./span/b/text()')[0]
獲取到需要的數(shù)據(jù)后,下面我們就要構(gòu)建循環(huán)去把1000所學(xué)校的信息都獲取到,然后把數(shù)據(jù)保存為csv格式。
第二部分完整代碼如下:
# 導(dǎo)入需要的模塊
import pandas as pd
import requests
from lxml import etree
import time
# 讀取數(shù)據(jù)
df = pd.read_csv('./QS世界大學(xué)排名.csv')
df = df[['中文名稱','詳情鏈接']]
# 設(shè)置請(qǐng)求頭
header = {
'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36 Edg/112.0.1722.58'
}
# 創(chuàng)建空列表儲(chǔ)存數(shù)據(jù)
name_all = []
title_all = []
info_all = []
# 遍歷全部數(shù)據(jù),構(gòu)建循環(huán)爬取
for i in range(len(df)):
name = df['中文名稱'][i]
link = df['詳情鏈接'][i]
# 請(qǐng)求網(wǎng)頁(yè)
html = requests.get(url=link,headers=header)
# 把請(qǐng)求到的網(wǎng)頁(yè)轉(zhuǎn)換為xpath提取樣式,方便下面通過(guò)xpath直接圖區(qū)
text = etree.HTML(html.text)
# 獲取要爬取內(nèi)容的所有標(biāo)簽
list_all = text.xpath('//div[@class="uni_snapshot"]/ul/li')
for li in list_all:
title = li.xpath('./span/text()')[0]
info = li.xpath('./span/b/text()')[0]
# 把數(shù)據(jù)存入列表
name_all.append(name)
title_all.append(title)
info_all.append(info)
# 顯示爬取到第幾個(gè)學(xué)校
print(name,'*** OK ***','{}/1000'.format(i+1))
# time.sleep(0.5)
# 把數(shù)據(jù)合并為數(shù)據(jù)表
data = pd.DataFrame({
'name':name_all,
'title':title_all,
'info':info_all
})
# 把數(shù)據(jù)保存為csv
data.to_csv('詳細(xì)內(nèi)容.csv',index=False)
第二部分獲取到的數(shù)據(jù)樣式如下,是以長(zhǎng)表的形式保存的,第一部分的數(shù)據(jù)是寬表的形式保存的,所以下面還需要把第二部分的數(shù)據(jù)合并到第一部分,形成完整的數(shù)據(jù)表。
第三部分
合并第一部分和第二部分的數(shù)據(jù),我這里用的方法比較簡(jiǎn)單,略顯笨拙,應(yīng)該會(huì)有更簡(jiǎn)便的方法,不過(guò)能干活就行。
讀取數(shù)據(jù)
處理數(shù)據(jù)只用了pandas
,所以只需要導(dǎo)入一個(gè)pandas
就行了
import pandas as pd
# 讀取第一部分?jǐn)?shù)據(jù)
df_1 = pd.read_csv('./QS世界大學(xué)排名.csv')
# 讀取第二部分?jǐn)?shù)據(jù)
df_2 = pd.read_csv('./詳細(xì)內(nèi)容.csv')
部分?jǐn)?shù)據(jù)樣式
合并數(shù)據(jù)
合并數(shù)據(jù)的流程就是,把表df_2
中需要的數(shù)據(jù)按照title
中的分類去分別提取出來(lái),然后合并到df_1
中。
代碼如下:
# 先把df_2中的高校性質(zhì)提取出來(lái),保留學(xué)校name和info兩列
gaoxiaoxingzhi = df_2[df_2.title =='高校性質(zhì)'][['name','info']]
# 重新設(shè)置兩列的名稱,使的數(shù)據(jù)中高校的名稱這一列的列名和df_1中的一樣,方便合并數(shù)據(jù)。
gaoxiaoxingzhi.columns = ['中文名稱','高校性質(zhì)']
如下樣子:
然后把數(shù)據(jù)合并到df_1
中。
df_1 = df_1.merge(gaoxiaoxingzhi,how='left',on='中文名稱')
合并后如下:數(shù)據(jù)最右邊就多了一列數(shù)據(jù)
后面幾列數(shù)據(jù)合并方法一樣,下面是完整的合并數(shù)據(jù)代碼:
# 導(dǎo)入pandas
import pandas as pd
# 讀取數(shù)據(jù)
df_1 = pd.read_csv('./QS世界大學(xué)排名.csv')
df_2 = pd.read_csv('./詳細(xì)內(nèi)容.csv')
# 合并 高校性質(zhì)
gaoxiaoxingzhi = df_2[df_2.title =='高校性質(zhì)'][['name','info']]
gaoxiaoxingzhi.columns = ['中文名稱','高校性質(zhì)']
df_1 = df_1.merge(gaoxiaoxingzhi,how='left',on='中文名稱')
# 合并 研究成果
yanjiuchengguo = df_2[df_2.title =='研究成果'][['name','info']]
yanjiuchengguo.columns = ['中文名稱','研究成果']
df_1 = df_1.merge(yanjiuchengguo,how='left',on='中文名稱')
# 合并 學(xué)生人數(shù)
xuesheng = df_2[df_2.title =='學(xué)生人數(shù)'][['name','info']]
xuesheng.columns = ['中文名稱','學(xué)生人數(shù)']
df_1 = df_1.merge(xuesheng,how='left',on='中文名稱')
# 合并 教員人數(shù)
jiaoyuan = df_2[df_2.title =='教員人數(shù)'][['name','info']]
jiaoyuan.columns = ['中文名稱','教員人數(shù)']
df_1 = df_1.merge(jiaoyuan,how='left',on='中文名稱')
# 合并 國(guó)際學(xué)生人數(shù)
guojixuesheng = df_2[df_2.title =='國(guó)際學(xué)生人數(shù)'][['name','info']]
guojixuesheng.columns = ['中文名稱','國(guó)際學(xué)生人數(shù)']
df_1 = df_1.merge(guojixuesheng,how='left',on='中文名稱')
# 保存數(shù)據(jù)
df_1.to_csv('QS世界大學(xué)排名前1000數(shù)據(jù).csv',index=False)
全部數(shù)據(jù)合并后:
完成 ??!
全部代碼:
第一部分代碼:https://download.csdn.net/download/weixin_44678403/87747986文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-431735.html
第二部分代碼:
https://download.csdn.net/download/weixin_44678403/87747985
第三部分代碼:
https://download.csdn.net/download/weixin_44678403/87747986文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-431735.html
到了這里,關(guān)于爬蟲 - QS世界大學(xué)排名數(shù)據(jù)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!