Python

【Python】Pythonでスクレイピング

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名の中の、クラス名を取得しています。

COMMENT

メールアドレスが公開されることはありません。