Пошаговое руководство по скрапингу Google News с помощью Python

Комментарии: 0

Скрапинг Google News может быть крайне полезным для сбора данных о последних новостных заголовках, и мониторинга трендов в новостях для проведения их анализа. В этой статье мы покажем, как осуществлять скрапинг Google News с использованием Python. Для этого воспользуемся библиотекой requests для получения содержимого страницы и lxml для парсинга HTML и извлечения необходимых данных.

Шаг 1: Настройка среды

Прежде чем начать, убедитесь, что на вашем компьютере установлен Python. Для установки необходимых библиотек выполните следующие команды:


pip install requests 
pip install lxml

Эти библиотеки позволят отправлять HTTP-запросы и анализировать HTML-содержимое веб-страниц.

Шаг 2: Понимание целевого URL и структуры XPath

Для скрапинга будет использоваться страница Google News, содержащая множество новостных статей:


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.

HTML-структура сайта Google News не меняется между страницами, поэтому перечисленные XPath-элементы будут актуальны для каждой из них.

Шаг 3: Извлечение содержимого страницы Google News

Процесс начинается с запроса страницы Google News с использованием библиотеки requests. Ниже представлен код для получения HTML-контента страницы:


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}")

В этом примере, если HTTP-запрос успешен, содержимое страницы сохраняется в переменной page_content. Это позволяет дальше работать с HTML-контентом для извлечения данных.

Шаг 4: Парсинг HTML-содержимого с помощью lxml

После получения HTML-содержимого страницы, следующий шаг — его анализ с помощью библиотеки lxml для извлечения необходимой информации, такой как заголовки новостей и соответствующие ссылки.


from lxml import html

# Парсинг HTML-содержимого
parser = html.fromstring(page_content)

Шаг 5: Извлечение новостных данных

После успешного парсинга HTML-страницы, следующий этап заключается в извлечении информации из контейнеров новостей на Google News. Это делается путем использования XPath для локализации этих контейнеров и последующего доступа к заголовкам новостей и их ссылкам внутри каждого контейнера.

Извлечение основных новостных статей

Для получения данных из основных новостных статей, сначала необходимо определить их расположение в HTML-структуре страницы Google News с использованием XPath.


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

После определения корректного XPath, можно перейти к извлечению заголовков и ссылок первых десяти статей.


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
})

Сохранение данных в формате 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-адресов и ограничений на частоту запросов при скрапинге сайтов с высокой посещаемостью, таких как Google News. Прокси позволяют маршрутизировать запросы через различные IP-адреса, что затрудняет обнаружение и блокировку активности скрапинга. Ниже представлен пример настройки прокси в запросах Python с использованием библиотеки requests:


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

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

Если вы используете сервис, который управляет ротацией прокси, вам необходимо только включить параметры прокси в ваши запросы. Сервис автоматически будет обрабатывать ротацию IP-адресов, минимизируя риск блокировки.

Настройка заголовков запросов для избежания обнаружения

Некоторые сайты могут отклонять запросы, если в них отсутствуют определенные заголовки, такие как User-Agent, который идентифицирует запросы, поступающие из браузеров. Настройка заголовков позволяет имитировать запросы, исходящие от реальных пользователей, тем самым снижая вероятность обнаружения скрапинга.


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}",
}

# Отправка GET-запроса для получения содержимого HTML
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()

# Парсинг HTML-содержимого с помощью lxml
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})

   # Добавление основной новости и ее связанных статей в список данных
   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')

Скрапинг Google News с помощью Python и библиотек requests и lxml позволяет глубоко анализировать новостные тренды. Важно использовать прокси и настроить заголовки запросов для предотвращения блокировок и обеспечения стабильности работы скрапера. Наиболее подходящие для веб-скрапинга прокси: датацентр IPv4 и IPv6, ISP прокси, которые обеспечивают высокую скорость соединения и низкий пинг, а также динамические резидентские прокси с наиболее высоким показателем траст-фактора.

Комментарии:

0 комментариев