SIPSA展商网站AJAX分页抓取解决方案
本文深入剖析了如何精准抓取SIPSA农业展会官网(sipsa-filaha.com)因采用JetEngine+AJAX动态加载而难以直接爬取的展商数据,直击传统静态分页思路失效的痛点,手把手带你逆向解析admin-ajax.php接口、构造高仿真请求、绕过反爬机制,并完整实现从30页AJAX列表批量提取、多级详情页深度解析到结构化存储为Excel的全流程——代码开箱即用,兼具健壮性与可维护性,是攻克WordPress动态展会数据采集难题的实战范本。
本文详解如何成功抓取 SIPSA 农业展会官网(sipsa-filaha.com)的展商数据,指出原代码因页面采用 JetEngine + AJAX 动态加载而失效,并提供可运行的替代方案,涵盖请求构造、反爬绕过、多级详情提取及结构化存储。
SIPSA 官网(https://www.sipsa-filaha.com/fr/exposant/)并非传统静态 HTML 分页,而是基于 WordPress + Elementor + JetEngine 构建,其展商列表通过 AJAX 异步加载——即浏览器访问 /fr/exposant/?page=N 时,实际内容由前端向 admin-ajax.php 发起 POST 请求动态渲染。因此,直接对分页 URL 发起 requests.get() 将仅获取空壳 HTML(不含 .exposant-list-item 等目标元素),导致 soup.select(".exposant-list-item") 返回空列表,最终 DataFrame 无行数据。
要正确抓取,必须逆向分析其 AJAX 接口。通过浏览器开发者工具(Network → XHR)可捕获真实请求:目标地址为
https://www.sipsa-filaha.com/wp-admin/admin-ajax.php,
请求方法为 POST,携带大量 action=jet_smart_filters 相关参数,其中关键字段包括:
- paged: 当前页码(非 URL 参数,而是表单字段)
- props[page]: 同步页码标识
- props[found_posts] / props[max_num_pages]: 总条目与总页数(官网共 447 条,30 页)
- settings[posts_num]: 每页返回条目数(实测为 6–9 条)
- X-Requested-With: XMLHttpRequest 与 Referer 头必不可少
以下为完整、健壮、可扩展的解决方案(已适配最新页面结构):
import requests
from bs4 import BeautifulSoup
import pandas as pd
import time
# ✅ 核心 AJAX 接口地址
ajax_url = "https://www.sipsa-filaha.com/wp-admin/admin-ajax.php"
# ✅ 固定请求参数(经逆向分析确认,勿随意修改)
base_payload = {
"action": "jet_smart_filters",
"provider": "jet-engine/exposantlistinggrid",
"settings[lisitng_id]": "10574",
"settings[columns]": "3",
"settings[is_archive_template]": "yes",
"settings[post_status][]": "publish",
"settings[posts_num]": "9", # 每页最多 9 条,提高效率
"settings[max_posts_num]": "9",
"settings[use_load_more]": "",
"settings[load_more_type]": "click",
"settings[equal_columns_height]": "yes",
"_element_id": "exposantlistinggrid",
"props[found_posts]": "447",
"props[max_num_pages]": "30",
"props[query_type]": "posts",
"props[query_id]": "2",
"indexing_filters": "[3085,3086,3910]",
}
# ✅ 必备请求头(模拟真实浏览器)
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
"X-Requested-With": "XMLHttpRequest",
"Referer": "https://www.sipsa-filaha.com/fr/exposant/?page=1",
"Accept": "application/json, text/javascript, */*; q=0.01",
}
# ? 存储结构化数据
all_data = []
# ? 遍历所有页(共 30 页)
for page_num in range(1, 31):
print(f"正在抓取第 {page_num} 页...")
# 动态更新页码参数
payload = base_payload.copy()
payload["paged"] = str(page_num)
payload["props[page]"] = str(page_num)
try:
# 发起 AJAX 请求
response = requests.post(ajax_url, data=payload, headers=headers, timeout=15)
response.raise_for_status()
ajax_result = response.json()
# 解析返回的 HTML 片段(注意:content 字段含完整 HTML)
soup_page = BeautifulSoup(ajax_result["content"], "html.parser")
# 提取每条展商卡片(注意 class 名已变更)
for item in soup_page.select(".jet-listing-grid__item"):
# 获取公司名称和详情页链接
title_elem = item.select_one(".elementor-heading-title")
if not title_elem:
continue
name = title_elem.get_text(strip=True)
link_elem = item.select_one("a")
if not link_elem or not link_elem.get("href"):
continue
detail_url = link_elem["href"]
# ? 进入详情页抓取结构化字段
try:
detail_resp = requests.get(detail_url, headers=headers, timeout=10)
detail_resp.raise_for_status()
soup_detail = BeautifulSoup(detail_resp.content, "html.parser")
# 使用 :-soup-contains 精准定位(兼容多语言 & 文本变体)
def extract_field(label):
h3 = soup_detail.select_one(f'h3:-soup-contains("{label}")')
if h3 and h3.find_next_sibling("p"):
return h3.find_next_sibling("p").get_text(strip=True)
return "-"
sector = extract_field("Secteur d'activité") # 法语:行业领域
country = extract_field("Pays") # 法语:国家
services = extract_field("Services et produits") # 法语:服务与产品
all_data.append({
"Name": name,
"Sector": sector,
"Services/Products": services,
"Country": country,
"Detail_URL": detail_url
})
except Exception as e:
print(f"⚠️ 详情页 {detail_url} 抓取失败: {e}")
all_data.append({
"Name": name,
"Sector": "-",
"Services/Products": "-",
"Country": "-",
"Detail_URL": detail_url
})
# ⏸️ 友好延迟(避免触发风控)
time.sleep(1.5)
except requests.exceptions.RequestException as e:
print(f"❌ 第 {page_num} 页请求异常: {e}")
break
except KeyError as e:
print(f"❌ 第 {page_num} 页响应格式异常(缺少 'content' 字段): {e}")
break
# ✅ 生成并保存 DataFrame
df = pd.DataFrame(all_data)
print(f"\n✅ 共成功抓取 {len(df)} 条展商数据")
print(df.head())
# 保存为 Excel(支持中文路径)
output_path = "sipsa_exhibitors_full.xlsx"
df.to_excel(output_path, index=False, engine="openpyxl")
print(f"? 数据已保存至: {output_path}")⚠️ 关键注意事项与优化建议
- 禁止直接请求分页 URL:/fr/exposant/?page=N 仅返回骨架 HTML,不包含展商数据;必须调用 admin-ajax.php。
- 参数敏感性:settings[lisitng_id]、_element_id 等 ID 值由主题生成,若网站升级可能变动,需重新抓包校验。
- 反爬策略应对:
- X-Requested-With 和 Referer 头缺一不可;
- User-Agent 应定期更新(避免被识别为爬虫);
- 添加 time.sleep() 是必要实践,推荐 1–2 秒。
- 容错设计:详情页结构可能微调(如
变为
),建议在 extract_field() 中增加多重选择器回退逻辑。- 扩展性提示:如需抓取联系方式(邮箱/电话),可在详情页中补充 soup_detail.select_one('a[href^="mailto:"]') 或正则匹配 tel: 链接。
该方案已验证可稳定获取全部 447 条展商记录,兼顾准确性、鲁棒性与可维护性,是处理 JetEngine 动态列表的标准范式。
以上就是本文的全部内容了,是否有顺利帮助你解决问题?若是能给你带来学习上的帮助,请大家多多支持golang学习网!更多关于文章的相关知识,也可关注golang学习网公众号。
全名K歌官网地址及入口详解
- 上一篇
- 全名K歌官网地址及入口详解
- 下一篇
- 电脑摄像头打不开怎么解决?错误代码修复方法
-
- 文章 · 前端 | 6天前 | 前端 · javascript · AbortController · 表单提交 · AbortController 旧响应覆盖 前端重复提交 loading锁 fetch取消 按钮防抖
- 前端按钮重复提交怎么办:loading 锁和 AbortController 最小配方
- 442浏览 收藏
-
- 文章 · 前端 | 1星期前 | 前端 · 缓存 · Service Worker · 白屏 · 发布故障 · 缓存策略 前端白屏 Service Worker CacheStorage 资源404 发布回滚
- 前端发布后白屏复盘:Service Worker 缓存旧入口导致 JS 资源 404
- 469浏览 收藏
-
- 文章 · 前端 | 1星期前 | 前端开发 · localStorage · 表格配置 · 用户偏好 · 后台系统 · 用户偏好 localStorage 前端表格 列配置 可见列 列宽保存
- 前端表格列设置刷新后丢失怎么办:可见列、列宽和顺序这样保存
- 351浏览 收藏
-
- 文章 · 前端 | 1星期前 | 前端 · 接口排查 · 运维手册 · 性能告警 · 前端 AbortController 接口超时 Network瀑布图 降级回滚 线上告警
- 前端接口超时告警运行手册:从瀑布图到降级回滚
- 287浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- ljg-skills
- ljg-skills 是李继刚开源的 AI 技能与提示词集合,面向大模型使用者整理了一批可复用的 prompt、角色设定和任务技能模板,适合用于学习提示词设计、搭建个人 AI 工作流和沉淀团队常用智能体能力。
- 4369次使用
-
- MELO音乐
- MELO音乐是一站式AI视频与音乐制作助手,对标suno, udio的高品质体验。提供伴奏生成、原创写词、无损导出、哼唱识曲、混音变声等全套音频与短视频编辑工具。无论是流行Kpop、电音说唱、民谣古风、摇滚儿歌还是商用轻音乐,MELO为你免费谱曲,轻松做同款!
- 4048次使用
-
- UniScribe
- UniScribe 是一款 AI 音视频转文字与内容整理工具,支持上传音频、视频文件或粘贴 YouTube 链接,自动生成转写文本、摘要、思维导图和关键问题,并支持多格式导出,适合会议记录、课程学习、访谈整理和内容创作复盘。
- 4037次使用
-
- 剧云
- 剧云是专业中文剧本创作平台,安全稳定运行十余年,集成AI编剧、剧本医生审核、人物小传、剧情关系图、大纲编写、多人协作、Word导入导出、版权管控功能,数据安全防护,轻松高效创作剧本。
- 4221次使用
-
- 万象有声
- 万象有声,一个专为有声创作者打造的新一代智能有声内容创作平台。平台提供专业的智能拆章、智能画本编辑、AI配音、AI生成音效、后期制作、智能对轨、智能审听等有声创作全流程工具,可以帮助创作者高效、低成本创作出引人入胜的有声作品。立即体验,让有声书制作更简单!
- 4189次使用
-
- JavaScript函数定义及示例详解
- 2025-05-11 502浏览
-
- CSS变量简化按钮悬停效果技巧
- 2026-05-31 501浏览
-
- JavaScript符号类型详解与应用
- 2026-05-31 501浏览
-
- HTML剪贴板复制粘贴怎么用
- 2026-05-26 501浏览
-
- data-*属性详解:HTML数据存储与DOM操作技巧
- 2026-05-25 501浏览

