今天我們來使用 Selenium 爬取動態網頁,以新浪微博網站爲例。我們需要分以下三步進行爬取:
- 登錄新浪微博網站
- 解析微博網站頁面
- 定時重新打開微博首頁,爬取最新發布的微博或者拉動滾動條爬取更多以前的微博
代碼如下
# -*- coding: utf-8 -*-
# # @Author: lemon
# # @Date: 2019-09-24 16:20
# # @Last Modified by: lemon
# # @Last Modified time: 2019-09-24 19:12
# # @function: 爬取新浪微博網站
from selenium import webdriver
import time
import pandas as pd
import hashlib # 摘要算法(哈希算法)包
# 創建 data 用來存儲
def create_frame():
data = {
'用戶_id': [],
'用戶_url': [],
'微博內容': []
}
return data
# 寫入data
def data_writer(pub_id, pub_url, pub_content):
data['用戶_id'].append(pub_id)
data['用戶_url'].append(pub_url)
data['微博內容'].append(pub_content)
# 保存文件
def data_save():
frame = pd.DataFrame(data)
frame.to_excel('微博用戶數據.xlsx')
# 登錄微博
def login():
driver.get('https://weibo.com')
time.sleep(5)
driver.set_window_size(1920, 1080) # 設置瀏覽器大小
username = driver.find_element_by_xpath('//*[@id="loginname"]') # 用戶名輸入框
username.send_keys('[email protected]') # 發送賬號
password = driver.find_element_by_xpath('//*[@id="pl_login_form"]/div/div[3]/div[2]/div/input') # 密碼輸入框
password.send_keys('sunxusen2020') # 發送密碼
submit = driver.find_element_by_xpath('//*[@id="pl_login_form"]/div/div[3]/div[6]') # 登錄按鈕
print('準備登錄...')
submit.click() # 點擊登錄按鈕
time.sleep(4) # 停止 4s , 確保已成功切入後續頁面
# 抓取頁面
def spider():
driver.get('https://www.weibo.com') # 刷新微博網站首頁
print('已登錄...')
# 先獲取頁面中所有微博代碼段, 然後使用循環從每一段中提取數據
all_weibo = driver.find_elements_by_xpath('//*[@class="WB_feed_detail clearfix"]')
for weibo in all_weibo:
pub_id = weibo.find_elements_by_xpath('div[3]/div[1]/a[1]')[0].text # 解析出微博用戶 id
pub_url = weibo.find_elements_by_xpath('div[3]/div[1]/a[1]')[0].get_attribute('href') # 解析出發佈者 URL
try:
pub_content = weibo.find_elements_by_xpath('div[3]/div[4]')[0].text
except:
print(f'{pub_id} : 無內容')
pub_content = '無內容'
pass
hash_content = hashlib.md5(pub_content.encode('utf-8')).hexdigest() # 計算微博內容的 MD5 值
if hash_content not in is_dup:
print(f'成功抓取 : {pub_id}')
data_writer(pub_id, pub_url, pub_content)
is_dup.add(hash_content)
if __name__ == '__main__':
is_dup = set() # 創建一個空的 set, 用來去重
data = create_frame()
driver = webdriver.Chrome('E:\ChromeDriver\chromedriver.exe')
login()
for i in range(3):
spider()
time.sleep(10)
data_save()
上面的代碼中使用到了去重功能,在我們爬取的過程中,可能會爬取之前已經爬過的數據,此時我們就需要進行去重。我們使用最常見的 set
數據結構進行去重。我們使用微博內容進行去重判斷,可以將爬取到的內容直接加到 set
中,但是由於微博內容一般比較多,直接使用會佔用較大的內存,影響爬蟲效率。下面我們採用摘要算法(又稱哈希算法),它通過一個函數把任意長度的數據轉換爲一個長度固定的數據串。微博內容是一個很長的字符串,使用摘要算法會得到一個固定長度的摘要,如果一段時間後再次爬取到了這條微博,對它使用摘要算法會得到相同的摘要;如果再次爬取的微博內容有變化,計算出的摘要會不同於原始微博的摘要。
下面以最常見的 MD5 摘要算法爲例,計算出一個字符串的 MD5 值。這裏需要導入 hashlib 。hashlib 是一個提供了一些流行的 hash 算法的 Python 標準庫,感興趣的小夥伴可以研究一下。
def MD5_example():
str_md5 = hashlib.md5('life is short you need python'.encode('utf-8')).hexdigest()
print(str_md5)
輸出如下:
注意:在使用 MD5 算法計算摘要之前,需要將字符串編碼爲二進制形式。