使用selenium自动化工具爬取微博内容和评论
任務(wù)需求是爬取微博的內(nèi)容和評(píng)論。一開始我是準(zhǔn)備直接用正常的爬蟲來做,但是發(fā)現(xiàn)微博上的內(nèi)容幾乎都是動(dòng)態(tài)加載生成的。所以了解了一下就學(xué)習(xí)使用·selenium自動(dòng)化測(cè)試工具來爬取相關(guān)數(shù)據(jù)。
首先是不登錄微博,發(fā)現(xiàn)只能查看最多二十條數(shù)據(jù),這自然限制太大所以還是需要實(shí)現(xiàn)登錄后再爬取。
1.登錄微博
由于微博現(xiàn)在的登錄不能只輸入賬號(hào)密碼,所以通過查找了一些方法后選用了注入cookie來實(shí)現(xiàn)自動(dòng)登錄。而想要注入的cookie需要自己先登錄獲得。這里直接使用了各位大佬給出的方法。實(shí)現(xiàn)掃碼登錄后獲取cookie。
from selenium import webdriver from time import sleep import json from selenium.webdriver.common.by import Byif __name__ == '__main__':driver = webdriver.Chrome()driver.maximize_window()driver.get('https://weibo.com/login.php')sleep(6)a = driver.find_element(By.XPATH, '//*[@id="pl_login_form"]/div/div[1]/div/a[2]')a.click()sleep(10)dictCookies = driver.get_cookies() # 獲取list的cookiesjsonCookies = json.dumps(dictCookies) # 轉(zhuǎn)換成字符串保存with open('微博_cookies.txt', 'w') as f:f.write(jsonCookies)print('cookies保存成功!')2.通過獲取到的cookie實(shí)現(xiàn)自動(dòng)登錄然后爬取用戶微博內(nèi)容和評(píng)論
2.1打開瀏覽器,進(jìn)入到登錄頁(yè)面。這里我最大化窗口了。
# 打開瀏覽器,進(jìn)入到微博登錄頁(yè)面 def browser_initial():browser = webdriver.Chrome()browser.maximize_window()browser.get('https://weibo.com/login.php')return browser2.2實(shí)現(xiàn)自動(dòng)化登錄
# 將已經(jīng)登錄獲得的cookie寫入,實(shí)現(xiàn)自動(dòng)登錄 def log_csdn(browser):with open('微博_cookies.txt', 'r', encoding='utf8') as f:listCookies = json.loads(f.read())# 往browser里添加cookiesfor cookie in listCookies:cookie_dict = {'domain': '.weibo.com','name': cookie.get('name'),'value': cookie.get('value'),"expires": '','path': '/','httpOnly': False,'HostOnly': False,'Secure': False}#print(cookie_dict)browser.add_cookie(cookie_dict)sleep(1)browser.get('https://weibo.com/login.php')登錄后的頁(yè)面如下圖
?
2.3搜索內(nèi)容并且爬取
這時(shí)候需要在左上角的搜索框輸入自己需要搜索的用戶,然后通過按回車來實(shí)現(xiàn)搜索
?得到新的頁(yè)面里可以看到最上方會(huì)顯示相關(guān)的賬戶,找到相關(guān)元素并點(diǎn)擊即可
最后進(jìn)入到用戶的完整頁(yè)面
這時(shí)侯就可以開始爬取用戶的微博信息和評(píng)論了。由于微博的內(nèi)容是動(dòng)態(tài)加載的,通過F12可以看到一開始是僅展示六條內(nèi)容的元素
通過滑動(dòng),元素會(huì)逐漸增加,但是上限是12個(gè),并且后面會(huì)出現(xiàn)元素順序和微博內(nèi)容順序不符的情況。如果單單爬取微博的內(nèi)容,不爬評(píng)論那還好,只需要定位到每一個(gè)元素塊,獲取其內(nèi)部的text文本然后處理一下就可以獲得自己想要的信息。但是由于還要爬取相應(yīng)的評(píng)論內(nèi)容,并且評(píng)論還要和微博內(nèi)容相對(duì)應(yīng),所以不能直接進(jìn)行爬取。
這里我選擇微博內(nèi)容里的時(shí)間元素里的href
?
?通過點(diǎn)擊這個(gè)a標(biāo)簽,可以跳轉(zhuǎn)到該條微博的詳情頁(yè)面
這時(shí)候就可以分塊爬起微博的內(nèi)容以及轉(zhuǎn)發(fā)數(shù)、評(píng)論數(shù)、點(diǎn)贊數(shù)和評(píng)論的內(nèi)容了。要注意的是這里的轉(zhuǎn)發(fā)數(shù)評(píng)論數(shù)這些可能存在多個(gè),比如此圖里是轉(zhuǎn)發(fā)他人微博,他人微博里也有轉(zhuǎn)發(fā)數(shù)這些。還有就是評(píng)論的內(nèi)容有可能是開啟精選后的,和普通的評(píng)論內(nèi)容要做判斷。?爬取完微博內(nèi)容和評(píng)論后點(diǎn)擊上方的返回按鈕,回到之前的頁(yè)面。
hrefs = []# 搜索內(nèi)容 def search(username):# 等待元素出現(xiàn)再進(jìn)行下一步WebDriverWait(browser, 15).until(EC.presence_of_element_located((By.CLASS_NAME, "woo-pop-ctrl")))# 獲取搜索框元素searchinput = browser.find_element(By.CLASS_NAME, 'woo-input-main')# 將要搜索的內(nèi)容寫入搜索框searchinput.send_keys(username)# 等待0.5秒后按回車sleep(0.2)searchinput.send_keys(Keys.ENTER)# 轉(zhuǎn)移句柄到新的頁(yè)面new_window = browser.window_handles[-1]# 關(guān)閉原來的頁(yè)面browser.close()# 窗口轉(zhuǎn)移到新的頁(yè)面browser.switch_to.window(new_window)# 等待WebDriverWait(browser, 15).until(EC.presence_of_element_located((By.CLASS_NAME, "card-wrap")))# 定位用戶微博頭像并點(diǎn)擊weibo = browser.find_element(By.XPATH, '//div[@class="card card-user-b s-brt1 card-user-b-padding"]/div/a')weibo.click()new_window = browser.window_handles[-1]browser.switch_to.window(new_window)WebDriverWait(browser, 15).until(EC.presence_of_element_located((By.CLASS_NAME, "vue-recycle-scroller__item-view")))# 微博一次最多給12條內(nèi)容的元素,并且給出的元素不保證順序。# 所以第一次進(jìn)入頁(yè)面的時(shí)候獲取所有的內(nèi)容元素,a標(biāo)簽里的href唯一,所以將其提取出來for t in range(3):a = browser.find_elements(By.XPATH, '//div[@class="woo-box-item-flex head_main_3DRDm"]/div/div[2]/a')# 在獲取到的列表里進(jìn)行篩選,已經(jīng)爬取過的微博就跳過for i in range(len(a)):if a[i].get_attribute("href") in hrefs:print("已經(jīng)搜索過")continueelse:print("還沒搜索過")# 每次都向下滑動(dòng)400像素,大致符合一條微博的高度changepage(400)# sleep(0.5)newpage = a[i].get_attribute("href")# 打印hrefprint(newpage)hrefs.append(newpage)# print(comments)# 打印已經(jīng)搜索的微博內(nèi)容數(shù)print(len(hrefs))# 使用js腳本來點(diǎn)擊元素,否則可能出現(xiàn)元素不在網(wǎng)頁(yè)上,無法交互的報(bào)錯(cuò)# a[i].click()browser.execute_script("arguments[0].click();", a[i])# 不要直接用href去請(qǐng)求,否則點(diǎn)擊返回的時(shí)候會(huì)直接回到微博首頁(yè)面# browser.get(newpage)sleep(0.5)# 爬取具體內(nèi)容頁(yè)面的內(nèi)容和評(píng)論findall()sleep(0.2)# 找到返回按鈕并點(diǎn)擊WebDriverWait(browser, 15).until(EC.presence_of_element_located((By.XPATH,'//div[@class="woo-box-flex woo-box-alignCenter Bar_left_2J3kl Bar_hand_2VAG1"]/i')))back = browser.find_element(By.XPATH,'//div[@class="woo-box-flex woo-box-alignCenter Bar_left_2J3kl Bar_hand_2VAG1"]/i')back.click()?
text = []# 將頁(yè)面向下滑動(dòng)px像素 def changepage(px):browser.execute_script("window.scrollBy(0, {})".format(px))# 爬取微博的內(nèi)容和評(píng)論 def findall():# 等待頁(yè)面元素加載WebDriverWait(browser, 15).until(EC.presence_of_element_located((By.CLASS_NAME, "Feed_body_3R0rO")))body = browser.find_element(By.CLASS_NAME, 'Feed_body_3R0rO')# 通過換行來劃分內(nèi)容bodytext = body.text.split("\n")print(bodytext)# 找到轉(zhuǎn)發(fā)評(píng)論點(diǎn)贊的元素,但是如果有微博內(nèi)容為轉(zhuǎn)發(fā)他人的微博,則存在兩個(gè)footer元素,# 所以尋找多個(gè),然后取最后那一個(gè)footer = browser.find_elements(By.TAG_NAME, 'footer')footertext = footer[-1].text.split("\n")print(footertext[1])WebDriverWait(browser, 15).until(EC.presence_of_element_located((By.CLASS_NAME, "Detail_box_3Jeom")))try:prompt = browser.find_element(By.CLASS_NAME, "RepostCommentList_tip_2O5W-")print(prompt.text)t = Falseexcept:t = Trueprint(t)while t:try:browser.find_element(By.XPATH, '//div[@class="Bottom_text_1kFLe"]')t = Falseexcept:t = TrueWebDriverWait(browser, 15).until(EC.presence_of_element_located((By.XPATH, '//div[@class="vue-recycle-scroller__item-wrapper"]')))pagecomment = browser.find_elements(By.XPATH, '//div[@class="vue-recycle-scroller__item-view"]')for i in pagecomment:comment = i.text.split("\n")if comment in text:continueelse:print(comment)text.append(comment)sleep(0.1)changepage(600)?最后爬取內(nèi)容和評(píng)論的總的代碼如下:
from selenium import webdriver from time import sleep import json from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.common.by import By from selenium.webdriver.common.keys import Keystext = [] hrefs = []# 打開瀏覽器,進(jìn)入到微博登錄頁(yè)面 def browser_initial():browser = webdriver.Chrome()browser.maximize_window()browser.get('https://weibo.com/login.php')return browser# 將已經(jīng)登錄獲得的cookie寫入,實(shí)現(xiàn)自動(dòng)登錄 def log_csdn(browser):with open('微博_cookies.txt', 'r', encoding='utf8') as f:listCookies = json.loads(f.read())# 往browser里添加cookiesfor cookie in listCookies:cookie_dict = {'domain': '.weibo.com','name': cookie.get('name'),'value': cookie.get('value'),"expires": '','path': '/','httpOnly': False,'HostOnly': False,'Secure': False}#print(cookie_dict)browser.add_cookie(cookie_dict)sleep(1)browser.get('https://weibo.com/login.php')#print(browser.get_cookies())#browser.refresh() # 刷新網(wǎng)頁(yè),cookies才成功# 搜索內(nèi)容 def search(username):# 等待元素出現(xiàn)再進(jìn)行下一步WebDriverWait(browser, 15).until(EC.presence_of_element_located((By.CLASS_NAME, "woo-pop-ctrl")))# 獲取搜索框元素searchinput = browser.find_element(By.CLASS_NAME, 'woo-input-main')# 將要搜索的內(nèi)容寫入搜索框searchinput.send_keys(username)# 等待0.5秒后按回車sleep(0.2)searchinput.send_keys(Keys.ENTER)# 轉(zhuǎn)移句柄到新的頁(yè)面new_window = browser.window_handles[-1]# 關(guān)閉原來的頁(yè)面browser.close()# 窗口轉(zhuǎn)移到新的頁(yè)面browser.switch_to.window(new_window)# 等待WebDriverWait(browser, 15).until(EC.presence_of_element_located((By.CLASS_NAME, "card-wrap")))# 定位用戶微博頭像并點(diǎn)擊weibo = browser.find_element(By.XPATH, '//div[@class="card card-user-b s-brt1 card-user-b-padding"]/div/a')weibo.click()new_window = browser.window_handles[-1]browser.switch_to.window(new_window)WebDriverWait(browser, 15).until(EC.presence_of_element_located((By.CLASS_NAME, "vue-recycle-scroller__item-view")))# 微博一次最多給12條內(nèi)容的元素,并且給出的元素不保證順序。# 所以第一次進(jìn)入頁(yè)面的時(shí)候獲取所有的內(nèi)容元素,a標(biāo)簽里的href唯一,所以將其提取出來for t in range(3):a = browser.find_elements(By.XPATH, '//div[@class="woo-box-item-flex head_main_3DRDm"]/div/div[2]/a')# 在獲取到的列表里進(jìn)行篩選,已經(jīng)爬取過的微博就跳過for i in range(len(a)):if a[i].get_attribute("href") in hrefs:print("已經(jīng)搜索過")continueelse:print("還沒搜索過")# 每次都向下滑動(dòng)400像素,大致符合一條微博的高度changepage(400)# sleep(0.5)newpage = a[i].get_attribute("href")# 打印hrefprint(newpage)hrefs.append(newpage)# print(comments)# 打印已經(jīng)搜索的微博內(nèi)容數(shù)print(len(hrefs))# 使用js腳本來點(diǎn)擊元素,否則可能出現(xiàn)元素不在網(wǎng)頁(yè)上,無法交互的報(bào)錯(cuò)# a[i].click()browser.execute_script("arguments[0].click();", a[i])# 不要直接用href去請(qǐng)求,否則點(diǎn)擊返回的時(shí)候會(huì)直接回到微博首頁(yè)面# browser.get(newpage)sleep(0.5)# 爬取具體內(nèi)容頁(yè)面的內(nèi)容和評(píng)論findall()sleep(0.2)# 找到返回按鈕并點(diǎn)擊WebDriverWait(browser, 15).until(EC.presence_of_element_located((By.XPATH,'//div[@class="woo-box-flex woo-box-alignCenter Bar_left_2J3kl Bar_hand_2VAG1"]/i')))back = browser.find_element(By.XPATH,'//div[@class="woo-box-flex woo-box-alignCenter Bar_left_2J3kl Bar_hand_2VAG1"]/i')back.click()# 將頁(yè)面向下滑動(dòng)px像素 def changepage(px):browser.execute_script("window.scrollBy(0, {})".format(px))# 爬取微博的內(nèi)容和評(píng)論 def findall():# 等待頁(yè)面元素加載WebDriverWait(browser, 15).until(EC.presence_of_element_located((By.CLASS_NAME, "Feed_body_3R0rO")))body = browser.find_element(By.CLASS_NAME, 'Feed_body_3R0rO')# 通過換行來劃分內(nèi)容bodytext = body.text.split("\n")print(bodytext)# 找到轉(zhuǎn)發(fā)評(píng)論點(diǎn)贊的元素,但是如果有微博內(nèi)容為轉(zhuǎn)發(fā)他人的微博,則存在兩個(gè)footer元素,# 所以尋找多個(gè),然后取最后那一個(gè)footer = browser.find_elements(By.TAG_NAME, 'footer')footertext = footer[-1].text.split("\n")print(footertext[1])WebDriverWait(browser, 15).until(EC.presence_of_element_located((By.CLASS_NAME, "Detail_box_3Jeom")))try:prompt = browser.find_element(By.CLASS_NAME, "RepostCommentList_tip_2O5W-")print(prompt.text)t = Falseexcept:t = Trueprint(t)while t:try:browser.find_element(By.XPATH, '//div[@class="Bottom_text_1kFLe"]')t = Falseexcept:t = TrueWebDriverWait(browser, 15).until(EC.presence_of_element_located((By.XPATH, '//div[@class="vue-recycle-scroller__item-wrapper"]')))pagecomment = browser.find_elements(By.XPATH, '//div[@class="vue-recycle-scroller__item-view"]')for i in pagecomment:comment = i.text.split("\n")if comment in text:continueelse:print(comment)text.append(comment)sleep(0.1)changepage(600)if __name__ == "__main__":# 打開瀏覽器進(jìn)入微博登錄頁(yè)面browser = browser_initial()# 使用cookie登錄微博log_csdn(browser)# 爬取相關(guān)用戶的評(píng)論search("杭州地鐵")里面的數(shù)據(jù)處理還沒做,大家可以自己打印出來后根據(jù)自己的需要進(jìn)行處理。
總結(jié)
以上是生活随笔為你收集整理的使用selenium自动化工具爬取微博内容和评论的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: AngularJS-模块化
- 下一篇: Java程序员常用网站