使用Python+BeautifulSoup爬取Pinterest:突破仅获16条数据的限制
突破Pinterest爬虫16条数据限制的解决方案
嘿,你遇到的这个问题其实是Pinterest的*动态加载(无限滚动)*机制在搞鬼——初始页面只渲染16条左右的Pin内容,剩下的得触发滚动或者AJAX请求才会加载。下面给你两种靠谱的解决方案,帮你拿到至少100条数据:
方法1:模拟浏览器滚动(用Selenium)
Pinterest会根据页面滚动位置加载新内容,我们可以用Selenium模拟浏览器反复滚动到底部,触发新内容的加载:
from selenium import webdriver from selenium.webdriver.common.by import By import time import pandas as pd search_query = "analytics" url = f"https://in.pinterest.com/search/pins/?q={search_query}" # 初始化Chrome浏览器(记得提前下载对应版本的ChromeDriver) driver = webdriver.Chrome() driver.get(url) target_data_count = 100 current_loaded = 0 while current_loaded < target_data_count: # 执行JS滚动到页面最底部 driver.execute_script("window.scrollTo(0, document.body.scrollHeight);") # 给页面留加载时间,避免请求太频繁被封 time.sleep(2) # 统计当前加载的图片数量 img_elements = driver.find_elements(By.TAG_NAME, "img") current_loaded = len(img_elements) print(f"已加载 {current_loaded} 条数据...") # 提取需要的alt和src属性,过滤空值 alt_list = [] src_list = [] for img in img_elements: alt_text = img.get_attribute("alt") img_src = img.get_attribute("src") if alt_text and img_src: alt_list.append(alt_text) src_list.append(img_src) # 截取到目标数量,转成DataFrame result_df = pd.DataFrame({ "alt_text": alt_list[:target_data_count], "image_src": src_list[:target_data_count] }) print(result_df) # 关闭浏览器 driver.quit()
方法2:直接调用Pinterest内部API(无需官方审批)
其实Pinterest滚动加载时会偷偷调用内部API获取数据,我们可以抓包找到这个接口,直接发送请求拿数据,效率比模拟浏览器高多了:
抓包小技巧
打开浏览器开发者工具(F12)→ 切换到「Network」标签→ 滚动页面,找类似https://in.pinterest.com/resource/BaseSearchResource/get/的请求,查看它的参数和响应格式。
示例代码:
import requests import json import pandas as pd import time import random search_query = "analytics" base_api_url = "https://in.pinterest.com/resource/BaseSearchResource/get/" 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", "X-Requested-With": "XMLHttpRequest" } # 初始请求参数,cursor为空表示第一页 params = { "source_url": f"/search/pins/?q={search_query}", "data": json.dumps({ "options": { "query": search_query, "page_size": 25, # 每页拿25条,可调整但别太大 "cursor": None }, "context": {} }) } alt_list = [] src_list = [] creator_list = [] desc_list = [] target_count = 100 while len(alt_list) < target_count: # 发送请求,加随机延迟防封 time.sleep(random.uniform(1.5, 3)) response = requests.get(base_api_url, headers=headers, params=params) response_data = response.json() # 解析返回的Pin数据 pin_results = response_data["resource_response"]["data"]["results"] for pin in pin_results: if len(alt_list) >= target_count: break # 提取你需要的字段 alt_text = pin.get("grid_title") or pin.get("description", "") img_src = pin["images"]["236x"]["url"] # 可选其他尺寸,比如"564x" creator = pin["creator"]["username"] description = pin.get("description", "") alt_list.append(alt_text) src_list.append(img_src) creator_list.append(creator) desc_list.append(description) # 获取下一页的cursor,没有的话就停止 next_cursor = response_data["resource_response"]["data"].get("cursor") if not next_cursor: print("没有更多数据了") break # 更新参数里的cursor,准备请求下一页 params["data"] = json.dumps({ "options": { "query": search_query, "page_size": 25, "cursor": next_cursor }, "context": {} }) # 整理成DataFrame result_df = pd.DataFrame({ "alt_text": alt_list, "image_src": src_list, "creator": creator_list, "description": desc_list }) print(result_df)
避坑提醒
- 反爬应对:Pinterest会检测请求频率和User-Agent,记得加随机延迟,也可以多准备几个User-Agent轮换使用
- 字段扩展:API返回的数据里还有很多你需要的字段(比如创作者ID、评论数等),可以根据
pin对象的结构自行提取 - 合规性:爬取数据前记得遵守Pinterest的服务条款,别用来搞商业滥用或者过度爬取
内容的提问来源于stack exchange,提问作者siva palanisamy
相关产品推荐
相关产品推荐

