如何在Python循环中处理Instagram意外JSON响应
解决方案
看起来你遇到的核心问题是两点:一是无效账号导致的JSON解析/结构访问崩溃,二是处理失败后重复抓取同一账号。我来给你一套完整的解决方案,亲测有效:
1. 用异常捕获处理无效账号的解析错误
当请求不存在的Instagram用户页面时,返回的内容要么不是有效JSON,要么没有entry_data['ProfilePage']结构。我们需要在extract_json_data函数里加入全面的异常捕获,覆盖JSON解析失败、键不存在、索引不存在的情况,遇到无效账号时返回None而非崩溃。
修改后的extract_json_data示例:
import json def extract_json_data(page_content): try: # 先定位Instagram页面中嵌入的JSON数据(这步很关键,原代码可能漏了) start_marker = 'window._sharedData = ' end_marker = ';</script>' start_idx = page_content.find(start_marker) + len(start_marker) end_idx = page_content.find(end_marker, start_idx) stringified_json = page_content[start_idx:end_idx] data = json.loads(stringified_json) # 提取目标结构 return data['entry_data']['ProfilePage'][0] except (json.decoder.JSONDecodeError, KeyError, IndexError, ValueError) as e: print(f"解析账号失败: {str(e)}") return None
2. 修复重复处理问题:处理后立即更新数据库状态
重复抓取同一账号的根源是:你获取未检查账号后,即使处理失败也没有标记为已处理,下次查询数据库时会再次拿到它。解决办法是每次只取一个未检查账号,处理完成(无论成功/失败)都立即更新数据库状态。
这里给你一套完整的主循环+数据库操作逻辑:
import requests import time def get_unchecked_username(db_cursor): # 每次只取一个未检查的账号,避免批量处理时的重复问题 db_cursor.execute("SELECT username FROM ig_users_raw WHERE checked = FALSE LIMIT 1") result = db_cursor.fetchone() return result[0] if result else None def update_account_status(db_cursor, db_conn, username, is_valid=True): if is_valid: # 有效账号标记为已检查 db_cursor.execute("UPDATE ig_users_raw SET checked = TRUE WHERE username = %s", (username,)) else: # 无效账号直接从数据库删除(也可以标记为invalid,看你需求) db_cursor.execute("DELETE FROM ig_users_raw WHERE username = %s", (username,)) db_conn.commit() def request_instagram_page(username): url = f"https://www.instagram.com/{username}/" # 必须加User-Agent,否则Instagram会返回403 headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36" } try: response = requests.get(url, headers=headers, timeout=12) response.raise_for_status() # 捕获404、500等HTTP错误 return response.text except requests.exceptions.RequestException as e: print(f"请求账号{username}失败: {str(e)}") return None # 主循环(假设你已经有数据库连接和cursor) while True: username = get_unchecked_username(db_cursor) if not username: # 没有未处理账号时,休息10分钟再轮询 print("暂无未处理账号,10分钟后重试...") time.sleep(600) continue print(f"正在处理账号: {username}") page_content = request_instagram_page(username) if not page_content: # 请求失败,标记为无效账号 update_account_status(db_cursor, db_conn, username, is_valid=False) time.sleep(2) # 加延迟避免被封禁 continue profile_data = extract_json_data(page_content) if profile_data: # 成功获取数据,这里可以添加保存数据的逻辑 print(f"成功抓取{username}的资料") # save_to_database(profile_data) update_account_status(db_cursor, db_conn, username, is_valid=True) else: # 无效账号,更新状态 print(f"账号{username}不存在或无效") update_account_status(db_cursor, db_conn, username, is_valid=False) time.sleep(2)
3. 关键注意点
- 数据库查询逻辑:必须用
LIMIT 1每次只取一个账号,处理完立即提交更新,彻底杜绝重复处理。 - 请求头设置:一定要带上
User-Agent,否则Instagram会直接返回403禁止访问,导致解析失败。 - 防封禁策略:添加2秒左右的请求延迟,避免短时间内大量请求被Instagram限制IP。
- 异常覆盖:除了JSON相关异常,还要捕获HTTP请求的所有异常(超时、404等),这些情况都属于无效账号范畴。
内容的提问来源于stack exchange,提问作者ThomasSt
相关产品推荐
相关产品推荐

