PythonでLet's Webスクレイピング！　①任意の要素の抽出

#はじめに
Webスクレイピングとは、Webサイトから情報を抽出する技術です。

本記事は、Webスクレイピングを始めたい方を対象に入門編として取り纏めたものになります。
長くなりそうなので何回かに分けて投稿したいと思います。

今回は初回なので、そもそものお話から任意の要素を抽出する方法についての内容になります。

気軽にご覧ください^^

#※処理環境※
本記事に記載のコードは以下の環境で動作検証をしています。
OS：Windows10
Python：3.6.5
（beautifulsoup4：4.6.3）

#WebスクレイピングといえばPython？
「Webスクレイピング」で検索するとPythonを使ったサイトがよくヒットします。

PythonでないとWebスクレイピングができない、ということでは全くないのですが、PythonではWebスクレイピング処理に関するライブラリが充実しているため、Pythonを勧める人が多いようです。

詳細は、以下の記事が参考になると思います。
[Webスクレイピングするなら何言語？Python、Ruby、またはJavaScript？](https://qiita.com/Octoparse_Japan/items/14304b5bd9fb84945ec3)

本記事では、PythonのWebスクレイピングのライブラリで有名なBeautifulSoupを使います。
BeautifulSoupは外部モジュールなので、pipであらかじめインストールが必要です。

```
pip install beautifulsoup4
```

Webスクレイピングのライブラリでは、他にもSelenium等があります。
使ったことないですが。。


#Webスクレイピングは何に使う？
Webスクレイピングは勉強すればするほど使い道がたくさんあることが分かると思いますが、
僕が最初にWebスクレイピングを使った作業は**「とあるサイトから特定のドメインを含むURLを抽出する」**というものでした。

自治体向けにWebシステムを構築・導入をしていたのですが、
Webシステムをリプレースするにあたり、
旧システムのURLがHPのあらゆるところに埋め込まれていて、
新システムのURLに置き換えるにあたり、そもそもどこにURLが埋め込まれているか分からないから調べる方法はないか、
とクライアントから要望があったのが始まりでした。

この対応としてWebスクレイピング技術を用いて、
旧システムのドメインを抽出条件として、
「このページには旧システムのURL埋め込みが何件あって、どんなURLで、だいたいこの場所にあるよ～」っていうのを資料として提示しました。

懐かしいです。2年前ぐらいの話です。

この対応をきっかけに少しずつWebスクレイピングを勉強するようになりましたね。

#BeautifulSoupの基本的な使い方
さてさて、では実際にWebスクレイピングをやってみましょう！

手始めに試しに私のQiitaのマイページ[（https://qiita.com/chanmaru）](https://qiita.com/chanmaru)からサイトタイトルを取得してみましょう！

以下のコードを試してみて下さい。

```Python:scraping_test1.py
#モジュールのインポート
import urllib.request
from bs4 import BeautifulSoup

#対象のサイトURL
url = "https://qiita.com/chanmaru"

#URLリソースを開く
res = urllib.request.urlopen(url)

#インスタンスの作成
soup = BeautifulSoup(res, 'html.parser')

#head内のタイトルタグを取得
site_title = soup.html.head.title

#取得したタイトル情報を出力
print(site_title.string)
```

処理結果は以下のとおりになるはずです。

```result
chanmaru - Qiita
```

上に記述したコードがBeautifulSoupの基本的な使い方になります。

順に解説していきます。

##モジュールのインストール
```Python
import urllib.request
from bs4 import BeautifulSoup
```
必要なモジュールをインストールしています。
注意して欲しい点は、BeatifulSoupはHTMLやXMLを解析するライブラリに過ぎないため、
URLを開いたり、ダウンロードする機能はありません。

そのため、URLを開くライブラリとして```urllib.request```を用いています。
こちらは標準モジュールなので、pipであらかじめインストールする必要はありません。

##URLの指定
```python
#対象のサイトURL
url = "https://qiita.com/chanmaru"
```
単なるURLの指定です。

私のアカウントは一回削除したので、投稿が全然ないですが、ちょくちょく投稿していきたいと思っています。（宣伝）
ちなみに以下の投稿が人気らしい。（宣伝）
[Python：処理ファイルをGUIから選択する方法](https://qiita.com/chanmaru/items/1b64aa91dcd45ad91540)

##URLを開く
```Python
#URLリソースを開く
res = urllib.request.urlopen(url)
```
URLを開くには```urllib.request.urlopen()```を使います。
引数にはURLを入れてください。

##BeautifulSoupのインスタンス作成
```Python
#インスタンスの作成
soup = BeautifulSoup(res, 'html.parser')
```
「インスタンス」というワードが難しいですが、[こちら](https://wa3.i-3-i.info/word1118.html)を参照して頂ければと思います。
インスタンスについて説明すると長くなるので割愛しますが、
すぐに分からなくても大丈夫です。
解析する前のおまじないと思って頂くだけで今はOKです。

第2引数は、「HTMLを解析するよ～」という値をしています。
XMLを解析したい場合は違う値になりますので注意。

##タイトルタグを取得
```Python
#head内のタイトルタグを取得
site_title = soup.html.head.title
```
HTMLの構造と同じく、htmlタグから任意の値にアクセスしています。
今回の例だとhtml→head→titleにある要素にアクセスしています。

これが基本的な要素へのアクセス方法になります。

##タイトルの出力
```Python
#取得したタイトル情報を出力
print(site_title.string)
```
これで、アクセスした要素のテキストを出力しています。
上記コードで```string```がないとタグまで含んだ結果を出力するため、
処理結果は以下になります。

```
<title>chanmaru - Qiita</title>
```

#任意の要素の抽出
先のコードで任意の要素にアクセスすることができますが、
ルート（html）から1つずつ要素をたどるかたちになるので、
HTMLが複雑になるとアクセスするのが非常に大変になります。

なので、よく使われるのが```find()```メソッドです。
これは検索のような感じで指定の要素にアクセスします。
引数として検索したいタグやid属性の値を設定します。

例えば、```find()```を使ってサイトタイトルを取得するコードは以下のとおりになります。

```Python:scraping_test2.py
import urllib.request
from bs4 import BeautifulSoup

url = "https://qiita.com/chanmaru"
res = urllib.request.urlopen(url)
soup = soup = BeautifulSoup(res, 'html.parser')

site_title = soup.find("title")
print(site_title.string)
```

結果は同様です。

```
chanmaru - Qiita
```

上記を例にして、```find()```メソッドを使えば、a要素もHTMLの構造を把握しなくとも簡単にアクセス・出力できます。

```Python:scraping_test3.py
import urllib.request
from bs4 import BeautifulSoup


url = "https://qiita.com/chanmaru"
res = urllib.request.urlopen(url)
soup = soup = BeautifulSoup(res, 'html.parser')

site_title = soup.find("a")
print(site_title)
```

結果は・・・

```
<a href="/chanmaru/following_tags">3</a>
```

でましたね！
要素内テキストが「3」だけだったので、今回は要素全体を出力しました。

問題点は最初のヒットした要素しか表示されない点ですが、```find_all()```メソッドを使えば複数の要素を取得することができます。

それは次回の記事にてまとめます。


#おわりに
Webスクレイピングのはじめの一歩、という内容になりました。
少し雑？だったかもしれませんが、少しでもWebスクレイピングについて興味を持ってもらえたら幸いです。
冒頭にも記載したとおり「PythonでLet's Webスクレイピング」はどこまでいけるか不明ですが、シリーズ化する予定です。

今後の記事も続けて読んで頂けたら嬉しいです。

【次の記事】
[PythonでLet's Webスクレイピング！　②任意の属性値の抽出](https://qiita.com/chanmaru/items/8aac4ed25372d89ce985)