Spaces:
Sleeping
Sleeping
File size: 4,887 Bytes
a08962e |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 |
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
|