微博爬虫流程解析——session的使用
最近,我在一个微博爬虫练手项目中使用到了requests库中的session模块。其实我一开始是不了解这个部分的,原本我将这个任务交给了claude来完成,结果在爬取过程中一直返回432状态码。日志如下:
2025-10-15 14:57:31,295 - crawl4weibo - WARNING - 遇到432错误,等待 4.3 秒后重试...
2025-10-15 14:57:35,636 - crawl4weibo - WARNING - 遇到432错误,等待 5.8 秒后重试...
我试了很多提示词,claude code也给出了多种解决方案,结果就是一直解决不了。后来,我问了kimi,问题居然神奇地解决了,当时的对话记录已经找不到了(我有随时删除对话记录的坏毛病)。虽然现在有llm的帮助,但还是有必要学习一下其中的原理,以免之后遇到类似的问题,还要用大模型抽奖才能解决。
直接发起get请求
import requestsresp = requests.get("https://m.weibo.cn/api/container/getIndex?containerid=1005052656274875", timeout=5)print('status_code: ', resp.status_code)
print('body: ', resp.text)
这段代码运行的结果如下,状态码为432,响应体为空:
status_code: 432
body:
关于这个状态码,HTTP 标准里面似乎没有定义,也就是说,这是微博自己定义或者是业内惯用(这里WhatsApp的错误码,表示请求签名认证失败)的一种做法。
使用session进行请求
我们试一下直接使用requests.session发起请求,看一下cookies里面是否有对应的字段用于鉴权。
from requests import Session
s = Session()
resp = s.get("https://m.weibo.cn/api/container/getIndex?containerid=1005052656274875", timeout=5)print('status_code: ', resp.status_code)
print('cookies: ', s.cookies.get_dict())
print('body: ', resp.text)
我们可以看到,该api端口并不会设置cookies,所以session的cookies字段仍然为空:
status_code: 432
cookies: {}
body:
这个结果在预期内,我们一般不会在获取详细数据的端口来设置cookies,更普遍且合理地做法是:在入口页返回cookies,然后客户端访问后续页面携带该cookies,服务端来进行校验。所以,在get之前,我们加入一行:
r1 = s.get('https://m.weibo.cn/', timeout=5)
print('Set-Cookie: ', r1.headers.get('Set-Cookie'))
不过加上对首页的get之后,返回里面仍然没有包含cookie的内容,这是因为我们先考虑了复杂的情形。大多数情况下,我们最先考虑的是user-agent的设置,服务端通过该字段最容易区分是否来自游览器/爬虫的请求。我们随便加入一个user-agent,来伪装游览器:
default_user_agent = ("Mozilla/5.0 (Linux; Android 13; SM-G9980) ""AppleWebKit/537.36 (KHTML, like Gecko) ""Chrome/112.0.5615.135 Mobile Safari/537.36"
)
此外,我们还需要考虑该api端口的特殊性,这个端口显然不是给用户直接访问的。通常,这些类似直接用来获取json数据的端口,是供前端界面中js脚本来调用之后渲染展示的。而游览器前端js发起的 XHR/Fetch,游览器会自动加上X-Requested-With: XMLHttpRequest,服务端通过该字段也能拦截部分爬虫请求。至此,微博的反爬策略就分析完成了,我们可以得到最终的代码:
from requests import Session
s = Session()default_user_agent = ("Mozilla/5.0 (Linux; Android 13; SM-G9980) ""AppleWebKit/537.36 (KHTML, like Gecko) ""Chrome/112.0.5615.135 Mobile Safari/537.36"
)s.headers.update({"User-Agent": default_user_agent,"X-Requested-With": "XMLHttpRequest",}
)r1 = s.get('https://m.weibo.cn/', timeout=5)
print('Set-Cookie: ', r1.headers.get('Set-Cookie'))resp = s.get("https://m.weibo.cn/api/container/getIndex?containerid=1005052656274875", timeout=5)print('status_code: ', resp.status_code)
print('cookies: ', s.cookies.get_dict())
print('body: ', resp.text)
在get首页后,响应里面包含了set-cookie,这里只展示部分内容,就不占用篇幅了。
Set-Cookie: MLOGIN=0; ****** domain=.weibo.cn; ***
requests.session会自动保存set-cookie里面的内容,并且在本次会话中的所有请求到带上这个cookie,所以非常的方便。
最后,我们获取到了该api的内容:
status_code: 200
cookies: ****
body: {"ok":1,"data":****}
更多实现细节,参考代码库:crawl4weibo。欢迎star,我会一边学习一边完善。
声明:仅供学习参考,请勿用于其他用途。