【Python3爬蟲】微博使用者爬蟲
此次爬蟲要實現的是爬取某個微博使用者的關注和粉絲的使用者公開基本資訊,包括使用者暱稱、id、性別、所在地和其粉絲數量,然後將爬取下來的資料儲存在MongoDB資料庫中,最後再生成幾個圖表來簡單分析一下我們得到的資料。
一、具體步驟:
這裡我們選取的爬取站點是https://m.weibo.cn,此站點是微博移動端的站點,我們可以直接檢視某個使用者的微博,比如https://m.weibo.cn/profile/5720474518。
然後檢視其關注的使用者,開啟開發者工具,切換到XHR過濾器,一直下拉列表,就會看到有很多的Ajax請求。這些請求的型別是Get型別,返回結果是Json格式,展開之後就能看到有很多使用者的資訊。
這些請求有兩個引數,containerid和page,通過改變page的數值,我們就能得到更多的請求了。獲取其粉絲的使用者資訊的步驟是一樣的,除了請求的連結不同之外,引數也不同,修改一下就可以了。
由於這些請求返回的結果裡只有使用者的名稱和id等資訊,並沒有包含使用者的性別等基本資料,所以我們點進某個人的微博,然後檢視其基本資料,比如這個,開啟開發者工具,可以找到下面這個請求:
由於這個人的id是6857214856,因此我們可以發現當我們得到一個人的id的時候,就可以構造獲取基本資料的連結和引數了,相關程式碼如下(uid就是使用者的id):
1 uid_str = "230283" + str(uid) 2 url = "https://m.weibo.cn/api/container/getIndex?containerid={}_-_INFO&title=%E5%9F%BA%E6%9C%AC%E8%B5%84%E6%96%99&luicode=10000011&lfid={}&featurecode=10000326".format(uid_str, uid_str) 3 data = { 4 "containerid": "{}_-_INFO".format(uid_str), 5 "title": "基本資料", 6 "luicode": 10000011, 7 "lfid": int(uid_str), 8 "featurecode": 10000326 9 }
然後這個返回的結果也是Json格式,提取起來就很方便,因為很多人的基本資料都不怎麼全,所以我提取了使用者暱稱、性別、所在地和其粉絲數量。而且因為一些賬號並非個人賬號,就沒有性別資訊,對於這些賬號,我選擇將其性別設定為男性。不過在爬取的時候,我發現一個問題,就是當頁數超過250的時候,返回的結果就已經沒有內容了,也就是說這個方法最多隻能爬250頁。對於爬取下來的使用者資訊,全都儲存在MongoDB資料庫中,然後在爬取結束之後,讀取這些資訊並繪製了幾個圖表,分別繪製了男女比例扇形圖、使用者所在地分佈圖和使用者的粉絲數量柱狀圖。
二、主要程式碼:
由於第一頁返回的結果和其他頁返回的結果格式是不同的,所以要分別進行解析,而且因為部分結果的json格式不同,所以可能報錯,因此採用了try...except...把出錯原因打印出來。
爬取第一頁並解析的程式碼如下:
1 def get_and_parse1(url): 2 res = requests.get(url) 3 cards = res.json()['data']['cards'] 4 info_list = [] 5 try: 6 for i in cards: 7 if "title" not in i: 8 for j in i['card_group'][1]['users']: 9 user_name = j['screen_name'] # 使用者名稱 10 user_id = j['id'] # 使用者id 11 fans_count = j['followers_count'] # 粉絲數量 12 sex, add = get_user_info(user_id) 13 info = { 14 "使用者名稱": user_name, 15 "性別": sex, 16 "所在地": add, 17 "粉絲數": fans_count, 18 } 19 info_list.append(info) 20 else: 21 for j in i['card_group']: 22 user_name = j['user']['screen_name'] # 使用者名稱 23 user_id = j['user']['id'] # 使用者id 24 fans_count = j['user']['followers_count'] # 粉絲數量 25 sex, add = get_user_info(user_id) 26 info = { 27 "使用者名稱": user_name, 28 "性別": sex, 29 "所在地": add, 30 "粉絲數": fans_count, 31 } 32 info_list.append(info) 33 if "followers" in url: 34 print("第1頁關注資訊爬取完畢...") 35 else: 36 print("第1頁粉絲資訊爬取完畢...") 37 save_info(info_list) 38 except Exception as e: 39 print(e)
爬取其他頁並解析的程式碼如下:
1 def get_and_parse2(url, data): 2 res = requests.get(url, headers=get_random_ua(), data=data) 3 sleep(3) 4 info_list = [] 5 try: 6 if 'cards' in res.json()['data']: 7 card_group = res.json()['data']['cards'][0]['card_group'] 8 else: 9 card_group = res.json()['data']['cardlistInfo']['cards'][0]['card_group'] 10 for card in card_group: 11 user_name = card['user']['screen_name'] # 使用者名稱 12 user_id = card['user']['id'] # 使用者id 13 fans_count = card['user']['followers_count'] # 粉絲數量 14 sex, add = get_user_info(user_id) 15 info = { 16 "使用者名稱": user_name, 17 "性別": sex, 18 "所在地": add, 19 "粉絲數": fans_count, 20 } 21 info_list.append(info) 22 if "page" in data: 23 print("第{}頁關注資訊爬取完畢...".format(data['page'])) 24 else: 25 print("第{}頁粉絲資訊爬取完畢...".format(data['since_id'])) 26 save_info(info_list) 27 except Exception as e: 28 print(e)
三、執行結果:
在執行的時候可能會出現各種各樣的錯誤,有的時候返回結果為空,有的時候解析出錯,不過還是能成功爬取大部分資料的,這裡就放一下最後生成的三張圖片吧。
完整程式碼已上傳到GitHub:https://github.com/QAQ112233/WeiBoUsers