【洞幺邦】Python爬取指定微博用戶所有內(nèi)容
通過Python爬取微博指定用戶的所有內(nèi)容,下面帶領(lǐng)大家一步一步爬取微博用戶(以微博用戶:https://weibo.com/u/6175460875 為例子)的所有微博內(nèi)容。運(yùn)行環(huán)境如下:電腦系統(tǒng):Windows10,Python版本:3.8,IDE:Pycharm2020.1,瀏覽器:谷歌瀏覽器。爬蟲程序最后一次測試時(shí)間為2021年6月21日。
下面我們分步驟講述爬取和分析處理過程,想跟著我學(xué)技術(shù)的可以一起看看,想使用代碼的可以直接跳到最后復(fù)制我的代碼。
**1. 使用瀏覽器獲取請(qǐng)求頭部信息**
打開谷歌瀏覽器并且訪問https://weibo.com/u/6175460875(其他微博頁面也可以),按F12打開開發(fā)者工具箱,如圖所示步驟復(fù)制Cookie和User-Agent信息留著備用:
我獲取到的信息是:
```c
"Cookie":"SUB=_2AkMXjLNHf8NxqwJRmfoRzWPmaox3zAzEieKh0EKcJRMxHRl-yT9jqn0ntRB6PAydqHF_kMSfPUJZ_Z3jMWJIHBy6j19j; SUBP=0033WrSXqPxfM72-Ws9jqgMF55529P9D9WWmnxcrYjVlNsejfucT6rxp; _s_tentry=passport.weibo.com; Apache=8321982383917.372.1624259696759; SINAGLOBAL=8321982383917.372.1624259696759; ULV=1624259696790:1:1:1:8321982383917.372.1624259696759:"
```
```c
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36 Edg/91.0.864.54"
```
**2. **獲取用戶主頁網(wǎng)頁源碼****
在這里我們使用的是urllib.request模塊來獲取源碼,注意,使用Python獲取源碼時(shí),需要進(jìn)行適當(dāng)偽裝,否則對(duì)方服務(wù)器會(huì)以為我們是爬蟲程序而返回一個(gè)無用信息,偽裝的方法就是把Python爬蟲程序的請(qǐng)求頭部信息改成第一步從瀏覽器獲取到的請(qǐng)求頭部信息,我們直接封裝一個(gè)函數(shù)用來獲取網(wǎng)頁源碼:
```python
def getHttpCode(url, coding="utf-8", method="GET"):
#獲取網(wǎng)頁源碼的函數(shù),傳入的url為地址
import urllib.parse
import urllib.request
data = bytes(urllib.parse.urlencode({"name": "Ningbei"}), encoding=coding)
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36 Edg/91.0.864.54",
"Cookie":"SUB=_2AkMXjLNHf8NxqwJRmfoRzWPmaox3zAzEieKh0EKcJRMxHRl-yT9jqn0ntRB6PAydqHF_kMSfPUJZ_Z3jMWJIHBy6j19j; SUBP=0033WrSXqPxfM72-Ws9jqgMF55529P9D9WWmnxcrYjVlNsejfucT6rxp; _s_tentry=passport.weibo.com; Apache=8321982383917.372.1624259696759; SINAGLOBAL=8321982383917.372.1624259696759; ULV=1624259696790:1:1:1:8321982383917.372.1624259696759:"
}
response = urllib.request.Request(url=url, data=data, headers=headers, method=method)
response = urllib.request.urlopen(response).read().decode(coding)
return response
```
3.**通過網(wǎng)頁源碼獲取用戶信息**
```python
print(getHttpCode("https://weibo.com/u/6175460875"))#輸出獲取到的源碼
```
獲取到的網(wǎng)頁源碼太長我就不全發(fā)出來了,只發(fā)有用部分進(jìn)項(xiàng)講解。
在源碼前面可以看到頁面信息,后續(xù)步驟中需要用到的信息是oid(用uid變量保存),domain(用同名變量保存),page_id(用pageid變量保存),我們使用正則表達(dá)式可以把這些信息讀取出來,封裝一個(gè)getUserInfo函數(shù)來獲取上述信息,函數(shù)返回一個(gè)包含用戶信息的字典。
```python
def getUserInfo(url):
# 獲取用戶id等信息
import re
result = getHttpCode(url)
domain = re.findall("\$CONFIG\['domain'\]='([0-9]+)';", result, re.DOTALL)
uid = re.findall("\$CONFIG\['oid'\]='([0-9]+)';", result, re.DOTALL)
pageid = domain[0] + uid[0]#觀察網(wǎng)頁源碼發(fā)現(xiàn),pageid就是domain和uid拼接得來
result = {'uid': uid[0], 'pageid': pageid, 'domain': domain[0]}
return result
```
**4. **分析網(wǎng)頁源碼,提取有效數(shù)據(jù)****
正常情況下,未登錄的用戶只能看到第一頁的數(shù)據(jù),通過小編的長時(shí)間分析,得出以下重要結(jié)論,可以在未登錄情況下獲取所有信息(分析過程比較復(fù)雜,略):有效獲取微博的內(nèi)容地址:https://weibo.com/p/aj/v6/mblog/mbloglist?
微博內(nèi)容分多頁顯示,同一頁(page)會(huì)分3次顯示,需提交3個(gè)ajax請(qǐng)求,每個(gè)請(qǐng)求包含domain,id,ajwvr,pagebar,page,pre_page共6個(gè)參數(shù)才能抓取完整,domain,id,ajwvr為固定值(同一個(gè)用戶)參數(shù),其他參數(shù)規(guī)律如下:
當(dāng)當(dāng)前頁面為第i頁時(shí),page=i;
第i頁第一部分的頁面參數(shù)為pagebar=0,pre_page=i-1
第i頁第二部分頁面參數(shù)為pagebar=0,page=i,pre_page=i
第i頁第三部分頁面參數(shù)為pagebar=1,page=i,pre_page=i
例如訪問第2頁第2部分的數(shù)據(jù)則提交鏈接:https://weibo.com/p/aj/v6/mblog/mbloglist?ajwvr=6&domain=100505&id=1005055705886600&pagebar=0&page=1&pre_page=1
服務(wù)器返回的結(jié)果是json格式的數(shù)據(jù),我們使用json.loads函數(shù)解析得到一個(gè)字典,字典里面 ‘data’的值就是http代碼,再使用BeautifulSoup模塊進(jìn)行解析,即可得到一個(gè)列表,里面是微博內(nèi)容信息。代碼如下:
```python
def getData(url):
#url='https://weibo.com/p/aj/v6/mblog/mbloglist?ajwvr=6&domain=100505&id=1005055705886600&pagebar=0&page=1&pre_page=1'
import re
import json
from bs4 import BeautifulSoup
result = getHttpCode(url)
result = json.loads(result)
result = result['data']
soup = BeautifulSoup(result, "html.parser")
soup = soup.find_all(class_='WB_text W_f14')
result = []
for i in soup:
if i['node-type'] == 'feed_list_content':
res = re.sub("<.*?>", "", str(i)).strip()
result.append(res)
return result
```
運(yùn)行結(jié)果如下:
**5.整合數(shù)據(jù)**
這步比較簡單,直接上代碼:
```python
def getResult(url):
#爬取指定微博用戶所有內(nèi)容核心函數(shù),url為微博用戶主頁鏈接
url = url.split("?")[0]
userInfo=getUserInfo(url)
base='https://weibo.com/p/aj/v6/mblog/mbloglist?ajwvr=6&domain={}&id={}'.format(userInfo['domain'], userInfo['pageid'] )
result=[];
for page in range(10):
#當(dāng)期循環(huán)是獲取微博用戶前10頁的所有數(shù)據(jù),獲取多少頁就改成多大的值即可(數(shù)據(jù)過大也沒問題,系統(tǒng)沒有爬取到內(nèi)容會(huì)自動(dòng)退出循環(huán)的。)
list=getData(base + "&pagebar=0&page=" + str(page + 1) + "&pre_page=" + str(page))
if len(list)==0:
#list為空表示已經(jīng)沒有可爬取的內(nèi)容了,直接break
break
result.extend(list)
result.extend(getData(base + "&pagebar=0&page=" + str(page + 1) + "&pre_page=" + str(page+1)))
result.extend(getData(base + "&pagebar=1&page=" + str(page + 1) + "&pre_page=" + str(page+1)))
return result
```
到了第5步就已經(jīng)完成爬取了,返回的是一個(gè)列表,列表內(nèi)容就是指定用戶的微博內(nèi)容。下面我們把所有代碼整合在一起如下:
```python
# -*- coding=utf-8 -*-
import re
import json
import urllib.request
import urllib.parse
from bs4 import BeautifulSoup
def getHttpCode(url, coding="utf-8", method="GET"):
#獲取網(wǎng)頁源碼
data = bytes(urllib.parse.urlencode({"name": "Ningbei"}), encoding=coding)
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36 Edg/91.0.864.54",
"Cookie":"SUB=_2AkMXjLNHf8NxqwJRmfoRzWPmaox3zAzEieKh0EKcJRMxHRl-yT9jqn0ntRB6PAydqHF_kMSfPUJZ_Z3jMWJIHBy6j19j; SUBP=0033WrSXqPxfM72-Ws9jqgMF55529P9D9WWmnxcrYjVlNsejfucT6rxp; _s_tentry=passport.weibo.com; Apache=8321982383917.372.1624259696759; SINAGLOBAL=8321982383917.372.1624259696759; ULV=1624259696790:1:1:1:8321982383917.372.1624259696759:"
}
response = urllib.request.Request(url=url, data=data, headers=headers, method=method)
response = urllib.request.urlopen(response).read().decode(coding)
return response
def getUserInfo(url):
#獲取用戶id等信息
result = getHttpCode(url)
domain=re.findall("\$CONFIG\['domain'\]='([0-9]+)';",result,re.DOTALL)
uid=re.findall("\$CONFIG\['oid'\]='([0-9]+)';",result,re.DOTALL)
pageid=domain[0]+uid[0]
result={'uid': uid[0], 'pageid': pageid, 'domain': domain[0]}
return result
def getData(url):
result = getHttpCode(url)
result = json.loads(result)
result = result['data']
soup = BeautifulSoup(result, "html.parser")
soup = soup.find_all(class_='WB_text W_f14')
result = []
for i in soup:
if i['node-type'] == 'feed_list_content':
res = re.sub("<.*?>", "", str(i)).strip()
result.append(res)
return result
def getResult(url):
#爬取指定微博用戶所有內(nèi)容核心函數(shù),url為微博用戶主頁鏈接
url = url.split("?")[0]
userInfo=getUserInfo(url)
base='https://weibo.com/p/aj/v6/mblog/mbloglist?ajwvr=6&domain={}&id={}'.format(userInfo['domain'], userInfo['pageid'] )
result=[];
for page in range(10):
#同一頁(page)會(huì)分3次顯示,需提交三個(gè)請(qǐng)求才能抓取完整,domain,id,ajwvr為固定參數(shù),當(dāng)當(dāng)前頁面為第i頁時(shí),page=i;第i頁第一部分的頁面參數(shù)為pagebar=0,page=i,pre_page=i-1,第i頁第二部分頁面參數(shù)為pagebar=0,page=i,pre_page=i,第i頁第三部分頁面參數(shù)為pagebar=1,page=i,pre_page=i
list=getData(base + "&pagebar=0&page=" + str(page + 1) + "&pre_page=" + str(page))
if len(list)==0:
#list為空表示已經(jīng)沒有可爬取的內(nèi)容了,直接break
break
result.extend(list)
result.extend(getData(base + "&pagebar=0&page=" + str(page + 1) + "&pre_page=" + str(page+1)))
result.extend(getData(base + "&pagebar=1&page=" + str(page + 1) + "&pre_page=" + str(page+1)))
return result
def main():
result=getResult("https://weibo.com/u/6175460875")
for i in result:
print(i)
print("-"*200)
print("前10頁(需要爬取更全數(shù)據(jù)去修改getResult函數(shù)里面for循環(huán)的范圍)共"+str(len(result))+"條微博")
main()
```
*博客內(nèi)容為網(wǎng)友個(gè)人發(fā)布,僅代表博主個(gè)人觀點(diǎn),如有侵權(quán)請(qǐng)聯(lián)系工作人員刪除。