Python自动化爬取微博用户相册图片实战指南
1. 准备工作:理解微博相册爬取的核心逻辑
微博相册爬取本质上是通过模拟浏览器行为,向微博服务器发送请求并解析返回的数据。这里有几个关键点需要理解:
首先,微博的相册数据是通过AJAX接口动态加载的,这意味着我们无法直接从网页源代码中获取图片链接。你需要找到微博用于加载相册数据的API接口。经过实测,https://weibo.com/ajax/profile/getImageWall这个接口就是我们要找的。
其次,微博采用了分页加载机制。每页最多显示20张图片,通过since_id参数控制分页。这个机制类似于翻书:你读完一页(获取20张图片),系统会告诉你下一页的标记(since_id),然后你用这个标记去获取下一页内容。
最后,微博图片有特殊的存储规则。每张图片都有一个唯一的pid(图片ID),通过这个pid可以构造出实际的图片URL。常见的格式是https://wx1.sinaimg.cn/large/{pid}.jpg,其中wx1可能根据图片服务器不同而变化。
2. 环境搭建与依赖安装
在开始编码前,我们需要准备好Python环境。我推荐使用Python 3.8或以上版本,因为这个版本的兼容性最好,各种库的支持也最完善。
首先安装必要的依赖库:
pip install requests
requests库是Python中最常用的HTTP请求库,相比urllib更加简单易用。它可以帮助我们发送HTTP请求和处理响应。
为了验证安装是否成功,可以打开Python解释器输入:
import requests
print(requests.__version__)
如果没有报错并显示版本号,说明安装成功。
3. 获取微博用户UID的三种方法
UID是微博用户的唯一标识符,是爬取相册的必要参数。这里分享三种获取UID的方法:
第一种是通过网页端直接查看。打开目标用户的微博主页,查看网页地址栏。例如:https://weibo.com/u/123456789,其中的123456789就是UID。
第二种方法适用于手机端。在微博APP中打开用户主页,点击右上角的"..."按钮,选择"复制链接",你会得到一个类似https://m.weibo.cn/u/123456789的链接,其中的数字就是UID。
第三种方法是通过开发者工具。在网页端按F12打开开发者工具,切换到Network(网络)选项卡,刷新页面,在请求列表中找到包含用户信息的请求,通常在响应数据中能找到uid字段。
4. 构建爬虫核心代码
现在我们来构建爬虫的核心部分。首先需要设置请求头,这是模拟浏览器行为的关键:
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36',
'Cookie': '你的微博cookie'
}
获取cookie的方法:登录微博网页版后,按F12打开开发者工具,在Application > Cookies中找到微博的cookie,复制整个字符串。
接下来是获取since_id的函数,这个参数用于分页控制:
def get_sinceid(url):
resp_json = requests.get(url, headers=headers).json()
return resp_json['data']['since_id']
然后是获取图片pid列表的函数:
def get_pids(url):
resp_json = requests.get(url, headers=headers).json()
return [d['pid'] for d in resp_json['data']['list']]
5. 图片下载与存储管理
获取到图片pid后,我们需要构造实际的图片URL并下载。这里有几个注意事项:
首先,微博图片有不同的大小规格,通过在pid前添加不同前缀实现。例如:
- 缩略图:
https://wx1.sinaimg.cn/thumb150/{pid}.jpg - 中等大小:
https://wx1.sinaimg.cn/mw690/{pid}.jpg - 原图:
https://wx1.sinaimg.cn/large/{pid}.jpg
建议下载原图,所以使用large前缀。
下载图片的函数如下:
def download_img(img_urls, save_dir='weibo_images'):
if not os.path.exists(save_dir):
os.makedirs(save_dir)
for img_url in img_urls:
try:
response = requests.get(img_url, headers=headers, stream=True)
if response.status_code == 200:
filename = os.path.join(save_dir, img_url.split('/')[-1])
with open(filename, 'wb') as f:
for chunk in response.iter_content(1024):
f.write(chunk)
print(f'下载成功: {filename}')
else:
print(f'下载失败: {img_url}')
except Exception as e:
print(f'下载出错: {e}')
这个函数使用了流式下载,可以避免大文件占用过多内存。同时加入了异常处理,使程序更加健壮。
6. 完整爬虫实现与分页控制
现在我们把所有部分组合起来,实现完整的爬虫功能:
import requests
import os
def main():
uid = input('请输入微博用户UID: ')
pages = int(input('请输入要爬取的页数(每页最多20张): '))
save_dir = f'weibo_images_{uid}'
base_url = f'https://weibo.com/ajax/profile/getImageWall?uid={uid}&sinceid=0&has_album=true'
since_id = 0
for page in range(1, pages + 1):
try:
# 获取当前页的图片pid
pids = get_pids(base_url)
if not pids:
print(f'第{page}页没有图片,停止爬取')
break
# 构造图片URL并下载
img_urls = [f'https://wx1.sinaimg.cn/large/{pid}.jpg' for pid in pids]
download_img(img_urls, save_dir)
# 获取下一页的since_id
since_id = get_sinceid(base_url)
if since_id == 0:
print('已到达最后一页,停止爬取')
break
# 更新base_url用于下一页
base_url = f'https://weibo.com/ajax/profile/getImageWall?uid={uid}&sinceid={since_id}&has_album=true'
print(f'第{page}页下载完成')
except Exception as e:
print(f'第{page}页处理出错: {e}')
break
if __name__ == '__main__':
main()
这个脚本会循环爬取指定页数的图片,直到达到指定页数或者没有更多图片为止。每次请求都会更新since_id,确保能获取到下一页的数据。
7. 常见问题与解决方案
在实际使用中,你可能会遇到以下问题:
-
请求被拒绝(403错误) 这通常是因为请求头不够完善或者cookie失效。解决方案:
- 更新cookie
- 添加更多请求头字段,如Referer
- 添加请求延迟,避免频率过高
-
获取的图片数量少于预期 微博相册可能有隐私设置,部分图片需要登录才能查看。确保:
- 使用有效的cookie
- 检查目标相册是否为公开可见
-
下载的图片损坏 可能是网络问题导致下载不完整。可以:
- 增加重试机制
- 验证下载文件的完整性
-
被封IP 如果请求太频繁,可能会触发微博的反爬机制。建议:
- 在请求间添加随机延迟
- 使用代理IP(需谨慎合规使用)
8. 优化与扩展建议
如果你需要更强大的爬虫,可以考虑以下优化:
-
多线程下载 使用concurrent.futures模块实现并行下载,大幅提高效率:
from concurrent.futures import ThreadPoolExecutor def download_all(img_urls, save_dir, max_workers=5): with ThreadPoolExecutor(max_workers=max_workers) as executor: executor.map(lambda url: download_img([url], save_dir), img_urls) -
断点续爬 将已经下载的图片记录到文件,程序重启后可以继续未完成的部分。
-
图片去重 使用hash算法检查图片内容,避免重复下载相同图片。
-
元数据保存 除了图片本身,还可以保存图片的发布时间、描述等信息,方便后续分析。
-
图形界面 使用PyQt或Tkinter为脚本添加图形界面,使其更易用。
在实际项目中,我发现合理设置请求间隔(如3-5秒)和良好的异常处理是保证爬虫稳定运行的关键。另外,建议将配置信息(如cookie、保存路径等)单独放在配置文件中,方便维护。
更多推荐


所有评论(0)