文章目錄
- 寫在前面
- 案例分析
- 代碼實作
寫在前面
前幾天學習了selenium自動化以及CSS、Xpath元素定位,想着找個網站練練手,不用登入的B站就是個不錯的選擇,下面以B站的校園學習專欄為例進行視訊标題及外鍊資訊的爬取。
測試環境
Windows 10 x64
Python 3.6.8
VS code
案例分析
- 第一步當然是檢視關鍵資訊的定位,這裡直接右鍵複制Xpath就OK,不過也需要思考Xpath的對應變化,比如翻頁後哪些值變了而哪些值不變,找到翻頁後的規律就能順利寫代碼了。
- 接下來需要考慮翻頁的實作,我一開始考慮的是從url入手,但是采用selenium的話會很浪費資源,于是就選擇頁面内翻頁,這裡就要想想具體怎麼實作了。下面代碼中的
函數是我的直接思路,就是直接用Xpath定位,但是在抓取到第五頁時候其标簽就發生變化了(采用标簽序号定位穩定性較差),于是我直接定位網頁中的頁面跳轉輸入框,每次頁碼增1,就可以了。page_plus_1()
- 最後,是循環的處理,這裡我用了while循環并設定跳出條件,内部嵌套了每一頁的條目循環,感覺還可以提高代碼運作效率,不過作為小白的我還是先打好基礎吧。
不得不說selenium庫的封裝還是很便攜的,除了Xpath要費點事,剩下的都可以直接調用現成的方法。下面是代碼的具體實作。
代碼實作
# 用于設定強制等待
from time import sleep
# 浏覽器自動化引擎
from selenium import webdriver
def web_auto_gain_item(page_num, item_num):
# 每一頁顯示20個條目
# 定位待抓取文字
elems_title = driver.find_elements_by_xpath(
'//*[@id="videolist_box"]/div[2]/ul/li[%d]/div/div[2]/a'%(item_num)
)
for elem in elems_title:
# 抓取内容為:視訊标題及外部連結(需要讀取屬性值)
content = elem.text + ': ' + elem.get_attribute("href") + '\n'
# 存儲内容至文本檔案,設定編碼以存儲文本字元串
with open('bilibili_tech_list.txt', 'a', encoding='utf-8') as file:
file.write(content)
print(content)
if item_num==20:
print("第%d頁抓取完成\n"%(page_num)+'-'*30)
sleep(1)
def page_plus_1(page_num):
# 定位翻頁按鈕,進行翻頁操作
# 第一頁的翻頁位于li[7], 之後的翻頁位于li[8]
# (但是由于使用數字定位标簽,導緻其魯棒性不高,是以下面考慮第二種辦法)
if page_num==1:
# 點選翻頁
driver.find_element_by_xpath(
'//*[@id="videolist_box"]/div[2]/div[2]/ul/li[7]/button'
).click()
else:
driver.find_element_by_xpath(
'//*[@id="videolist_box"]/div[2]/div[2]/ul/li[8]/button'
).click()
def page_plus_2(page_num):
# 定位元素:網頁翻頁的
driver.find_element_by_xpath(
'//*[@id="videolist_box"]/div[2]/div[2]/div/input'
).send_keys('%d\n'%(page_num+1))
if __name__ == '__main__':
# 待抓取的連結
url = '''https://www.bilibili.com/v/technology/campus/#
/all/stow/0/1/2020-08-07,2020-08-14'''
# 執行個體化自動化引擎
driver = webdriver.Edge(r"C:\msedgedriver.exe")
driver.get(url)
# 設定隐性等待
driver.implicitly_wait(15)
# 開始抓取
while True:
# 強制等待1s,便于讀取頁碼資訊
sleep(1)
page_num = eval(driver.current_url.split("/")[-2])
print("開始抓取第%d頁"%(page_num))
# 循環提取item資訊
for item_num in range(1,21):
web_auto_gain_item(page_num, item_num)
# 抓取一頁完成後進行翻頁
page_plus_2(page_num)
# 設定循環跳出的條件,這裡以抓取5頁,20*5=100條視訊資訊為例
if page_num == 5:
print("抓取完畢,關閉浏覽器,謝謝使用!")
# 關閉浏覽器,釋放記憶體
driver.close()
break