打印
[技术讨论]

【洞幺邦】Python爬取指定微博用户所有内容

[复制链接]
1618|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
#申请原创# 通过Python爬取微博指定用户的所有内容,下面带领大家一步一步爬取微博用户(以微博用户:https://weibo.com/u/6175460875 为例子)的所有微博内容。运行环境如下:电脑系统:Windows10,Python版本:3.8,IDE:Pycharm2020.1,浏览器:谷歌浏览器。爬虫程序最后一次测试时间为2021年6月21日。
下面我们分步骤讲述爬取和分析处理过程,想跟着我学技术的可以一起看看,想使用代码的可以直接跳到最后复制我的代码。

**1. 使用浏览器获取请求头部信息**
       
打开谷歌浏览器并且访问https://weibo.com/u/6175460875(其他微博页面也可以),按F12打开开发者工具箱,如图所示步骤复制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. **获取用户主页网页源码****

在这里我们使用的是urllib.request模块来获取源码,注意,使用Python获取源码时,需要进行适当伪装,否则对方服务器会以为我们是爬虫程序而返回一个无用信息,伪装的方法就是把Python爬虫程序的请求头部信息改成第一步从浏览器获取到的请求头部信息,我们直接封装一个函数用来获取网页源码:
```python

def getHttpCode(url, coding="utf-8", method="GET"):
    #获取网页源码的函数,传入的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.**通过网页源码获取用户信息**


```python
print(getHttpCode("https://weibo.com/u/6175460875"))#输出获取到的源码
```

获取到的网页源码太长我就不全发出来了,只发有用部分进项讲解。

在源码前面可以看到页面信息,后续步骤中需要用到的信息是oid(用uid变量保存),domain(用同名变量保存),page_id(用pageid变量保存),我们使用正则表达式可以把这些信息读取出来,封装一个getUserInfo函数来获取上述信息,函数返回一个包含用户信息的字典。


```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]#观察网页源码发现,pageid就是domain和uid拼接得来
    result = {'uid': uid[0], 'pageid': pageid, 'domain': domain[0]}
    return result
```


**4. **分析网页源码,提取有效数据****
正常情况下,未登录的用户只能看到第一页的数据,通过小编的长时间分析,得出以下重要结论,可以在未登录情况下获取所有信息(分析过程比较复杂,略):有效获取微博的内容地址:https://weibo.com/p/aj/v6/mblog/mbloglist?

微博内容分多页显示,同一页(page)会分3次显示,需提交3个ajax请求,每个请求包含domain,id,ajwvr,pagebar,page,pre_page共6个参数才能抓取完整,domain,id,ajwvr为固定值(同一个用户)参数,其他参数规律如下:

当当前页面为第i页时,page=i;
第i页第一部分的页面参数为pagebar=0,pre_page=i-1
第i页第二部分页面参数为pagebar=0,page=i,pre_page=i
第i页第三部分页面参数为pagebar=1,page=i,pre_page=i

例如访问第2页第2部分的数据则提交链接:https://weibo.com/p/aj/v6/mblog/mbloglist?ajwvr=6&domain=100505&id=1005055705886600&pagebar=0&page=1&pre_page=1

服务器返回的结果是json格式的数据,我们使用json.loads函数解析得到一个字典,字典里面 ‘data’的值就是http代码,再使用BeautifulSoup模块进行解析,即可得到一个列表,里面是微博内容信息。代码如下:

```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
```

运行结果如下:

**5.整合数据**

这步比较简单,直接上代码:
```python
def getResult(url):
    #爬取指定微博用户所有内容核心函数,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):
        #当期循环是获取微博用户前10页的所有数据,获取多少页就改成多大的值即可(数据过大也没问题,系统没有爬取到内容会自动退出循环的。)
        list=getData(base + "&pagebar=0&page=" + str(page + 1) + "&pre_page=" + str(page))
        if len(list)==0:
                #list为空表示已经没有可爬取的内容了,直接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步就已经完成爬取了,返回的是一个列表,列表内容就是指定用户的微博内容。下面我们把所有代码整合在一起如下:



```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"):
    #获取网页源码
    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):
    #爬取指定微博用户所有内容核心函数,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)会分3次显示,需提交三个请求才能抓取完整,domain,id,ajwvr为固定参数,当当前页面为第i页时,page=i;第i页第一部分的页面参数为pagebar=0,page=i,pre_page=i-1,第i页第二部分页面参数为pagebar=0,page=i,pre_page=i,第i页第三部分页面参数为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为空表示已经没有可爬取的内容了,直接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页(需要爬取更全数据去修改getResult函数里面for循环的范围)共"+str(len(result))+"条微博")

main()

```


使用特权

评论回复

相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

11

主题

11

帖子

1

粉丝