Scraping news of incidents on livedoor

世の中で起こる事件に興味があるので、ライブドアニュースで日々更新される事件・事故のニュースをスクレイピングすることにしました。流れの自分用メモです。
[livedoor NEWS 国内の事件・事故](https://news.livedoor.com/%E5%9B%BD%E5%86%85%E3%81%AE%E4%BA%8B%E4%BB%B6%E3%83%BB%E4%BA%8B%E6%95%85/topics/keyword/31673/)

##1. scrapingとは何かを知る
[pythonでwebスクレイピング](https://qiita.com/pontyo4/items/264b03d1f718fb55eb08)
←このサイトでとりあえず基本の動きを確認。
##2. livedoor NEWSのサイトで試す
上のサイトはyahooのプロ野球選手打率で実験していたのでそれをlivedoor NEWSのサイトで再現してみると、問題が発生した。。
上のサイトの要領でアクセスおよび情報の取得を試みるも、アクセスが許可されない。

```
403 Forbidden
Forbidden
You don't have permission to access /国内の事件・事故/topics/keyword/31673/
on this server.
```

次のサイトを読んで解決。[【Python】スクレイピングで403 Forbidden：You don’t have permission to access on this serverが出た際の対処法](https://non-dimension.com/solution-403forbidden/)
サイトにもよるが、livedoor NEWSはどうやらリクエスト時にヘッダーにユーザーエージェントが記載されていないとアクセスできない様子。修正した。


##3. ニュースのリンク先に飛びたい
livedoor NEWSのサイトにアクセスして情報をファイルに書き込むところまでは無事完了。
次にやりたいのは、ニュース一覧のページからリンクを踏んでそれぞれのニュースのページに飛びたい。
ニュース一覧のページの一つのニュースのブロックは以下のようになっていて、aタグのhrefの値がリンク。これを取得するにはどうしたらいいか。

```
<li class="hasImg">
  <a href="https://news.livedoor.com/topics/detail/18794424/">
    <p class="articleListImg"><img src="https://sl.news.livedoor.com/a8affe16ad083d6f44918377f5748e09849ffbc0/small_light(p=S80)/https://image.news.livedoor.com/newsimage/stf/3/f/3f701_1675_218e1f3c1a51c13c80249b4bd8af0afe-m.jpg" onMouseDown="return false;" onSelectStart="return false;" oncontextmenu="return false;" galleryimg="no"></p>
    <div class="articleListBody">
      <h3 class="articleListTtl">持続化給付金を詐取した疑いで3人を逮捕 総額4億円を不正受給か</h3>
      <p class="articleListSummary">ほかにもフリーターや学生ら約400人が不正申請に関与した疑いがあるという</p>
      <time datetime="2020-08-26 16:57:08" class="articleListDate">16時57分</time>
    </div>
  </a>
</li>
```

次のサイトをみて解決。[【Python】BeautifulSoupでhrefの値を取得する](https://naruport.com/blog/2019/12/27/bs4-href/)

```
#まず
link = soup.find('a')
#からの
link.get('href')
#でリンクゲット！
```
意外と簡単にできた。

##4. 完成
以下が一応完成したプログラム。それなりに使えるレベルではある。
ただ、一覧のページは2ページ目、3ページ目とあるので過去2日分くらいのニュースを取って来れるように改良したい。また、全ての記事を取ってくるのに数分かかるので、もっと早く取って来れるような改良ができたらより良い。

```
import requests
import time
from bs4 import BeautifulSoup

def Get_soup( url ):
    headers = {
        "User-Agent" : "Mozilla/... Chrome/... Safari/..."
    }

    response = requests.get(url , headers = headers)

    response.encoding = response.apparent_encoding

    return BeautifulSoup(response.text, "html.parser")

def Get_article( url , f ):
    soup = Get_soup( url )

    title = soup.find( 'h1' , class_ = "articleTtl" )

    f.write( title.text )

    body = soup.find( 'div' , class_ = "articleBody" )
    
    f.write( body.text )

    f.write('@@@@@\n')

    time.sleep(1)


def go_through( url , f  ):
    soup = Get_soup( url )

    footer = soup.find( 'div' , class_ = "articleFooter" )
    
    link = footer.find('a')

    url_ = link.get('href')

    Get_article(url_ , f )


def main():
    url = "https://news.livedoor.com/%E5%9B%BD%E5%86%85%E3%81%AE%E4%BA%8B%E4%BB%B6%E3%83%BB%E4%BA%8B%E6%95%85/topics/keyword/31673/"

    soup = Get_soup( url )

    topic_date_ = soup.find( 'h2' , class_ = "keywordDate" )
    topic_date_ = topic_date_.text
    title = 'CaseNews_' +  topic_date_ + '.txt'
    f = open( title , 'w' )

    articles_ = soup.find( 'ul' , class_ = "articleList" )

    articles = articles_.find_all( 'li' )

    art_len = len(articles)
    dl_count = 1
    for art_i in articles:
        link_i_ = art_i.find('a')
        url_i_ = link_i_.get('href')
        go_through(url_i_ , f )

        print( dl_count , end = '/' )
        print( art_len , end = ' ' )
        print('downloaded.' , end = '\n' )
        dl_count += 1
        # go_through: 本記事の手前のリンク先サイトを乗り越える関数

    f.close()

main()
```