如何用Python爬取完整Instagram页面?解决仅获取12张图片的问题
解决Instagram爬虫仅获取12张图片的问题
嘿,我完全懂你的困扰!Instagram网页版用了动态加载机制——初始页面只会渲染前12条帖子,剩下的内容都是在你滚动页面时,通过后台GraphQL API异步加载的。所以直接用requests.get只能拿到初始加载的内容,要抓取所有图片,得模拟这个异步请求的过程才行。
下面我给你一步步拆解解决方案,用requests实现完整的内容抓取:
核心思路
- 从初始页面提取关键参数:用户ID、分页标记(
end_cursor)、CSRF Token(需要登录后获取有效会话,否则API会限制访问)。 - 循环调用Instagram的GraphQL API,每次请求获取下一页的帖子,直到没有更多内容为止。
- 从每一页的API响应中提取图片链接。
完整代码实现
import json import requests from bs4 import BeautifulSoup import time def get_instagram_all_images(username): # 初始化会话,保持登录状态 session = requests.Session() 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" } base_url = f"https://www.instagram.com/{username}/" # 1. 初始请求,获取基础参数 response = session.get(base_url, headers=headers) soup = BeautifulSoup(response.text, 'lxml') # 提取页面内嵌的共享数据 script_tag = soup.find('script', string=lambda t: t and 'window._sharedData' in t) shared_data = json.loads(script_tag.text.replace('window._sharedData = ', '')[:-1]) # 提取用户ID、初始分页标记和是否还有下一页 user_data = shared_data['entry_data']['ProfilePage'][0]['graphql']['user'] user_id = user_data['id'] media_info = user_data['edge_owner_to_timeline_media'] end_cursor = media_info['page_info']['end_cursor'] has_next_page = media_info['page_info']['has_next_page'] # 提取CSRF Token(从会话Cookie中获取) csrf_token = session.cookies.get('csrftoken') # 收集所有图片链接,先加入初始的12张 all_image_urls = [] for post in media_info['edges']: if post['node']['display_url']: all_image_urls.append(post['node']['display_url']) # 2. 循环请求GraphQL API加载更多内容 graphql_url = "https://www.instagram.com/graphql/query/" # 注意:query_hash可能随Instagram更新变化,失效时需抓包获取最新值 query_hash = "e769aa130647d2354c40ea6a439bfc08" while has_next_page: # 构造请求参数 params = { "query_hash": query_hash, "variables": json.dumps({ "id": user_id, "first": 12, "after": end_cursor }) } headers.update({ "X-CSRFToken": csrf_token, "Referer": base_url }) # 发送请求,添加延迟避免被封 time.sleep(2) graphql_response = session.get(graphql_url, params=params, headers=headers) if graphql_response.status_code != 200: print(f"请求失败,状态码:{graphql_response.status_code}") break # 解析响应数据,提取图片链接 data = graphql_response.json() new_posts = data['data']['user']['edge_owner_to_timeline_media']['edges'] for post in new_posts: if post['node']['display_url']: all_image_urls.append(post['node']['display_url']) # 更新分页参数 page_info = data['data']['user']['edge_owner_to_timeline_media']['page_info'] has_next_page = page_info['has_next_page'] end_cursor = page_info['end_cursor'] return all_image_urls # 使用示例(替换成目标账号名) if __name__ == "__main__": target_username = "accountName" all_images = get_instagram_all_images(target_username) print(f"共抓取到 {len(all_images)} 张图片") # 打印前5张链接示例 for idx, url in enumerate(all_images[:5]): print(f"第{idx+1}张:{url}")
重要注意事项
- 登录会话要求:现在Instagram对未登录用户的API访问限制极严,你需要先登录网页版Instagram,从浏览器Cookie中获取
sessionid,并手动添加到session的cookies中(否则会返回403或空数据)。 - Query Hash 更新:Instagram的GraphQL查询哈希值(
query_hash)可能不定期更新,如果代码突然失效,打开浏览器开发者工具的Network面板,抓取滚动加载时的GraphQL请求,就能拿到最新的query_hash。 - 请求频率控制:务必添加请求延迟(比如
time.sleep(2)),频繁请求会触发Instagram的反爬机制,导致IP被封禁。 - 账号权限:确保目标账号是公开的,爬取私人账号需要对应权限,否则会被拒绝访问。
内容的提问来源于stack exchange,提问作者WeDa Beast
相关产品推荐
相关产品推荐

