使用BeautifulSoup抓取动态JavaScript表格遇数据获取问题
解决JavaScript动态表格抓取问题
你的代码只能获取页面静态HTML,而目标表格数据是通过AJAX异步请求从后端API加载的,所以BeautifulSoup无法直接提取动态内容。
核心问题分析
页面初始HTML仅包含表格框架,真实数据是用户点击分页时,前端通过JavaScript调用后端API接口获取的。requests.get()只能拿到初始静态页面,自然无法获取动态加载的表格数据。
解决步骤
1. 定位数据接口
打开浏览器开发者工具(F12)→ 切换到Network标签 → 勾选XHR过滤选项,然后点击页面分页按钮,观察新出现的请求。你会发现表格数据来自https://search-intelligence.co.uk/niche-finder/data的POST接口,请求参数包含page(页码)和per_page(每页行数)。
2. 配置请求头和参数
该站点基于Laravel框架,需要携带X-XSRF-TOKEN(从Cookie中的XSRF-TOKEN值URL解码后得到),同时保持完整的Cookie信息(避免会话失效)。
3. 循环请求所有分页
因为有3188页数据,需要循环请求每一页的API接口,解析返回的JSON数据。
修正后的代码示例
import requests import json from urllib.parse import unquote import time # 解码Cookie中的XSRF-TOKEN(注意:Cookie过期后需要从浏览器重新复制) xsrf_token = unquote("eyJpdiI6ImxJbXN4NHpuRHRkSnB0RjNnMEU1cVE9PSIsInZhbHVlIjoiTEd6V3BibHEvTG84aCtkajIxQTJ4Szk4cTZQQ2dNODJmcHpSZkltK3FZQTJOOUIvSHJDU05EV3Ztd0tUMEJCbmhxTzVFSThoQ1NNaldDWWpGNEo1Z0ZsYjlUSTVEZVBJcGw5NmIrK2NqdHh2cURVTUJyQy9JcUdMYmNWZ1FwQ3MiLCJtYWMiOiI1ZmRjNDE4YWI4OTVhZDZkMjA1OTlhNGU5Zjk1YTNkMDQxNTQyNTc0MmU3MjhiMGE5NjM0YzFkY2Q0ZjQ1NmZjIiwidGFnIjoiIn0%3D") headers = { 'Accept': 'application/json, text/javascript, */*; q=0.01', 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', 'X-XSRF-TOKEN': xsrf_token, 'Cookie': '_ga=GA1.3.280184480.1658298012; XSRF-TOKEN=eyJpdiI6ImxJbXN4NHpuRHRkSnB0RjNnMEU1cVE9PSIsInZhbHVlIjoiTEd6V3BibHEvTG84aCtkajIxQTJ4Szk4cTZQQ2dNODJmcHpSZkltK3FZQTJOOUIvSHJDU05EV3Ztd0tUMEJCbmhxTzVFSThoQ1NNaldDWWpGNEo1Z0ZsYjlUSTVEZVBJcGw5NmIrK2NqdHh2cURVTUJyQy9JcUdMYmNWZ1FwQ3MiLCJtYWMiOiI1ZmRjNDE4YWI4OTVhZDZkMjA1OTlhNGU5Zjk1YTNkMDQxNTQyNTc0MmU3MjhiMGE5NjM0YzFkY2Q0ZjQ1NmZjIiwidGFnIjoiIn0%3D; laravel_session=eyJpdiI6InJRSDVHMEFOY3BCcHk1OGNjY2srdGc9PSIsInZhbHVlIjoiS1pxbEJJNHZtT3ZuNkgzMTlhTG1CZXBwY3VYK3JIamNaajhSU1JXRmpwS3lFMElFenpVdVpNd0Q0VlRQdFdUYi9ndFRGQytJcUxIV1pCUmxpVkEzTVRXSzZiOWFXVCs0ZHhGVldxbTRucGJjTjRNM0tQWHg4NUNUdk9aZUNxaGIiLCJtYWMiOiIwZTU0OTMzZTM1MDZkZmI5MjdjZmIzNDczNzViZGI4YzM1ODdhN2RiYzk0YzUzMzI3Njg1MjE4MTlmYzg4MmVlIiwidGFnIjoiIn0%3D; _gid=GA1.3.1135025661.1662360353' } api_url = 'https://search-intelligence.co.uk/niche-finder/data' # 循环请求所有页码 for page_num in range(1, 3189): payload = { 'page': page_num, 'per_page': 100 } try: # 发送POST请求 response = requests.post(api_url, headers=headers, data=payload) response.raise_for_status() # 捕获HTTP错误 # 解析JSON数据 table_data = response.json() # 示例:打印当前页数据(可替换为保存到数据库/文件) print(f"已获取第{page_num}页数据,共{len(table_data)}条") # 保存到JSON文件 with open(f'niche_finder_page_{page_num}.json', 'w', encoding='utf-8') as f: json.dump(table_data, f, indent=2, ensure_ascii=False) # 添加请求间隔,避免触发反爬 time.sleep(1) except requests.exceptions.RequestException as e: print(f"第{page_num}页请求失败:{str(e)}") continue
注意事项
- Cookie过期问题:
laravel_session和XSRF-TOKEN会定期失效,需要从浏览器开发者工具中重新复制最新的Cookie值。 - 反爬机制:大量连续请求可能会被网站封禁IP,建议增加请求间隔(
time.sleep()),或使用代理IP。 - 参数一致性:确保请求头、参数与浏览器中实际发送的完全一致,可通过开发者工具的"复制为cURL"功能,再转成Python代码验证。
内容的提问来源于stack exchange,提问作者Philip Fernando
相关产品推荐
相关产品推荐

