PythonでWebスクレイピング①(スクレイピング事前知識)

#1.背景
**本記事は前回のSQLiteに引き続いて、pythonを投資活用に使う目的で調べたまとめ記事の第2弾です。**
**全2回にわたってスクレイピングに関して調べた内容をシェアしていきます。
初回①としてはスクレイピングする前に知っておく内容を自分なりにまとめてみました。**


<参考>前回記事(投資活用のための記事の第1弾)：
[Pythonで簡単にデータベースを扱う(SQLite3)](https://qiita.com/ku_a_i/items/9c68e8aed3c2c066bc60)
　※本記事は前回とは全く関連はないので、読んでなくても読み進められます。

#2.Webスクレイピングを知る上での基本用語
**・スクレイピングとは？**
Webサイトから必要な情報を抽出すること。

**・クローリングとは？**
リンクを辿ってWebページを収集すること。


**・クローラーとは？**
クローラーとは、インターネット上を巡回し、Webサイト・画像・動画などのデータを収集・保存するプログラムのこと。
例えばGoogleやBingなどのWeb検索エンジンは、予めクローラーを使って世界中のWebページを収集しているから高速に検索出来ているということである。

#3.どんなWebページでもスクレイピングしてもいいのか？
**<font color="Red">Web ページは基本的に著作物</br>
・Webサイトによっては「利用規約」や「ヘルプページ」等でクローリングを明確に禁止しているケースがある
・robots.txtやrobots metaタグで拒否されているページをクロールしないこと
・万が一許可されていたとしても、Webサーバーへの負担をかけないように配慮すること
</font>**

**・robot.txtとは何か？**
robots.txtとは、クローラへアクセス制限などを伝えるために設置されるファイルのこと。
robot.txtは、rootページ(WebのTOPページ)のURLに「/robots.txt」を入れて確認できる。
　(Yahooの)rootページ：https://www.yahoo.co.jp/
　(Yahooの)robots.txt：https://www.yahoo.co.jp/robots.txt


**・(robots) metaタグとは何か？**
robots.txtと似た目的で使われ、HTMLファイルのヘッダ(head)部に書いてある「そのサイトの説明書きみたいなもの」


<参考>
[Robots.txt の仕様](https://developers.google.com/search/reference/robots_txt?hl=ja)
[robots【metaタグ】とは](https://wa3.i-3-i.info/word11810.html)

#4.robots.txtをパースする
**・パースとは？**
一定の書式や文法に従って記述されたデータを解析し、構文が文法にあっているかどうかを解析すること

**・パーサーとは？**
構造的な文字データを解析し、プログラムで扱えるようなデータ構造の集合体に変換するプログラム

pythonのライブラリに`urllib.robotparser`というものがあるが、使い勝手的には`reppy`の方がいいと感じたのでここではそれを使う。
**※ただし、Robots.txtが規則に沿って記載されていないケースはうまく読めないこともあるので、その時は直接URLに/robots.txtを付け加えて確認するか、別の手法で確認する必要がある**

**reppyのパーサーライブラリの使い方**
(・`pip install reppy` でreppyをインストールしておく)
・fetch`命令にてuser-agentを指定し、でどのクローラーに対調べるか？を指定する。
・allowed命令でクロールしようとするURLを指定し、アクセス可能か？を確認する
・Crawl-delay（サイトが指定したクロール間隔)を確認する。※これが規定されている場合はこれに従う必要がある


下記では1例として[MSN](https://www.msn.com/)のホームページを取り上げる

```python:
from reppy.robots import Robots

#fetchでmsnのrobots.txtを読み込む
robots = Robots.fetch('https://www.msn.com/robots.txt')
#確認対象をワイルドカード('*')で指定する ※つまり全クローラーが対象ということ
agent = robots.agent('*')

#それぞれ指定したURLに対してallowedを使用してrobots.txtがアクセス可能か？を確認する
print(agent.allowed('https://www.msn.com/ja-jp/news'))
print(agent.allowed('https://www.msn.com/ja-jp/health/search/filter'))
```
```:実行結果
True
False
```
1サイト目はOK、2サイト目はNGとなっていることが確認できる。

引き続き、サイトが指定したクロール間隔があるケースを紹介する。
例として[クラウドワークス](https://crowdworks.jp/)のホームページを取り上げる。

```python:
from reppy.robots import Robots

#fetchでクラウドワークスのrobots.txtを読み込む
robots = Robots.fetch('https://crowdworks.jp/robots.txt')

#確認対象をbingbot(Bing)で指定し、delayで確認する ※bingbot≒マイクロソフトの検索クローラ－
agent = robots.agent("bingbot")
print(agent.delay)

#比較対象としてワイルドカードも確認してみる
agent = robots.agent("*")
print(agent.delay)
```
```:実行結果
10.0
None
```
Bingのクローラーには10秒のクロール間隔を空けるように書いていることがわかる。

#5. robotsのmetaタグを確認する
HTMLタグやHTTPヘッダーによるアクセス制限も確認しておく。
サイトページのmetaタグやaタグにnoindex、nofollow等の記載があれば、そのサイトのインデックス化やリンクをたどることが禁止されている

<参考>
[メタタグの記述と検索エンジン](https://info-search.yahoo.co.jp/archives/002841.php)

BeautifulSoup4を使用してmetaタグを確認したいURLを指定する
※`pip install beautifulsoup4` でライブラリのインストールが必要。

```Python:
import requests 
from bs4 import BeautifulSoup

#request.get()で指定されたwebの情報を取得
url = requests.get("https://www.yahoo.co.jp/")

#BeautifulSoupオブジェクトを生成する(textで取得したHTMLを文字化し、html.parserで解析する)
soup = BeautifulSoup(url.text, "html.parser")
# soup = BeautifulSoup(url.content, "html.parser")

#findで一番最初に一致するタグ<meta>を取得し、attrsにname属性の属性値robotsを渡す
robots = soup.find("meta", attrs={'name': 'robots'})

print(robots)
```

```:実行結果
<meta content="noodp" name="robots"/>
```
どうやらyahooにはnoodp(NO Open Directory Procject)というMetaタグが設定されているようである。

#6.色々な投資サイトがどうなっているか？を見てみた。
参考までに投資のスクレイピングでよく話題に上がっているサイトを紹介した手法で調べてみた。
**<font color="Red">各HPに対するスクレイピングのOK/NGに関する結論は本記事で言及/記載しない。
調べていて感じたのは、基本的にファイナンス系はNGが多そうということ。</font>**
別途APIがあったりするケースもあるのでそれを使うのも手かも。。。
***
**例①：株式投資メモ**
https://kabuoji3.com/
・robots.txt： Allow:/ ※ルートディレクトリ以下すべて許可する
・metaタグ：記載なし
・ホームページ規約 : 記載なし

※このサイトのrobots.txtはreppyではうまく取得できなかった。おそらく`Allow:/` の`:と/の間にスペースがない`ためだと考えている。別の手段でも取得できるが、今回は割愛する。 

***
**例②：株探**
https://kabutan.jp/
・robots.txt： Disallow: /94446337/※94449667ディレクトリ以下は許可しない
・metaタグ：記載なし
・ホームページ規約 : 不当な負荷をかけるのは禁止(下記参照)
 
第４条（**禁止事項**）
１．運営者は、利用者が以下に該当する、あるいはその恐れのある行為を行うことを禁止します。
:
**(7)本サイトのサーバーに不当な負担をかける行為や本サービスの運営を妨げる行為。**

[株探利用規約](https://info.kabutan.jp/terms-site/)
***
**例③：四季報オンライン**
https://shikiho.jp/
・robots.txt： 記載なし
・metaタグ：記載なし
・ホームページ規約 : 禁止(下記参照)

第13条（利用者のその他の**禁止行為**）
1. 利用者は、本規約の他の条項において禁止される行為の他、本サービスにおいて以下の行為をしてはならないものとします。
:
**(10) 本サービスで提供された情報を、コンピューター等を利用して自動取得する行為**

[四季報オンライン規約](https://str.toyokeizai.net/-/info/kiyaku/sol/4ol_terms_20200401.pdf)
***

**例④：Yahoo! ファイナンス**
https://finance.yahoo.co.jp/
・robots.txt： 記載なし
・metaタグ：記載なし
・ホームページ規約 : ネットワークの機能を破壊したり、妨害したりする行為は禁止（下記参照）
　※ただし**Yahoo!ファイナンスヘルプを確認すると禁止と記載**されている

●規約
7.サービス利用にあたっての順守事項
当社のサービスのご利用に際しては以下に定める行為（それらを誘発する行為や準備行為も含みます）を**禁止**いたします。
:
**4.当社のサーバーまたはネットワークの機能を破壊したり、妨害したりする行為**

●Yahoo!ファイナンスヘルプ
**Yahoo!ファイナンス掲載情報の自動取得（スクレイピング）は禁止しています。**

[Yahoo!ファイナンス規約](https://about.yahoo.co.jp/common/terms/chapter1/#cf1st)
[Yahoo!ファイナンスヘルプ](https://support.yahoo-net.jp/PccFinance/s/article/H000011276)
***


#7.負荷にならない為にどうすればいいのか？

規定は決まっていないと思われる。あくまで相手のサービスの負荷にならないように・・とのことらしいが、今はCrawl-delayで指定されていない場合は1秒に1回という目安が認知されている気がする。(岡崎市立中央図書館事件で広まった？)

<参考>
[2010年岡崎市立中央図書館事件のwiki](https://ja.wikipedia.org/wiki/%E5%B2%A1%E5%B4%8E%E5%B8%82%E7%AB%8B%E4%B8%AD%E5%A4%AE%E5%9B%B3%E6%9B%B8%E9%A4%A8%E4%BA%8B%E4%BB%B6)
[国立国会図書館法によるインターネット資料の収集について(資料)](https://warp.ndl.go.jp/bulk_info.pdf)


#8.最後に
個人的な備忘録兼ねてる為、初心者には難しめの記事になってしまったかもですが重要なのでまとめました。
まとめてみてこの問題にはグレーな部分も多く、ハッキリNGと記載していない場合の明確な規定はないと思いました。
とにかく相手のサーバー運営に迷惑がかかったらNGなので、よくわからなければ諦めるのも肝心ですね。

また、クローラで収集したデータの利用方法によって問題が発生することがあることも考慮する必要がありそうです(別問題として)

**具体的なスクレイピングの記事は次回。**

<br>

<その他参考ページ>
[robots.txt ファイルを作成する](https://developers.google.com/search/docs/advanced/robots/create-robots-txt?hl=ja&visit_id=637434421534486729-1976705014&rd=1)
[Webスクレイピングする際のルールとPythonによる規約の読み込み](https://vaaaaaanquish.hatenablog.com/entry/2017/12/01/064227)
[スクレイピング、クローリングする時の注意点](https://docs.pyq.jp/column/crawler.html)
[Webスクレイピングの注意事項一覧](https://qiita.com/nezuq/items/c5e827e1827e7cb29011)
[PythonでWebスクレイピングする時の知見](https://vaaaaaanquish.hatenablog.com/entry/2017/06/25/202924#%E6%B3%95%E5%BE%8B%E3%81%AE%E8%A9%B1)