Yahoo!のトップニュースをスクレイピングしてみる

データの活用

こんにちは。今回はYahoo!のトップニュースをスクレイピングしてみます。高校生が考えたモデル化とシミュレーションの続編を期待していた方がいたら申し訳ありません。

Yahoo!のHTMLを取得する

最終的に出来上がるプログラムは短いのですが、小分けにして紹介していきます。

はじめにHTMLを取得します。そのプログラムは次になります。

import requests
from bs4 import BeautifulSoup

url = 'https://www.yahoo.co.jp/'
res = requests.get( url )
soup = BeautifulSoup( res.text, 'html.parser' )

print( soup )

実行結果は次になります。(行数が多いので適当に割愛しています。また見やすいように整形しています。)

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html>
<head>
<meta content="text/html; charset=utf-8" http-equiv="content-type"/>
<meta content="text/css" http-equiv="content-style-type"/>
<meta content="text/javascript" http-equiv="content-script-type"/>
<meta content="日本最大級のポータルサイト。検索、オークション、ニュース、メール、コミュニティ、ショッピング、など80以上のサービスを展開。あなたの生活をより豊かにする「ライフ・エンジン」を目指していきます。" name="description"/>
(中略)
<table border="0" cellpadding="0" cellspacing="4" width="100%">
  <tr>
    <td>
      <font color="#666666" size="-3">12時16分更新</font>
    </td>
  </tr>
  <tr>
    <td>
      <a href="https://news.yahoo.co.jp/pickup/6326134">
        稼ぐ高齢者 年金減額見直しへ
      </a>
    </td>
  </tr>
  <tr>
    <td>
      <a href="https://news.yahoo.co.jp/pickup/6326137">
        尖閣周辺に中国船、58日連続
        <img alt="写真" border="0" height="12" src="//s.yimg.jp/images/top/sp/cgrade/iconPhoto_150713.gif" width="16"/>
      </a>
    </td>
  </tr>
  <tr>
    <td>
      <a href="https://news.yahoo.co.jp/pickup/6326143">
        米軍基地外に拳銃 相次ぐ長崎
        <img alt="写真" border="0" height="12" src="//s.yimg.jp/images/top/sp/cgrade/iconPhoto_150713.gif" width="16"/>
        <img alt="NEW" border="0" height="12" src="//s.yimg.jp/images/top/sp/cgrade/iconNew_150713.gif" width="30"/>
      </a>
    </td>
  </tr>
  <tr>
    <td>
      <a href="https://news.yahoo.co.jp/pickup/6326140">
        充電池ごみ発火 5年間で4倍
        <img alt="NEW" border="0" height="12" src="//s.yimg.jp/images/top/sp/cgrade/iconNew_150713.gif" width="30"/>
      </a>
    </td>
  </tr>
  <tr>
    <td>
      <a href="https://news.yahoo.co.jp/pickup/6326136">
        コンビニ まだ残る本部の圧力
        <img alt="写真" border="0" height="12" src="//s.yimg.jp/images/top/sp/cgrade/iconPhoto_150713.gif" width="16"/>
      </a>
    </td>
  </tr>
  <tr>
    <td>
      <a href="https://news.yahoo.co.jp/pickup/6326139">
        速報 大谷と雄星がMLB初対決
        <img alt="写真" border="0" height="12" src="//s.yimg.jp/images/top/sp/cgrade/iconPhoto_150713.gif" width="16"/>
        <img alt="LIVE" border="0" height="12" src="//s.yimg.jp/images/top/sp/cgrade/iconLive_150713.gif" width="30"/>
      </a>
    </td>
  </tr>
  <tr>
    <td>
      <a href="https://news.yahoo.co.jp/pickup/6326141">
        君の名は。6月30日地上波放送
        <img alt="写真" border="0" height="12" src="//s.yimg.jp/images/top/sp/cgrade/iconPhoto_150713.gif" width="16"/>
      </a>
    </td>
  </tr>
  <tr>
    <td>
      <a href="https://news.yahoo.co.jp/pickup/6326144">
        テリー伊藤 兄書類送検を謝罪
        <img alt="写真" border="0" height="12" src="//s.yimg.jp/images/top/sp/cgrade/iconPhoto_150713.gif" width="16"/>
        <img alt="NEW" border="0" height="12" src="//s.yimg.jp/images/top/sp/cgrade/iconNew_150713.gif" width="30"/>
      </a>
    </td>
  </tr>
  <tr>
    <td>
      <img alt="" height="20" src="//s.yimg.jp/images/clear.gif" width="10"/>
      <a href="https://news.yahoo.co.jp/list/?d=20190609&mc=f&mp=f">
        もっと見る
      </a>
      <img alt="" height="1" src="//s.yimg.jp/images/clear.gif" width="40"/>
      <a href="https://news.yahoo.co.jp/fc">
        記事一覧
      </a>
    </td>
  </tr>
</table>
(後略)

ここまでで、RequestsとBeautifulSoup4という2つのライブラリを用いてHTMLを取得しています。

トップニュースを取得する

なぜか、ブラウザで見ることができるHTMLと違っています。なぜだろう?よくわかりませんがトップニュースにあたる部分はtableとなっています。

id属性やclass属性がないため、記事にあたる部分を取得するためには工夫が必要です。Yahoo!のトップニュースのリンク先は、”news.yahoo.co.jp/pickup”へのリンクが付いています。これを利用してトップニュースのタイトルを取得します。

プログラムは次になります。

9行目で、リンク先に’news.yahoo.co.jp/pickup’を含むものをすべて取り出しています。

11行目のgetText()で記事の見出しを、12行目のattrs['href’]でリンク先を取り出しています。

import requests
from bs4 import BeautifulSoup
import re

url = 'https://www.yahoo.co.jp/'
res = requests.get( url )
soup = BeautifulSoup( res.text, 'html.parser' )

elements = soup.find_all( href = re.compile( 'news.yahoo.co.jp/pickup' ) )
for element in elements:
    text = element.getText()
    link = element.attrs['href']
    print( "'{}','{}'".format( text, link ) )

実行結果は次になります。

'稼ぐ高齢者 年金減額見直しへ','https://news.yahoo.co.jp/pickup/6326134'
'尖閣周辺に中国船、58日連続','https://news.yahoo.co.jp/pickup/6326137'
'米軍基地外に拳銃 相次ぐ長崎','https://news.yahoo.co.jp/pickup/6326143'
'充電池ごみ発火 5年間で4倍','https://news.yahoo.co.jp/pickup/6326140'
'コンビニ まだ残る本部の圧力','https://news.yahoo.co.jp/pickup/6326136'
'速報 大谷と雄星がMLB初対決','https://news.yahoo.co.jp/pickup/6326139'
'君の名は。6月30日地上波放送','https://news.yahoo.co.jp/pickup/6326141'
'テリー伊藤 兄書類送検を謝罪','https://news.yahoo.co.jp/pickup/6326144'

これをcrontabなどで定期的に実行してファイルやデータベースに書き出せば、Yahoo!のトップニュースに掲載されたニュースを蓄えることができます。

今回はこれでおしまいにします。それではまた。

Posted by 春日井 優