
Google 新闻 RSS Feed 返回的链接是动态重定向 URL,直接请求会返回 JavaScript 重定向页而非目标文章;需通过模拟 Google 的 batchexecute 接口解析 data-p 参数并发起 POST 请求,才能获取原始文章 URL。
google 新闻 rss feed 返回的链接是动态重定向 url,直接请求会返回 javascript 重定向页而非目标文章;需通过模拟 google 的 `batchexecute` 接口解析 `data-p` 参数并发起 post 请求,才能获取原始文章 url。
Google 新闻(news.google.com/rss/...)提供的 RSS 源看似标准,但其 <link> 标签中嵌入的并非真实文章地址,而是 Google 自有的中间跳转链接(形如 https://news.google.com/rss/articles/...?oc=5)。这类链接在浏览器中可正常跳转,是因为前端 JS 执行了 garturlreq 请求;而用 requests.get() 直接访问时,服务器仅返回含重定向逻辑的 HTML/JS 片段,不会自动执行 JavaScript,因此无法获得最终目标 URL。
解决该问题的核心思路是:逆向还原 Google 前端的重定向逻辑。实际流程如下:
-
获取 RSS 中的 Google 跳转链接(如
https://news.google.com/rss/articles/...?oc=5); -
请求该链接,解析返回 HTML 中
<c-wiz data-p="..."></c-wiz>的data-p属性值; -
清洗并解析
data-p字符串为 JSON 结构(需替换%.@.为["garturlreq",); -
构造
f.req参数,调用https://news.google.com/_/DotsSplashUi/data/batchexecute接口; -
从响应中提取嵌套的 JSON,定位到真正的原始文章 URL(通常位于
response[0][2]解析后的[1]位置)。
以下是完整、可运行的 Python 示例(依赖 requests 和 beautifulsoup4):
import requests
import json
from bs4 import BeautifulSoup
def get_original_article_url(google_rss_link: str) -> str:
# Step 1: Fetch the Google 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(google_rss_link, headers=headers, timeout=10)
resp.raise_for_status()
# Step 2: Parse data-p from c-wiz tag
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
cleaned = data_p.replace('%.@.', '["garturlreq",')
try:
obj = json.loads(cleaned)
except json.JSONDecodeError as e:
raise ValueError(f"Invalid data-p format: {e}")
# Step 4: Build f.req payload (keep last 2 elements, drop middle 6)
payload_obj = obj[:-6] + obj[-2:]
f_req_payload = [[['Fbv4je', json.dumps(payload_obj), 'null', 'generic']]]
payload = {
'f.req': json.dumps(f_req_payload)
}
# Step 5: Call batchexecute
batch_url = "https://news.google.com/_/DotsSplashUi/data/batchexecute"
batch_resp = requests.post(
batch_url,
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/',
},
data=payload,
timeout=10
)
batch_resp.raise_for_status()
# Step 6: Extract real URL
raw = batch_resp.text
if raw.startswith(")]}'"):
raw = raw[4:] # Strip batchexecute prefix
try:
parsed = json.loads(raw)
# Navigate: [0][2] is the main response string → parse again → [1] is the URL
url_string = parsed[0][2]
final_url = json.loads(url_string)[1]
return final_url
except (IndexError, KeyError, json.JSONDecodeError, TypeError) as e:
raise ValueError(f"Failed to extract article URL: {e}")
# ✅ 使用示例
if __name__ == "__main__":
sample_rss_link = "https://news.google.com/rss/articles/CBMiogFBVV95cUxQLUFubVFtajlobFdKQllBb1JBRDNPNm8yRE51a0N2STl3SGd6eFY2cEVMdllnM1VwNGRBbWxsa0FLUGViaHNaN2p2R2oyMWFsNklvM3pFdXZFWjNNT1dNN2lrclRzWTlLOEpOLXYzZzdETnFMS0ZUZktvZTREcmU0ZzZucmFYZk0tR1gzTVlEUWh4dXVpMGMxSWltb2x2enl1TEE?oc=5"
try:
original_url = get_original_article_url(sample_rss_link)
print("✅ Original article URL:", original_url)
except Exception as e:
print("❌ Error:", e)⚠️ 重要注意事项:
-
反爬与频率限制:Google 明确禁止自动化抓取其新闻服务。高频请求可能导致 IP 封禁或
429 Too Many Requests。建议添加随机延迟(time.sleep(random.uniform(1, 3)))、轮换 User-Agent,并优先使用官方 API(如 Google News API 或第三方合规聚合服务)。 -
URL 稳定性:
data-p结构和batchexecute接口属于内部实现,可能随时变更。本方案需定期验证与维护。 - 法律与合规性:请务必查阅 Google 的 robots.txt 及 Terms of Service,确保用途符合合理使用原则(如个人学习、非商业研究)。
-
备用方案:若稳定性要求高,推荐改用 RSS 解析后对目标站点(如
bbc.com,reuters.com)直接抓取——即先提取 RSS 中的<source></source>或域名信息,再针对性请求原文。
综上,这不是简单的 HTTP 重定向问题,而是需深度模拟前端行为的协议级解析。理解其机制后,你不仅能获取真实链接,还能为其他类似“JS 重定向保护”的 RSS/聚合源提供通用解法思路。


















