使用 Python 浏览 Google 新闻的分步指南

评论: 0

在收集最新的新闻标题、监控新闻趋势以及对当前事件进行情感分析时,搜索 Google News 被证明是一种无价的工具。在本文中,我们将指导您使用 Python 浏览 Google 新闻。我们将使用请求库获取页面内容;使用 lxml 解析 HTML 文档并提取所需数据。本教程结束时,您将学会如何将 Google News 中的新闻标题及其相应链接提取为结构化的 JSON 格式。

步骤 1:设置环境

开始之前,请确保您的系统已安装 Python。运行以下命令即可安装所需的库:

pip install requests 
pip install lxml

通过这些库,我们可以发出 HTTP 请求并解析网页的 HTML 内容。

第 2 步:了解目标 URL 和 XPath 结构

我们将从以下网址抓取谷歌新闻页面:

URL = "https://news.google.com/topics/CAAqKggKIiRDQkFTRlFvSUwyMHZNRGRqTVhZU0JXVnVMVWRDR2dKSlRpZ0FQAQ?hl=en-US&gl=US&ceid=US%3Aen"

本页包含多个新闻条目,每个条目都有一个主标题和相关文章。这些项目的 XPath 结构如下:

  • 主要新闻集装箱: //c-wiz[@jsrenderer="ARwRbe"]
  • 主要新闻标题: //c-wiz[@jsrenderer="ARwRbe"]/c-wiz/div/article/a/text()
  • 主要新闻链接: //c-wiz[@jsrenderer="ARwRbe"]/c-wiz/div/article/a/@href
  • 相关新闻集装箱: //c-wiz[@jsrenderer="ARwRbe"]/c-wiz/div/div/article/
  • 相关新闻标题: //c-wiz[@jsrenderer="ARwRbe"]/c-wiz/div/div/article/a/text()
  • 相关新闻链接: //c-wiz[@jsrenderer="ARwRbe"]/c-wiz/div/div/article/a/@href

Google News 的 HTML 结构在不同页面上保持一致,确保指定的 XPath 元素普遍适用。

步骤 3:获取 Google 新闻内容

首先,我们将使用请求库获取 Google 新闻页面的内容。下面是获取页面内容的代码:

import requests

url = "https://news.google.com/topics/CAAqKggKIiRDQkFTRlFvSUwyMHZNRGRqTVhZU0JXVnVMVWRDR2dKSlRpZ0FQAQ?hl=en-US&gl=US&ceid=US%3Aen"
response = requests.get(url)

if response.status_code == 200:
    page_content = response.content
else:
    print(f"Failed to retrieve the page. Status code: {response.status_code}")

这段代码会向 Google News URL 发送 GET 请求,并将页面的 HTML 内容存储在 page_content 变量中。

步骤 4:使用 lxml 解析 HTML 内容

有了 HTML 内容,我们就可以使用 lxml 来解析页面并提取新闻标题和链接。

from lxml import html

# 解析 HTML 内容
parser = html.fromstring(page_content)

步骤 5:提取新闻数据

谷歌新闻将文章组织在特定的容器中。我们将首先使用 XPath 提取这些容器,然后遍历这些容器以提取单个新闻标题和链接。

提取主要新闻报道

主要新闻文章位于以下 XPath 下:

main_news_elements = parser.xpath('//c-wiz[@jsrenderer="ARwRbe"]')

现在,我们可以循环浏览前 10 个有效元素,并提取标题和链接:

news_data = []

for element in main_news_elements[:10]:
    title = element.xpath('.//c-wiz/div/article/a/text()')[0]
    link = "https://news.google.com" + element.xpath('.//c-wiz/div/article/a/@href')[0][1:]

    
    # 在向列表添加数据之前确保数据存在
    if title and link:
        news_data.append({
        "main_title": title,
        "main_link": link,
    })

在每个主要新要素中提取相关文章

主新闻元素有相关新闻的子部分。我们可以使用类似的方法提取这些内容:

related_articles = []
related_news_elements = element.xpath('.//c-wiz/div/div/article')

for related_element in related_news_elements:
    related_title = related_element.xpath('.//a/text()')[0]
    related_link = "https://news.google.com" + related_element.xpath('.//a/@href')[0][1:]
    related_articles.append({"title": related_title, "link": related_link})

news_data.append({
    "main_title": title,
    "main_link": link,
    "related_articles": related_articles
})

第 6 步:将数据保存为 JSON 格式

提取数据后,我们可以将其保存到 JSON 文件中,以供日后使用。

import json

with open('google_news_data.json', 'w') as f:
    json.dump(news_data, f, indent=4)

这段代码将创建一个名为 google_news_data.json 的文件,其中包含所有搜索到的新闻标题及其相应链接。

使用代理

在抓取大量数据时,尤其是从谷歌新闻等高流量网站抓取数据时,可能会遇到 IP 屏蔽或速率限制等问题。要避免这种情况,可以使用代理。代理允许你通过不同的 IP 地址路由你的请求,使网站更难检测和阻止你的搜刮活动。

在本教程中,您可以通过修改 requests.get 调用来使用代理:

proxies = {
    "http": "http://your_proxy_ip:port",
    "https": "https://your_proxy_ip:port",
}

response = requests.get(url, proxies=proxies)

如果与管理代理轮换的服务提供商合作,只需在请求中配置服务即可。服务提供商将在其端处理轮换和 IP 池管理。

