파이썬으로 Google 뉴스를 스크랩하는 단계별 가이드

댓글: 0

최신 뉴스 헤드라인을 수집하고, 뉴스 트렌드를 모니터링하고, 현재 이슈에 대한 감성 분석을 수행할 때 Google 뉴스 스크래핑은 매우 유용한 도구입니다. 이 문서에서는 Python을 사용하여 Google 뉴스를 스크랩하는 과정을 안내합니다. 페이지 콘텐츠를 얻기 위해 요청 라이브러리를 사용하고, HTML 문서를 파싱하고 필요한 데이터를 추출하기 위해 lxml을 사용합니다. 이 튜토리얼이 끝나면 Google 뉴스에서 뉴스 헤드라인과 해당 링크를 구조화된 JSON 형식으로 추출하는 방법을 배우게 됩니다.

1단계: 환경 설정

시작하기 전에 시스템에 Python이 설치되어 있는지 확인하세요. 다음 명령을 실행하여 필요한 라이브러리를 설치할 수 있습니다:

pip install requests 
pip install lxml

이러한 라이브러리를 통해 HTTP 요청을 하고 웹페이지의 HTML 콘텐츠를 구문 분석할 수 있습니다.

2단계: 타깃 URL 및 XPath 구조 이해

다음 URL에서 Google 뉴스 페이지를 스크랩하겠습니다:

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 뉴스의 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 뉴스 URL에 GET 요청을 전송하고 페이지의 HTML 콘텐츠를 page_content 변수에 저장합니다.

4단계: lxml로 HTML 콘텐츠 구문 분석

HTML 콘텐츠가 준비되면 lxml을 사용하여 페이지를 구문 분석하고 뉴스 헤드라인과 링크를 추출할 수 있습니다.

from lxml import html

# HTML 콘텐츠 구문 분석
parser = html.fromstring(page_content)

5단계: 뉴스 데이터 추출

Google 뉴스는 특정 컨테이너에 기사를 정리합니다. 먼저 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이라는 파일을 생성합니다.

프록시 사용

특히 Google 뉴스와 같이 트래픽이 많은 사이트에서 대량의 데이터를 스크랩할 때 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})

   # 주요 뉴스 및 관련 기사를 뉴스_데이터 목록에 추가합니다.
   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')

요청 및 lxml 라이브러리와 함께 Python을 사용하여 Google 뉴스를 스크랩하면 뉴스 트렌드를 자세히 분석할 수 있습니다. 프록시를 구현하고 요청 헤더를 구성하는 것은 차단을 방지하고 스크래퍼의 안정성을 유지하는 데 매우 중요합니다. 이러한 목적에 이상적인 프록시에는 빠른 속도와 낮은 핑을 제공하는 IPv4 및 IPv6 데이터센터 프록시, ISP 프록시가 포함됩니다. 또한 동적 주거용 프록시는 우수한 신뢰 요소로 인해 매우 효과적입니다.

댓글:

0 댓글