news_summarizer / news_scraper.py
Kota Takahashi
説明文を修正
44bec05
import requests
from bs4 import BeautifulSoup
import re
from time import sleep
class Scraper:
def __init__(self):
"""
Scraperクラスを初期化し、requestsセッションを作成
"""
self.session = requests.Session()
def _fetch_content(self, url):
"""
指定されたURLのコンテンツを取得する
Parameters:
- url (str): 取得するウェブページのURL
Returns:
- content (bytes): 取得したコンテンツのデータ
"""
response = self.session.get(url)
response.raise_for_status() # HTTPエラーが発生した場合は例外を投げる
return response.content
def _parse_html(self, html):
"""
HTMLコンテンツをBeautifulSoupでパース
Parameters:
- html (bytes): パースするHTMLコンテンツ
Returns:
- soup (BeautifulSoup): パースされたBeautifulSoupオブジェクト
"""
soup = BeautifulSoup(html, 'html.parser')
return soup
class YahooNewsScraper(Scraper):
base_url = "https://news.yahoo.co.jp/"
def get_news_urls(self):
"""
Yahooニュースのトップページから最新ニュース記事のURLを取得
Parameters:
- なし
Returns:
- article_url_list (list): ニュース記事のURLリスト(最大5件)
"""
content = self._fetch_content(self.base_url)
soup = self._parse_html(content)
news_list = soup.select('section.topics a') # 'topics'セクション内のすべての<a>タグを選択
article_url_list = [tag.get('href') for tag in news_list if tag.get('href')] # href属性を抽出
return article_url_list[:5] # 最初の5つのURLを返す
def get_article_url(self, index=0):
"""
指定したインデックスのニュース記事のURLを取得する
Parameters:
- index (int): 取得したい記事のインデックス (デフォルトは0)
Returns:
- article_url (str): 指定されたインデックスの記事のURL
Raises:
- IndexError: インデックスが範囲外の場合に発生
"""
article_urls = self.get_news_urls()
if index >= len(article_urls):
raise IndexError("URLが取得できませんでした") # インデックスが範囲外の場合は例外を投げる
return article_urls[index]
def get_article_detail_url(self, article_url):
"""
記事ページから詳細記事のURLを取得する
Parameters:
- article_url (str): ニュース記事のURL
Returns:
- detail_url (str): 記事の詳細ページのURL
Raises:
- ValueError: 詳細ページのURLが見つからない場合に発生
"""
content = self._fetch_content(article_url)
soup = self._parse_html(content)
detail_url_tag = soup.select_one('a:-soup-contains("記事全文を読む")') # "記事全文を読む"を含むリンクを選択
if detail_url_tag:
return detail_url_tag.get('href') # タグのhref属性を返す
else:
raise ValueError("ニュース記事が見つかりませんでした") # タグが見つからない場合はエラーを出力
def get_full_article_text(self, detail_url):
"""
詳細記事の全文を取得し、不要な文字を削除する
Parameters:
- detail_url (str): 記事の詳細ページのURL
Returns:
- full_text (str): 記事の全文テキスト
"""
content = self._fetch_content(detail_url)
soup = BeautifulSoup(content, 'html.parser')
paragraphs = soup.select('article div.article_body p') # 記事本文内のすべての<p>タグを選択
full_text = ''.join([p.text for p in paragraphs]) # すべての段落のテキストを結合
return re.sub(r"[\u3000\n\r]", "", full_text) # 不要な文字を削除
def scrape_article(self, index=0):
"""
指定されたインデックスの記事をスクレイプし、全文を取得する
Parameters:
- index (int): スクレイプする記事のインデックス (デフォルトは0)
Returns:
- full_text (str): スクレイプされた記事の全文テキスト
"""
article_url = self.get_article_url(index)
sleep(1) # サーバー負荷を避けるために1秒待機
detail_url = self.get_article_detail_url(article_url)
sleep(1) # サーバー負荷を避けるためにさらに1秒待機
article_text = self.get_full_article_text(detail_url)
return article_text, detail_url