
本文详解如何纯用 scrapy 高效抓取 mdpi 搜索结果页(每页 50 篇文献),解决默认仅返回 15 条、javascript 动态加载、cloudflare 双重邮箱混淆等核心问题,无需 selenium,显著提升爬取速度与稳定性。
本文详解如何纯用 scrapy 高效抓取 mdpi 搜索结果页(每页 50 篇文献),解决默认仅返回 15 条、javascript 动态加载、cloudflare 双重邮箱混淆等核心问题,无需 selenium,显著提升爬取速度与稳定性。
MDPI 官网(如 mdpi.com/search)采用分页异步加载策略:首屏渲染仅展示前 15 篇文献,剩余 35 篇通过 AJAX 请求按批次(通常每次 +15 条)动态注入 DOM。若仅依赖静态 XPath 提取 //a[@class='title-link'],Scrapy 将只能捕获初始 HTML 中的 15 个链接——这正是你遇到“只返回 15 条而非 50 条”的根本原因。关键在于识别并模拟其前端分页逻辑,而非转向 Selenium。
MDPI 的搜索结果页实际通过 POST /search/set/default/pagination 接口加载后续数据,该接口接受 X-Requested-With: XMLHttpRequest 头,并依赖 Referer 和会话上下文。我们可完全绕过浏览器渲染,直接构造请求:
- 第一步:设置高密度分页参数
在 URL 中显式指定 page_count=50(支持最大单页 50 条),并配合 page_no 控制页码:
base_url = "https://www.mdpi.com/search?sort=pubdate&page_no={}&page_count=50&year_from=1996&year_to=2024&q=biomaterials&view=default"
- 第二步:主动触发 AJAX 补充加载
初始响应仅含 15 条,需额外发送 3 次 AJAX 请求(因 15 × 4 = 60 > 50),每次获取下一批 15 条。注意携带必要 headers:
headers = {
"X-Requested-With": "XMLHttpRequest", "Referer": self.base_url.format(page_no), "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
} yield scrapy.Request(
url="https://www.mdpi.com/search/set/default/pagination", headers=headers, cb_kwargs={"page_no": page_no, "index": index}, dont_filter=True # 避免因相同 URL 被去重
)
MDPI 使用 Cloudflare 邮箱保护(两次 XOR 十六进制解码)。原函数已适配双层解密逻辑,确保 email_href(如 mailto:mailto:…)被完整还原:
def decode_email_protection(encoded_string):
if not encoded_string: return None # 第一层解码:提取 # 后数据,用前2位 hex 作密钥 XOR encoded_data = encoded_string.split('#')[-1] r = int(encoded_data[:2], 16) email = ''.join([chr(int(encoded_data[i:i+2], 16) ^ r) for i in range(2, len(encoded_data), 2)]) # 第二层解码:再次处理 email 中的 # 编码片段 encoded_data = email.split('#')[-1] r = int(encoded_data[4:6], 16) encoded_data = encoded_data[:4] + encoded_data[6:] email = ''.join([chr(int(encoded_data[i:i+2], 16) ^ r) for i in range(0, len(encoded_data), 2)]) return email
- User-Agent 与 Referer 必须匹配:AJAX 请求的 Referer 必须为当前搜索页 URL,否则服务器返回空数据或 403。
- 禁用去重(dont_filter=True):因所有 AJAX 请求 URL 相同(/pagination),需手动控制去重逻辑(通过 cb_kwargs 中的 index 区分批次)。
- XPath 健壮性增强:作者字段使用 getall() + strip() 组合,避免因换行/空格导致数据截断;标题用 //text() 全量提取再拼接。
- 性能对比:纯 Scrapy 方案耗时约为 Selenium 的 1/5–1/3(无浏览器启动、JS 解析、渲染开销),内存占用更低,更适合分布式部署。
运行优化后的 Spider,单页 page_no=218 将稳定提取全部 50 篇文献链接,并正确解析出经双重混淆的作者邮箱。你无需维护 WebDriver 实例、等待页面加载超时或处理弹窗,Scrapy 原生异步能力与精准协议分析即可胜任。
延伸建议:若需全站抓取,将 start_requests 中的 range(218, 219) 扩展为 range(1, total_pages+1),并通过首次请求解析 total_results // 50 + 1 动态计算总页数,实现全自动分页。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/282019.html