自定义请求标头

有时,网站可能会阻止没有适当标头(如用户代理字符串,用于识别请求来自浏览器)的请求。你可以自定义标头,以避免被发现:

headers = {
    'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
    'accept-language': 'en-IN,en;q=0.9',
    'cache-control': 'no-cache',
    'dnt': '1',
    'pragma': 'no-cache',
    'priority': 'u=0, i',
    'sec-ch-ua': '"Not)A;Brand";v="99", "Google Chrome";v="127", "Chromium";v="127"',
    'sec-ch-ua-arch': '"x86"',
    'sec-ch-ua-bitness': '"64"',
    'sec-ch-ua-full-version-list': '"Not)A;Brand";v="99.0.0.0", "Google Chrome";v="127.0.6533.72", "Chromium";v="127.0.6533.72"',
    'sec-ch-ua-mobile': '?0',
    'sec-ch-ua-model': '""',
    'sec-ch-ua-platform': '"Linux"',
    'sec-ch-ua-platform-version': '"6.5.0"',
    'sec-ch-ua-wow64': '?0',
    'sec-fetch-dest': 'document',
    'sec-fetch-mode': 'navigate',
    'sec-fetch-site': 'none',
    'sec-fetch-user': '?1',
    'upgrade-insecure-requests': '1',
    'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36',
}

response = requests.get(url, headers=headers)

完整代码示例

下面是完整的代码,综合了所有步骤:

import requests
import urllib3
from lxml import html
import json

urllib3.disable_warnings()

# URL 和页眉
url = "https://news.google.com/topics/CAAqKggKIiRDQkFTRlFvSUwyMHZNRGRqTVhZU0JXVnVMVWRDR2dKSlRpZ0FQAQ?hl=en-US&gl=US&ceid=US%3Aen"
headers = {
   'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
   'accept-language': 'en-IN,en;q=0.9',
   'cache-control': 'no-cache',
   'dnt': '1',
   'pragma': 'no-cache',
   'priority': 'u=0, i',
   'sec-ch-ua': '"Not)A;Brand";v="99", "Google Chrome";v="127", "Chromium";v="127"',
   'sec-ch-ua-arch': '"x86"',
   'sec-ch-ua-bitness': '"64"',
   'sec-ch-ua-full-version-list': '"Not)A;Brand";v="99.0.0.0", "Google Chrome";v="127.0.6533.72", "Chromium";v="127.0.6533.72"',
   'sec-ch-ua-mobile': '?0',
   'sec-ch-ua-model': '""',
   'sec-ch-ua-platform': '"Linux"',
   'sec-ch-ua-platform-version': '"6.5.0"',
   'sec-ch-ua-wow64': '?0',
   'sec-fetch-dest': 'document',
   'sec-fetch-mode': 'navigate',
   'sec-fetch-site': 'none',
   'sec-fetch-user': '?1',
   'upgrade-insecure-requests': '1',
   'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36',
}

# 代理配置(用代理详细信息代替)
proxy = 'ip:port'
proxies = {
   "http": f"http://{proxy}",
   "https": f"https://{proxy}",
}

# 使用指定的标头和代理获取页面内容
response = requests.get(url, headers=headers, proxies=proxies, verify=False)

# 检查请求是否成功
if response.status_code == 200:
   page_content = response.content
else:
   print(f"Failed to retrieve the page. Status code: {response.status_code}")
   exit()

# 使用 lxml 解析 HTML 内容
parser = html.fromstring(page_content)

# 摘录主要新闻和相关文章
main_news_elements = parser.xpath('//*[@id="i10-panel"]/c-wiz/c-wiz')

# 初始化一个列表,用于存储提取的新闻数据
news_data = []

# 循环浏览每个主要新闻元素
for element in main_news_elements[:10]:
   # 提取主要新闻标题和链接
   title = element.xpath('.//c-wiz/div/article/a/text()')
   link = element.xpath('.//c-wiz/div/article/a/@href')

   # 初始化一个列表,用于存储该主要新闻的相关文章
   related_articles = []

   # 提取同一区块内的相关新闻元素
   related_news_elements = element.xpath('.//c-wiz/div/div/article')

   # 循环浏览每个相关新闻元素,提取标题和链接
   for related_element in related_news_elements:
       related_title = related_element.xpath('.//a/text()')[0]
       related_link = "https://news.google.com" + related_element.xpath('.//a/@href')[0][1:]
       related_articles.append({"title": related_title, "link": related_link})

   # 将主要新闻及其相关文章添加到 news_data 列表中
   if title is not None:
       news_data.append({
           "main_title": title,
           "main_link": f'https://news.google.com{link}',
           "related_articles": related_articles
       })
   else:
       continue


# 将提取的数据保存为 JSON 文件
with open("google_news_data.json", "w") as json_file:
   json.dump(news_data, json_file, indent=4)

print('Data extraction complete. Saved to google_news_data.json')

使用 Python 以及 requests 和 lxml 库抓取 Google 新闻,有助于对新闻趋势进行详细分析。实施代理和配置请求标头对于避免阻塞和保持抓取稳定性至关重要。理想的代理服务器包括 IPv4 和 IPv6 数据中心代理服务器以及 ISP 代理服务器,它们提供高速度和低 ping。此外,动态住宅代理服务器因其卓越的信任因素而非常有效。

评论:

0 评论