使用Selenium實(shí)現(xiàn)微博爬蟲(預(yù)登錄、展開全文、翻頁(yè))
前言
在CSDN發(fā)的第一篇文章,時(shí)隔兩年,終于實(shí)現(xiàn)了爬微博的自由!本文可以解決微博預(yù)登錄、識(shí)別“展開全文”并爬取完整數(shù)據(jù)、翻頁(yè)設(shè)置等問(wèn)題。由于剛接觸爬蟲,有部分術(shù)語(yǔ)可能用的不正確,請(qǐng)大家多指正!
一、區(qū)分動(dòng)態(tài)爬蟲和靜態(tài)爬蟲
1、靜態(tài)網(wǎng)頁(yè)
靜態(tài)網(wǎng)頁(yè)是純粹的HTML,沒有后臺(tái)數(shù)據(jù)庫(kù),不含程序,不可交互,體量較少,加載速度快。靜態(tài)網(wǎng)頁(yè)的爬取只需四個(gè)步驟:發(fā)送請(qǐng)求、獲取相應(yīng)內(nèi)容、解析內(nèi)容及保存數(shù)據(jù)。
2、動(dòng)態(tài)網(wǎng)頁(yè)
動(dòng)態(tài)網(wǎng)頁(yè)上的數(shù)據(jù)會(huì)隨時(shí)間及用戶交互發(fā)生變化,因此數(shù)據(jù)不會(huì)直接呈現(xiàn)在網(wǎng)頁(yè)源代碼中,數(shù)據(jù)將以Json的形式保存起來(lái)。因此,動(dòng)態(tài)網(wǎng)頁(yè)比靜態(tài)網(wǎng)頁(yè)多了一步,即需渲染獲得相關(guān)數(shù)據(jù)。
3、區(qū)分動(dòng)靜態(tài)網(wǎng)頁(yè)的方法
加載網(wǎng)頁(yè)后,點(diǎn)擊右鍵,選中“查看網(wǎng)頁(yè)源代碼”,如果網(wǎng)頁(yè)上的絕大多數(shù)字段都出現(xiàn)源代碼中,那么這就是靜態(tài)網(wǎng)頁(yè),否則是動(dòng)態(tài)網(wǎng)頁(yè)。
二、動(dòng)態(tài)爬蟲的兩種方法
1.逆向分析爬取動(dòng)態(tài)網(wǎng)頁(yè)
適用于調(diào)度資源所對(duì)應(yīng)網(wǎng)址的數(shù)據(jù)為json格式,Javascript的觸發(fā)調(diào)度。主要步驟是獲取需要調(diào)度資源所對(duì)應(yīng)的網(wǎng)址-訪問(wèn)網(wǎng)址獲得該資源的數(shù)據(jù)。(此處不詳細(xì)講解)
2.使用Selenium庫(kù)爬取動(dòng)態(tài)網(wǎng)頁(yè)
使用Selenium庫(kù),該庫(kù)使用JavaScript模擬真實(shí)用戶對(duì)瀏覽器進(jìn)行操作。本案例將使用該方法。
三、安裝Selenium庫(kù)及下載瀏覽器補(bǔ)丁
1.Selenium庫(kù)使用pip工具進(jìn)行安裝即可。
2.下載與Chrome瀏覽器版本匹配的瀏覽器補(bǔ)丁。
Step1:查看Chrome的版本
Step2:去下載相應(yīng)版本的瀏覽器補(bǔ)丁。網(wǎng)址:http://npm.taobao.org/mirrors/chromedriver/
Step3:解壓文件,并將之放到與python.exe同一文件下
四、頁(yè)面打開及預(yù)登錄
1.導(dǎo)入selenium包
from selenium import webdriver from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.common.by import By import time import pandas as pd
2.打開頁(yè)面
driver = webdriver.Chrome() print('準(zhǔn)備登陸Weibo.cn網(wǎng)站...') #發(fā)送請(qǐng)求 driver.get("https://login.sina.com.cn/signup/signin.php") wait = WebDriverWait(driver,5) #重要:暫停1分鐘進(jìn)行預(yù)登陸,此處填寫賬號(hào)密碼及驗(yàn)證 time.sleep(60)
3.采用交互式運(yùn)行,運(yùn)行完上面兩段程序,會(huì)彈出一個(gè)框,這個(gè)框就是用來(lái)模擬網(wǎng)頁(yè)的交互。在這個(gè)框中完成登錄(包括填寫登錄名、密碼及短信驗(yàn)證等)
4.完成預(yù)登錄,則進(jìn)入個(gè)人主頁(yè)
五、關(guān)鍵詞搜索操作
1.定位上圖中的關(guān)鍵詞輸入框,并在框中輸入搜索對(duì)象,如“努力學(xué)習(xí)”
#使用selector去定位關(guān)鍵詞搜索框 s_input = driver.find_element_by_css_selector('#search_input') #向搜索框中傳入字段 s_input.send_keys("努力學(xué)習(xí)") #定位搜索鍵 confirm_btn = driver.find_element_by_css_selector('#search_submit') #點(diǎn)擊 confirm_btn.click()
2.當(dāng)完成上步的代碼運(yùn)行后,會(huì)彈出新的窗口,從個(gè)人主頁(yè)跳到微博搜索頁(yè)。但是driver仍在個(gè)人主頁(yè),需要人為進(jìn)行driver的移動(dòng),將之移動(dòng)到微博搜索頁(yè)。
3.使用switch_to.window()方法移位
#人為移動(dòng)driver driver.switch_to.window(driver.window_handles[1])
六、識(shí)別“展開全文”并爬取數(shù)據(jù)
1.了解每個(gè)元素的Selector,用以定位(重點(diǎn)在于唯一標(biāo)識(shí)性)
2.使用Selector定位元素,并獲取相應(yīng)的數(shù)據(jù)
comment = [] username = [] #抓取節(jié)點(diǎn):每個(gè)評(píng)論為一個(gè)節(jié)點(diǎn)(包括用戶信息、評(píng)論、日期等信息),如果一頁(yè)有20條評(píng)論,那么nodes的長(zhǎng)度就為20 nodes = driver.find_elements_by_css_selector('div.card > div.card-feed > div.content') #對(duì)每個(gè)節(jié)點(diǎn)進(jìn)行循環(huán)操作 for i in range(0,len(nodes),1): #判斷每個(gè)節(jié)點(diǎn)是否有“展開全文”的鏈接 flag = False try: nodes[i].find_element_by_css_selector("p>a[action-type='fl_unfold']").is_displayed() flag = True except: flag = False #如果該節(jié)點(diǎn)具有“展開全文”的鏈接,且該鏈接中的文字是“展開全文c”,那么點(diǎn)擊這個(gè)要素,并獲取指定位置的文本;否則直接獲取文本 #(兩個(gè)條件需要同時(shí)滿足,因?yàn)樵搒elector不僅標(biāo)識(shí)了展開全文,還標(biāo)識(shí)了其他元素,沒有做到唯一定位) if(flag and nodes[i].find_element_by_css_selector("p>a[action-type='fl_unfold']").text.startswith('展開全文c')): nodes[i].find_element_by_css_selector("p>a[action-type='fl_unfold']").click() comment.append(nodes[i].find_element_by_css_selector('p[node-type="feed_list_content_full"]').text) else: comment.append(nodes[i].find_element_by_css_selector('p[node-type="feed_list_content"]').text) username.append(nodes[i].find_element_by_css_selector("div.info>div:nth-child(2)>a").text)
七、設(shè)置翻頁(yè)
1.使用for循環(huán)實(shí)現(xiàn)翻頁(yè),重點(diǎn)在于識(shí)別“下一頁(yè)”按鈕,并點(diǎn)擊它
for page in range(49): print(page) # 定位下一頁(yè)按鈕 nextpage_button = driver.find_element_by_link_text('下一頁(yè)') #點(diǎn)擊按鍵 driver.execute_script("arguments[0].click();", nextpage_button) wait = WebDriverWait(driver,5) #與前面類似 nodes1 = driver.find_elements_by_css_selector('div.card > div.card-feed > div.content') for i in range(0,len(nodes1),1): flag = False try: nodes1[i].find_element_by_css_selector("p>a[action-type='fl_unfold']").is_displayed() flag = True except: flag = False if (flag and nodes1[i].find_element_by_css_selector("p>a[action-type='fl_unfold']").text.startswith('展開全文c')): nodes1[i].find_element_by_css_selector("p>a[action-type='fl_unfold']").click() comment.append(nodes1[i].find_element_by_css_selector('p[node-type="feed_list_content_full"]').text) else: comment.append(nodes1[i].find_element_by_css_selector('p[node-type="feed_list_content"]').text) username.append(nodes1[i].find_element_by_css_selector("div.info>div:nth-child(2)>a").text)
八、保存數(shù)據(jù)
1.使用DataFrame保存字段
data = pd.DataFrame({'username':username,'comment':comment})
2.導(dǎo)出到Excel
data.to_excel("weibo.xlsx")
九、完整代碼
from selenium import webdriver from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.common.by import By from bs4 import BeautifulSoup import time import pandas as pd '''打開網(wǎng)址,預(yù)登陸''' driver = webdriver.Chrome() print('準(zhǔn)備登陸Weibo.cn網(wǎng)站...') #發(fā)送請(qǐng)求 driver.get("https://login.sina.com.cn/signup/signin.php") wait = WebDriverWait(driver,5) #重要:暫停1分鐘進(jìn)行預(yù)登陸,此處填寫賬號(hào)密碼及驗(yàn)證 time.sleep(60) '''輸入關(guān)鍵詞到搜索框,完成搜索''' #使用selector去定位關(guān)鍵詞搜索框 s_input = driver.find_element_by_css_selector('#search_input') #向搜索框中傳入字段 s_input.send_keys("努力學(xué)習(xí)") #定位搜索鍵 confirm_btn = driver.find_element_by_css_selector('#search_submit') #點(diǎn)擊 confirm_btn.click() #人為移動(dòng)driver driver.switch_to.window(driver.window_handles[1]) '''爬取第一頁(yè)數(shù)據(jù)''' comment = [] username = [] #抓取節(jié)點(diǎn):每個(gè)評(píng)論為一個(gè)節(jié)點(diǎn)(包括用戶信息、評(píng)論、日期等信息),如果一頁(yè)有20條評(píng)論,那么nodes的長(zhǎng)度就為20 nodes = driver.find_elements_by_css_selector('div.card > div.card-feed > div.content') #對(duì)每個(gè)節(jié)點(diǎn)進(jìn)行循環(huán)操作 for i in range(0,len(nodes),1): #判斷每個(gè)節(jié)點(diǎn)是否有“展開全文”的鏈接 flag = False try: nodes[i].find_element_by_css_selector("p>a[action-type='fl_unfold']").is_displayed() flag = True except: flag = False #如果該節(jié)點(diǎn)具有“展開全文”的鏈接,且該鏈接中的文字是“展開全文c”,那么點(diǎn)擊這個(gè)要素,并獲取指定位置的文本;否則直接獲取文本 #(兩個(gè)條件需要同時(shí)滿足,因?yàn)樵搒elector不僅標(biāo)識(shí)了展開全文,還標(biāo)識(shí)了其他元素,沒有做到唯一定位) if(flag and nodes[i].find_element_by_css_selector("p>a[action-type='fl_unfold']").text.startswith('展開全文c')): nodes[i].find_element_by_css_selector("p>a[action-type='fl_unfold']").click() comment.append(nodes[i].find_element_by_css_selector('p[node-type="feed_list_content_full"]').text) else: comment.append(nodes[i].find_element_by_css_selector('p[node-type="feed_list_content"]').text) username.append(nodes[i].find_element_by_css_selector("div.info>div:nth-child(2)>a").text) '''循環(huán)操作,獲取剩余頁(yè)數(shù)的數(shù)據(jù)''' for page in range(49): print(page) # 定位下一頁(yè)按鈕 nextpage_button = driver.find_element_by_link_text('下一頁(yè)') #點(diǎn)擊按鍵 driver.execute_script("arguments[0].click();", nextpage_button) wait = WebDriverWait(driver,5) #與前面類似 nodes1 = driver.find_elements_by_css_selector('div.card > div.card-feed > div.content') for i in range(0,len(nodes1),1): flag = False try: nodes1[i].find_element_by_css_selector("p>a[action-type='fl_unfold']").is_displayed() flag = True except: flag = False if (flag and nodes1[i].find_element_by_css_selector("p>a[action-type='fl_unfold']").text.startswith('展開全文c')): nodes1[i].find_element_by_css_selector("p>a[action-type='fl_unfold']").click() comment.append(nodes1[i].find_element_by_css_selector('p[node-type="feed_list_content_full"]').text) else: comment.append(nodes1[i].find_element_by_css_selector('p[node-type="feed_list_content"]').text) username.append(nodes1[i].find_element_by_css_selector("div.info>div:nth-child(2)>a").text) '''保存數(shù)據(jù)''' data = pd.DataFrame({'username':username,'comment':comment}) data.to_excel("weibo.xlsx")
到此這篇關(guān)于使用Selenium實(shí)現(xiàn)微博爬蟲(預(yù)登錄、展開全文、翻頁(yè))的文章就介紹到這了,更多相關(guān)Selenium 微博爬蟲 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 基于python requests selenium爬取excel vba過(guò)程解析
- Python + selenium + requests實(shí)現(xiàn)12306全自動(dòng)搶票及驗(yàn)證碼破解加自動(dòng)點(diǎn)擊功能
- 如何使用selenium和requests組合實(shí)現(xiàn)登錄頁(yè)面
- python selenium實(shí)現(xiàn)智聯(lián)招聘數(shù)據(jù)爬取
- Python+Selenium定位不到元素常見原因及解決辦法(報(bào):NoSuchElementException)
- python+selenium小米商城紅米K40手機(jī)自動(dòng)搶購(gòu)的示例代碼
- python爬蟲之利用Selenium+Requests爬取拉勾網(wǎng)
相關(guān)文章
好用的Python編輯器WingIDE的使用經(jīng)驗(yàn)總結(jié)
WingIDE是個(gè)專為python程序語(yǔ)言設(shè)計(jì)的集成開發(fā)環(huán)境。從1999年起,Wingware公司便開始專注于python開發(fā),目前WingIDE已經(jīng)是著名的python開發(fā)框架,面向項(xiàng)目風(fēng)格的 IDE 對(duì)于大型產(chǎn)品非常有用, 是個(gè)很有前途的開發(fā)環(huán)境。2016-08-08requests.post()方法中data和json參數(shù)的使用
這篇文章主要介紹了requests.post()方法中data和json參數(shù)的使用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-02-02Python Flask異步發(fā)送郵件實(shí)現(xiàn)方法解析
這篇文章主要介紹了Python Flask異步發(fā)送郵件實(shí)現(xiàn)方法解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-08-08Python守護(hù)進(jìn)程和腳本單例運(yùn)行詳解
本篇文章主要介紹了Python守護(hù)進(jìn)程和腳本單例運(yùn)行,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-01-01django drf框架中的user驗(yàn)證以及JWT拓展的介紹
這篇文章主要介紹了django drf框架中的user驗(yàn)證以及JWT拓展的介紹,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08Python實(shí)現(xiàn)讀取TXT文件數(shù)據(jù)并存進(jìn)內(nèi)置數(shù)據(jù)庫(kù)SQLite3的方法
這篇文章主要介紹了Python實(shí)現(xiàn)讀取TXT文件數(shù)據(jù)并存進(jìn)內(nèi)置數(shù)據(jù)庫(kù)SQLite3的方法,涉及Python針對(duì)txt文件的讀取及sqlite3數(shù)據(jù)庫(kù)的創(chuàng)建、插入、查詢等相關(guān)操作技巧,需要的朋友可以參考下2017-08-08