遭遇请求速率限制时,如何创建粉丝数列并保存已获取数据至CSV?
解决方案:处理请求限制并保留已获取的数据
我来帮你解决这个问题,核心问题在于你当前的代码遇到429错误时只做了一次sleep但没有重新发起请求,而且函数在这种场景下没有返回值,可能导致apply过程中断,无法生成完整的新列。另外代码里还有个小bug:你导入了from time import sleep,却用了time.sleep(1),这会触发NameError。
下面是修正后的完整代码,同时加入了更健壮的错误处理和重试机制:
import requests from bs4 import BeautifulSoup from time import sleep import pandas as pd # 假设你已经导入pandas,因为用到了DataFrame def getFollowerCount(Username, max_retries=3): url = 'https://somewebsite.com' + Username retries = 0 while retries < max_retries: try: # 发起请求 r = requests.get(url) # 触发HTTP错误(比如429、404等)的异常 r.raise_for_status() # 这里替换成你实际解析粉丝数的逻辑 soup = BeautifulSoup(r.text, 'html.parser') # 示例:假设粉丝数在class为follower-count的span标签里 follower_text = soup.find('span', class_='follower-count').text.strip() # 转成数字(处理可能的千位分隔符) follower_count = int(follower_text.replace(',', '')) return follower_count except requests.exceptions.HTTPError as e: if r.status_code == 429: # 指数退避:每次重试等待时间翻倍,避免持续触发限制 wait_time = 2 ** retries print(f"⚠️ 对用户{Username}触发速率限制,{wait_time}秒后重试(第{retries+1}/{max_retries}次)") sleep(wait_time) retries += 1 else: print(f"❌ 获取用户{Username}数据失败:{e}") return None # 失败时返回None,pandas会转为NaN except Exception as e: # 捕获其他异常(比如解析失败、网络超时等) print(f"❌ 处理用户{Username}时出错:{e}") return None # 生成粉丝数列,失败的行会显示NaN df['follower_count'] = df['Username'].apply(getFollowerCount) # 保存数据,已成功获取的粉丝数会被保留 df.to_csv('df.csv', index=False)
关键改进点:
- 指数退避重试:遇到429错误时,每次重试的等待时间翻倍(2^retries),这是处理速率限制的标准做法,比固定sleep更高效,也更不容易触发平台的限制规则。
- 全链路异常捕获:不管是HTTP错误、解析失败还是网络问题,函数都会返回
None(pandas会自动转为NaN),确保apply过程不会中断,新列能顺利生成,已成功的数据完全保留。 - 修复sleep导入错误:统一使用导入的
sleep()函数,避免NameError。
额外优化建议:
- 添加请求头:在
requests.get()里加入headers参数模拟浏览器请求,降低被限制的概率,比如:headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36' } r = requests.get(url, headers=headers) - 中间保存进度:如果处理大量用户,建议分批保存数据,避免中途出错丢失进度:
# 逐行处理并每100个用户保存一次 for idx, username in enumerate(df['Username']): df.loc[idx, 'follower_count'] = getFollowerCount(username) if (idx + 1) % 100 == 0: df.to_csv('df_progress.csv', index=False) print(f"✅ 已保存前{idx+1}条数据") # 最终保存 df.to_csv('df.csv', index=False) - 使用tqdm显示进度:安装
tqdm库后,可以给apply加上进度条,方便跟踪处理进度:from tqdm import tqdm tqdm.pandas() df['follower_count'] = df['Username'].progress_apply(getFollowerCount)
内容的提问来源于stack exchange,提问作者newbie101
相关产品推荐
相关产品推荐

