目次
Pythonでスクレイピングしてみよう
スクレイピングとは?
スクレイピングとは、web上に公開されているページからHTMLなどを解析して、欲しいデータを取得する手法です。
webページは、HTMLで書かれているので、多くの記事ではHTMLの取得方法が紹介されていますが、CSVファイルなど、web上に上げられているファイルならば、なんでも可能です。
本記事の目標
・requestsを用いて、
URLからwebページのHTMLを取得できる
・BeautifulSoupを用いて、
HTMLを解析し、欲しいデータだけを取得できる
requests?クローリング?ってなる方が多いかもしれませんが、詳しく書いていくので、ぜひ読者の皆さんも手を動かしながら、読み進めていってください!
では、、いきなりコードを書いて動かせないので、まずは環境構築をしていきます。
上記のrequests、BeautifulSouがインストール済みの方は、環境構築を読み飛ばしてもらって大丈夫です!
完成形のディレクトリ構造
Python
├── lib_beautifulSoup.py
├── lib_requests.py
├── outPut.html
└── outPut.txt
あらかじめ必要なファイルを全て作っておきましょう!
今回はライブラリごとに、完結するようなコードを用意しているので、ファイルを3つ用意しました。
outPut.txtとoutPut.htmlは、取得したデータを書き出すために用意しました。
環境構築
まずは、homebrewをインストールします。
$ /usr/bin/ruby -e “$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)”
インストールしたhomebrewを用いて、python3をインストールします。
$ brew install python3
ここからは、必要なライブラリをインストールしていきます。
$ pip3 install requests
$ pip3 install beautifulsoup4
requestsでURLからwebページのHTMLを取得する
目標の確認
まずは、requestsというライブラリを使って取得したいページのHTMLを全て取得したいと思います。
実際に取得したHTMLをoutPut.htmlに 書き出していきます。
上にも記述しましたが対象ページは、https://news.yahoo.co.jpです。
完成コード
import requests
url = "https://news.yahoo.co.jp"
# HTMLの取得と表示
response = requests.get(url)
response.encoding = response.apparent_encoding
html = response.text
# ファイルへの書き出し
with open("scraping/outPut.html", mode="w", encoding="utf-8") as file:
file.write(html)
基本的なファイルへの書き出し処理のフローは、
①ファイルを開く
②ファイルに書き込む
③ファイルを閉じる
で、以下のようになります。
file = open("outPut.txt", "w")
file.write("こんにちは")
file.close()
with構文を使うと、最後のファイルを閉じる処理(file)を書かなくて済みます。
with open("outPut.txt", mode="w") as file:
file.write("こんにちは")
ファイルを閉じる処理が自動化されて明示しなくて済むので、僕は下の書き方をしてます。
outPut.htmlを確認してみてください。
非常に長いので、ここでは紹介しませんが取得できていればファイル内が大量のコードで埋め尽くされているはずです。
でもスクレイピングの醍醐味は、web上の大量のデータから欲しいデータだけを抽出することです。
今のままでは、欲しいデータがどこにあるかわかりません。
そこで、BeautifulSoupというライブラリを使って、HTML内を検索し、欲しいデータだけを抽出していきます!
BeautifulSoupで欲しいデータのみを取得する
目標の確認
では、実際にニュースのタイトルだけを取得するプログラムを書いていきます。
HTML内の特定のデータだけを取得するには、HTMLのタグを指定する必要があります。
そこで使うのが、BeautifulSoupというライブラリです。
今回、実際に取得する部分は以下の部分です。

検証ツールを使って、どの要素、どのクラスを指定すれば良いのか、確認してみてください。
もしかしたら、クラス名が変わっているかもしれないので確認をお願いします。
完成コード
import requests
from bs4 import BeautifulSoup
url = "https://news.yahoo.co.jp"
# HTTPリクエストを送り、レスポンスを得る
response = requests.get(url)
response.encoding = response.apparent_encoding
# 解析を可能にする
yahoo = BeautifulSoup(response.text, "html.parser")
# selectを指定するとレスポンスはリスト型
a_tags = yahoo.select(".topicsListItem > a")
# ファイルへの書き出し
with open("scraping/outPut.txt", mode="a", encoding="utf-8") as file:
for title in a_tags:
file.write(title.text + "\n")
BeautifulSoupのチートシート
タグでの検索
# 最初のaタグを取得
soup.find("a")
soup.a
※2つはどちらも同じ動きをします
# aタグ内のテキストを取得
soup.find("a").text
soup.a.text
# 全てのaタグを取得
soup.find_all("a")
soup("a")
# ※リスト型で返ってきます!
# 全てのaタグのテキストのみを取得
[ a_tag.text for a_tag in soup.find_all("a") ]
# ※テキストのみをリスト型で返します!
属性で検索
# class属性で取得
soup.find(class_ = "クラス名")
# class属性に一致する全てのタグを取得
soup(class_ = "クラス名")
soup.find_all("class_ = クラス名")
# id属性で取得
soup.find(id = "id名")
# id属性に一致する全てのタグを取得
soup(id = "id名")
soup.find_all(id = "id名"
複数条件で検索
複数の条件を指定したい場合は、カンマで区切って記述すればOKです。
CSSセレクタ型で検索
ここからは、もう少し簡単な書き方を紹介します。
ここまでで基本的な取得の仕方は紹介しました。
しかし、取得する際に、ネストが深かったりした場合がめんどくさいなーと思った方もいるかもしれません。
soup.select("a > #id名 > .クラス名")
簡単に説明すると、aタグ内のid名の中の、クラス名を取得しています。