はじめに
前回記事に続き、データ収集に関する投稿です。
- ニュースアクセスランキング編
- 今日のニュース編 ★本稿
- 話題のニュース編
- キーワード検索結果のニュース編
今回は、今日のニュースが対象です。
というわけで、Pythonプログラムで取得(スクレイピング)する処理を実現してみようと思います。
※本稿執筆時点(2021/10/07)の情報に基づき、Code紹介と実行例を示します。
本稿で紹介すること
- 今日のニュース(livedoor NEWS)の取得
尚、筆者は以下のVersionで動作確認をしています。
- Python: 3.6.10
- BeautifulSoup4: 4.9.3
本稿で紹介しないこと
- Pythonライブラリのインストール方法および使い方
- urllib.request
- BeautifulSoup4
- re
- pandas
- csv
- traceback
- os
サンプルコード
Code量も多くないので、全体のCodeを紹介。
ポイントは3つ。
1. User-Agentの設定
HTTPリクエストヘッダーにUserAgentを設定するのがベター。
自宅PC(個人環境)なので不要ですが、会社PC(企業環境)であればProxyの設定も同じようにヘッダーに設定するのがベター。
2. 名前付きグループの正規表現
後々、ニュースIDをKeyに記事全文を取得することも視野に、ニュースIDも抽出しておくのがベター。
3. タグ要素の指定
各ページSourceを眺めて、タグ構成を鑑みて要素を指定し、BeautifulSoup4で情報を取得する必要あり。
多くの場合、タグに付与されたclass属性を指定し、目的のタグ(およびその内部のText)を取得する処理を実装することになります。
WebブラウザでページのSourceを眺めて、HTMLタグの構造を把握するのは簡単です。
Codeを紹介
以下、全体のCodeです。
from urllib.request import Request, urlopen
from bs4 import BeautifulSoup
import re
import pandas as pd
import csv
import traceback
import os
# 保管先フォルダの名称
OUTPUT_DIR = 'livedoor_news'
# 今日のニュース(ライブドアニュース)のURL
URL = 'https://news.livedoor.com/straight_news/'
# ニュースID抽出用の正規表現(名前付きグループ)
REG_URL = r'(?P<L1>(https?://[^/]+/))(?P<L2>([^/]+))/(?P<L3>([^/]+))/(?P<L4>([^/]+))/'
# UserAgent
USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.71 Safari/537.36'
def create_folder():
if not os.path.exists(OUTPUT_DIR):
# フォルダが存在しなければ、フォルダを作成
os.makedirs(OUTPUT_DIR)
def get_links():
try:
# HTTPリクエストヘッダーにUser Agentを設定
req = Request(URL, data=None, headers={'User-Agent': USER_AGENT})
with urlopen(req) as res:
# HTMLドキュメントからBeautifulSoupを初期化
soup = BeautifulSoup(res.read().decode('euc_jp', 'ignore'), 'html.parser')
# 今日のニュース部分を検索し、全てを取得
soupNewsStraight = soup.find('ul', class_='straightList').find_all('li')
articles = []
for idx, soupNews in enumerate(soupNewsStraight):
# 詳細ページURLをHTMLタグの属性から抽出
url = soupNews.a.get('href')
# NewsBodyを検索し取得
soupNewsBody = soupNews.find('div', class_='straightBody')
# NewsBodyから各種データを抽出
article = {
'url': url,
# ニュースIDを詳細ページURLから抽出
'id': re.search(REG_URL, url).groupdict()['L4'],
# タイトル/サマリ/提供元/公開日時をHTMLタグの本文から抽出
'title': soupNewsBody.find('h3', class_='straightTtl').text,
'summary': soupNewsBody.find('p', class_='straightSummary').text,
'vender': soupNewsBody.find('p', class_='straightVender').text,
'datetime': soupNews.a.time.get('datetime')
}
articles.append(article)
print('%2d: %s' %(idx + 1, soupNewsBody.find('h3', class_='straightTtl').text))
df = pd.DataFrame(articles)
# DataFrameからCSVファイルを生成
# encoding='sjis'だとJupyterLab(CSVTable)上で表示不可なことに注意
df.to_csv('%s/livedoor_news_straight.csv' %OUTPUT_DIR, encoding='utf-8', index=False, quotechar='"', quoting=csv.QUOTE_ALL)
except Exception as e:
# エラー概要
print('Exception: ', e)
print('=====')
# エラー詳細(スタックトレース)
print(traceback.format_exc().rstrip())
print('=====')
まとめ
BeautifulSoup4を使って今日のニュースを取得(スクレイピング)する方法を紹介。