Scrapy如何高效抓取MDPI动态加载内容及双重编码邮箱?

2026-04-29 08:272阅读0评论SEO资源
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计996个文字,预计阅读时间需要4分钟。

Scrapy如何高效抓取MDPI动态加载内容及双重编码邮箱?

本篇详细介绍如何纯用Scrapy高效抓取MDPI搜索结果页面(每页50+篇文献),解决默认仅返回15条、JavaScript动态加载、Cloudflare双重防护等问题。

1. 使用Scrapy爬虫框架

2.解析JavaScript动态加载内容

3.获取每页50+篇文献信息

4.跳过15条默认结果限制

5.消除Cloudflare双重防护

具体步骤如下:

MDPI 官网(如 mdpi.com/search)采用分页异步加载策略:首屏渲染仅展示前 15 篇文献,剩余 35 篇通过 AJAX 请求按批次(通常每次 +15 条)动态注入 DOM。若仅依赖静态 XPath 提取 //a[@class='title-link'],Scrapy 将只能捕获初始 HTML 中的 15 个链接——这正是你遇到“只返回 15 条而非 50 条”的根本原因。关键在于识别并模拟其前端分页逻辑,而非转向 Selenium。

✅ 正确方案:Scrapy + AJAX 分页模拟(零 JavaScript 渲染)

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 原生异步能力与精准协议分析即可胜任。

标签:编码邮箱

本文共计996个文字,预计阅读时间需要4分钟。

Scrapy如何高效抓取MDPI动态加载内容及双重编码邮箱?

本篇详细介绍如何纯用Scrapy高效抓取MDPI搜索结果页面(每页50+篇文献),解决默认仅返回15条、JavaScript动态加载、Cloudflare双重防护等问题。

1. 使用Scrapy爬虫框架

2.解析JavaScript动态加载内容

3.获取每页50+篇文献信息

4.跳过15条默认结果限制

5.消除Cloudflare双重防护

具体步骤如下:

MDPI 官网(如 mdpi.com/search)采用分页异步加载策略:首屏渲染仅展示前 15 篇文献,剩余 35 篇通过 AJAX 请求按批次(通常每次 +15 条)动态注入 DOM。若仅依赖静态 XPath 提取 //a[@class='title-link'],Scrapy 将只能捕获初始 HTML 中的 15 个链接——这正是你遇到“只返回 15 条而非 50 条”的根本原因。关键在于识别并模拟其前端分页逻辑,而非转向 Selenium。

✅ 正确方案:Scrapy + AJAX 分页模拟(零 JavaScript 渲染)

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 原生异步能力与精准协议分析即可胜任。

标签:编码邮箱