爬取新浪微博網站

今天我們來使用 Selenium 爬取動態網頁,以新浪微博網站爲例。我們需要分以下三步進行爬取:

  1. 登錄新浪微博網站
  2. 解析微博網站頁面
  3. 定時重新打開微博首頁,爬取最新發布的微博或者拉動滾動條爬取更多以前的微博

代碼如下

# -*- 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 算法計算摘要之前,需要將字符串編碼爲二進制形式。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章