
Google 新闻 RSS Feed 中的链接是经过混淆的跳转 URL,直接请求会返回 JavaScript 重定向页而非目标文章;需通过解析 data-p 参数并调用其内部 BatchExecute 接口,才能解密获取原始文章地址。
google 新闻 rss feed 中的链接是经过混淆的跳转 url,直接请求会返回 javascript 重定向页而非目标文章;需通过解析 `data-p` 参数并调用其内部 batchexecute 接口,才能解密获取原始文章地址。
Google 新闻(news.google.com/rss/...)提供的 RSS 源看似标准 XML,但其中 <link> 标签指向的并非真实文章地址,而是形如 https://news.google.com/rss/articles/CBMiogFBVV95cUxQLUFubVFtajlobFdKQllBb1JBRDNPNm8yRE51a0N2STl3SGd6eFY2cEVMdllnM1VwNGRBbWxsa0FLUGViaHNaN2p2R2oyMWFsNklvM3pFdXZFWjNNT1dNN2lrclRzWTlLOEpOLXYzZzdETnFMS0ZUZktvZTREcmU0ZzZucmFYZk0tR1gzTVlEUWh4dXVpMGMxSWltb2x2enl1TEE?oc=5 的混淆链接。这类 URL 并非真实资源地址,而是 Google 前端 JS 用于动态加载和跳转的中间标识符——直接用 requests.get() 请求它,将收到含 <script></script> 的 HTML 页面(含 window.location.replace(...)),而非重定向到目标站点。
要可靠提取真实文章 URL,核心思路是模拟 Google 新闻前端的跳转逻辑:
- 解析 RSS 中的混淆链接;
- 请求该链接,提取页面中
<c-wiz data-p="..."></c-wiz>的data-p属性值; - 清洗并反序列化该 JSON 字符串(注意替换
%.@.占位符); - 构造符合 Google 内部协议的
batchexecutePOST 请求体; - 调用
https://news.google.com/_/DotsSplashUi/data/batchexecute接口,解析响应中的嵌套 JSON,最终定位真实文章 URL。
以下是完整、可运行的 Python 示例(依赖 requests 和 beautifulsoup4):
import requests
import json
from bs4 import BeautifulSoup
def extract_real_article_url(rss_link: str) -> str:
# Step 1: Fetch the Google News article redirect page
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language': 'en-US,en;q=0.5',
'Accept-Encoding': 'gzip, deflate',
'Connection': 'keep-alive',
}
resp = requests.get(rss_link, headers=headers, timeout=10)
resp.raise_for_status()
# Step 2: Parse data-p from c-wiz element
soup = BeautifulSoup(resp.text, 'html.parser')
c_wiz = soup.select_one('c-wiz[data-p]')
if not c_wiz:
raise ValueError("Failed to locate c-wiz[data-p] in response")
data_p = c_wiz.get('data-p')
# Step 3: Clean and parse data-p (Google uses custom encoding)
try:
# Replace placeholder and load as JSON array
cleaned = data_p.replace('%.@.', '["garturlreq",')
obj = json.loads(cleaned)
except json.JSONDecodeError as e:
raise ValueError(f"Failed to parse data-p: {e}")
# Step 4: Build batchexecute payload
# Keep all but last 6 elements, then append last 2 — per observed pattern
trimmed_obj = obj[:-6] + obj[-2:]
inner_payload = json.dumps([['Fbv4je', json.dumps(trimmed_obj), 'null', 'generic']])
payload = {
'f.req': json.dumps([[inner_payload]])
}
# Step 5: Call batchexecute endpoint
be_url = "https://news.google.com/_/DotsSplashUi/data/batchexecute"
be_headers = {
'content-type': 'application/x-www-form-urlencoded;charset=UTF-8',
'user-agent': headers['User-Agent'],
'origin': 'https://news.google.com',
'referer': 'https://news.google.com/',
}
be_resp = requests.post(be_url, headers=be_headers, data=payload, timeout=10)
be_resp.raise_for_status()
# Step 6: Extract real URL from nested response
# Remove RPC wrapper: )]}'
raw_json = be_resp.text.replace(")]}'", "")
try:
parsed = json.loads(raw_json)
# Navigate: [0][2] → stringified array → [1] = final URL
array_str = parsed[0][2]
url_list = json.loads(array_str)
return url_list[1] # actual article URL
except (IndexError, KeyError, json.JSONDecodeError, TypeError) as e:
raise ValueError(f"Failed to extract URL from batchexecute response: {e}")
# Usage example:
if __name__ == "__main__":
rss_item_link = "https://news.google.com/rss/articles/CBMiogFBVV95cUxQLUFubVFtajlobFdKQllBb1JBRDNPNm8yRE51a0N2STl3SGd6eFY2cEVMdllnM1VwNGRBbWxsa0FLUGViaHNaN2p2R2oyMWFsNklvM3pFdXZFWjNNT1dNN2lrclRzWTlLOEpOLXYzZzdETnFMS0ZUZktvZTREcmU0ZzZucmFYZk0tR1gzTVlEUWh4dXVpMGMxSWltb2x2enl1TEE?oc=5"
try:
real_url = extract_real_article_url(rss_item_link)
print("✅ Real article URL:", real_url)
except Exception as e:
print("❌ Error:", str(e))
⚠️ 重要注意事项:
-
合规性与稳定性:此方法逆向了 Google 前端私有协议,不受官方支持,且极易因前端更新而失效(如
data-p结构、BatchExecute 端点、参数签名规则变化)。生产环境请优先考虑 Google News API(需申请)、RSS 直接订阅(部分媒体提供原生 RSS),或使用合法新闻聚合服务。 - 反爬机制:务必设置合理 User-Agent、Referer 和请求间隔;频繁调用可能触发验证码或 IP 限流。
-
错误处理:示例中已加入基础异常捕获,实际部署时建议添加重试机制(如
tenacity)和日志记录。 -
编码兼容性:
data-p中的%.@.是 Google 特定占位符,不可硬编码为其他字符串;若解析失败,请检查返回 HTML 是否被动态渲染(此时需考虑 Playwright/Selenium,但违背轻量初衷)。
总结:Google RSS 链接本质是“前端跳转令牌”,绕过 JS 重定向的唯一稳健路径是复现其后端跳转协议。本方案提供了可落地的技术实现,但请始终以尊重 robots.txt、服务条款及网站可持续性为前提进行开发。











