You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何用Python抓取Google News特定年份(如2020年)的新闻标题及相关信息

如何用Python抓取Google News特定年份(如2020年)的新闻标题及相关信息

嘿,我完全懂你的困扰!Google News的RSS接口确实有局限性,它默认只返回近期的热门内容,根本没法直接指定年份过滤——这就是为什么你用原有代码抓不到2020年的旧新闻,而网页端滚动能看到,是因为网页用了动态加载的后端接口,RSS根本对接不到那部分数据。下面给你几个可行的解决思路和代码示例:

一、为什么原有RSS方法不生效?

Google News的RSS搜索接口https://news.google.com/rss/search没有公开的参数支持指定年份范围,它默认只返回最近数天/数周的内容,完全触达不到2020年这类历史新闻数据。网页端能加载旧内容,是因为它调用了不同的动态接口,和RSS不是一套体系。

二、解决方案1:构造时间过滤的网页搜索URL,用BeautifulSoup解析

我们可以直接利用Google News的高级搜索语法,构造包含年份范围的搜索URL,然后用requests模拟浏览器请求,再用BeautifulSoup解析网页内容。

代码示例:

import requests
from bs4 import BeautifulSoup
import pandas as pd
from datetime import datetime
import time

class GoogleNewsYearScraper:
    def __init__(self, query, target_year):
        self.query = query
        self.target_year = target_year
        # 设定目标年份的时间范围:1月1日到12月31日
        self.start_date = f"{target_year}-01-01"
        self.end_date = f"{target_year}-12-31"
        # 模拟浏览器请求头,避免被Google拦截
        self.headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"
        }
        self.base_url = "https://news.google.com/search"

    def scrape_single_page(self, page=0):
        # 构造带时间过滤的搜索参数,page控制分页(每10条为一页)
        search_params = {
            "q": f"{self.query} after:{self.start_date} before:{self.end_date}",
            "hl": "en-IN",
            "gl": "IN",
            "ceid": "IN:en",
            "start": page * 10
        }
        response = requests.get(self.base_url, params=search_params, headers=self.headers)
        
        if response.status_code != 200:
            print(f"请求失败,状态码:{response.status_code}")
            return []
        
        soup = BeautifulSoup(response.text, "html.parser")
        articles = soup.find_all("article")
        page_data = []
        
        for article in articles:
            # 提取标题
            title_tag = article.find("h3")
            title = title_tag.get_text(strip=True) if title_tag else "无标题"
            
            # 提取并转换真实链接(处理Google的内部跳转链接)
            link_tag = title_tag.find("a") if title_tag else None
            link = f"https://news.google.com{link_tag['href']}" if (link_tag and link_tag['href'].startswith("/")) else "无链接"
            
            # 提取发布日期
            date_tag = article.find("time")
            if date_tag:
                date_obj = datetime.fromisoformat(date_tag["datetime"].replace("Z", "+00:00"))
                formatted_date = date_obj.strftime("%Y-%m-%d")
            else:
                formatted_date = "无日期"
            
            page_data.append({
                "Title": title,
                "URL link": link,
                "Date": formatted_date
            })
        
        return page_data

    def scrape_all_pages(self, max_pages=5):
        all_news_data = []
        for page_num in range(max_pages):
            print(f"正在抓取第{page_num+1}页...")
            current_page_data = self.scrape_single_page(page_num)
            if not current_page_data:
                break  # 没有更多内容就停止抓取
            all_news_data.extend(current_page_data)
            time.sleep(2)  # 加延迟,避免触发反爬机制
        
        return all_news_data

    def save_to_csv(self):
        all_data = self.scrape_all_pages()
        df = pd.DataFrame(all_data)
        csv_filename = f"{self.query.replace(' ', '_')}_{self.target_year}.csv"
        df.to_csv(csv_filename, index=False)
        print(f"数据已成功保存到 {csv_filename}")

if __name__ == "__main__":
    search_query = "forex rate news"
    target_year = 2020
    scraper = GoogleNewsYearScraper(search_query, target_year)
    scraper.save_to_csv()

代码说明:

  • 用Google搜索的高级语法after:before:精准锁定2020年的时间范围
  • 模拟浏览器的User-Agent,降低被拦截的概率
  • 支持分页抓取,你可以调整max_pages参数控制抓取的页数
  • 自动把Google的内部跳转链接转换为真实新闻链接

三、解决方案2:使用第三方库GoogleNews

如果你不想自己写网页解析逻辑,可以用现成的GoogleNews库,它封装了Google News的接口,能直接支持时间范围过滤。

操作步骤:

  1. 先安装库:
pip install GoogleNews
  1. 代码示例:
from GoogleNews import GoogleNews
import pandas as pd
from datetime import datetime

class GoogleNewsLibraryScraper:
    def __init__(self, query, target_year):
        self.query = query
        self.start_date = f"{target_year}-01-01"
        self.end_date = f"{target_year}-12-31"
        # 初始化GoogleNews对象,设置语言和地区
        self.gn = GoogleNews(hl='en-IN', gl='IN')
        self.gn.set_time_range(self.start_date, self.end_date)

    def scrape_news(self, max_pages=5):
        self.gn.search(self.query)
        all_news_data = []
        for page_num in range(max_pages):
            print(f"正在抓取第{page_num+1}页...")
            page_results = self.gn.page_at(page_num+1)  # 库的分页从1开始计数
            if not page_results:
                break
            for result in page_results:
                # 处理日期格式:尝试转换为标准日期,失败则保留原字符串
                try:
                    date_obj = datetime.strptime(result["date"], "%b %d, %Y")
                    formatted_date = date_obj.strftime("%Y-%m-%d")
                except ValueError:
                    formatted_date = result["date"]
                
                all_news_data.append({
                    "Title": result["title"],
                    "URL link": result["link"],
                    "Date": formatted_date,
                    "Summary": result["desc"]  # 额外提取新闻摘要
                })
        return all_news_data

    def save_to_csv(self):
        all_data = self.scrape_news()
        df = pd.DataFrame(all_data)
        csv_filename = f"{self.query.replace(' ', '_')}_{self.target_year}.csv"
        df.to_csv(csv_filename, index=False)
        print(f"数据已成功保存到 {csv_filename}")

if __name__ == "__main__":
    search_query = "forex rate news"
    target_year = 2020
    scraper = GoogleNewsLibraryScraper(search_query, target_year)
    scraper.save_to_csv()

注意事项:

  • GoogleNews库有时会返回相对时间(比如"2 years ago"),如果需要精确的2020年日期,可能需要额外处理,或者结合第一种网页解析的方式
  • 第三方库可能会随着Google News界面更新而失效,记得定期检查版本更新

四、重要提醒

  • Google有严格的反爬机制,不要过于频繁地发送请求,建议每次请求之间加2-5秒的延迟
  • 如果遇到验证码或被封禁,可以尝试更换User-Agent,或者使用代理(注意合规)
  • 确保你的抓取行为符合Google的服务条款,不要用于大规模商业爬取

备注:内容来源于stack exchange,提问作者Charmi Divecha

火山引擎 最新活动