【失敗談】スクレイピングを約１時間学んだだけで作業時間が激減した件。

# 失敗談
過去記事にて、競艇の順位予想をするプログラムを作成し、紹介しました。

↓過去記事については、下記リンクを参照してください。↓
[【ディープラーニング】機械学習初心者が競艇１位予想を作れるのか試してみた。](https://qiita.com/gorilland/items/c203fee4362e8dea0037)

プログラムに関してはある程度の評価をいただきましたが、ひとつ気になることが私にはありました。

それは、**データ収集の大変さ**でした。

Webページからデータを収集していたので、この作業を楽にするのはスクレイピングをすることだとはわかっていました。

しかし私は、食わず嫌いというのとディープラーニングで手一杯だった為、難しそうなスクレイピングの中身さえ確認せずにコピーアンドペーストをしてデータを集めていました。

実際にスクレイピングの基礎を学習してみて、まず**取り掛かりやすさに驚き**、私が必死にコピーアンドペーストして収集していたテキストが

```html
<pre>テキスト</pre>
```

のみで囲われていたことに絶望しました。

つまり、基礎でも取得できる単純なソースコードで構成されていたという訳です。

これで私は、開発に取り掛かる前にきちんと設計することの大切さを学びました。

設計さえしていれば、より短い時間で、効率よく円滑に作業が進んでいたはずです。

設計することは基本だと思いますが、きちんとしないと私のようになってしまうので気をつけてください。

# モジュール
```py
import requests
from bs4 import BeautifulSoup
import time
```
* Requests
* BeautifulSoup4

これらは追加モジュールなのでターミナル(Mac)でインストールする必要があります。

```terminal
$ pip install requests
$ pip install BeautifulSoup4
```
# ソースコード

```py
import requests
from bs4 import BeautifulSoup
import time

date = ["202004", "202003", "202002", "202001",
        "201912", "201911", "201910", "201909",
        "201908", "201907", "201906", "201905",
        "201904", "201903", "201902", "201901"]

with open("scraping_data.txt", "a", encoding='utf-8') as f:
    for month in date:
        for day in range(1, 32):
            try:
                if num < 10:
                    url = "URL/{}/12/0{}.html".format(month, day)
                else:
                    url = "URL/{}/12/{}.html".format(month, day)
            except ValueError:
                pass

            response = requests.get(url)
            response.encoding = response.apparent_encoding

            bs = BeautifulSoup(response.text, "html.parser")


            for pre in bs.find_all("pre"):
                f.write(pre.text)
            time.sleep(1)
        print("{}: 書き込み完了".format(month))
```
Pythonの基礎は特に説明を付け加える必要がない場合の説明は省かせていただきます。

## url
URLを見てみると、日付を変えるごとに

```
URL/202004/12/04.html
```
のようにURLの一部が変更されるだけなのでこれを利用して取得しました。
### if-else
```py
if num < 10:
    url = "URL/{}/12/0{}.html".format(month, day)
else:
    url = "URL/{}/12/{}.html".format(month, day)
```
1~9日では、URL内で「01」のように表現されているので分岐させています。

### try-except

```py
try:
    if num < 10:
        url = "URL/{}/12/0{}.html".format(month, day)
    else:
        url = "URL/{}/12/{}.html".format(month, day)
except ValueError:
    pass
```
URL内に任意の日付が存在しない場合があったので、指定のURLがなかったときに発生する```ValueError```を```except```文で無視しています。

## requests

### requests.get(url)
```py
response = requests.get(url)
```
HTTPリクエストを送り、HTTPレスポンスを取得することができます。
これによりHTMLを取得することができます。

### レスポンスのエンコーディング

```py
response.encoding = response.apparent_encoding
```
日本語などでは、エンコーディングを適切に判断できずに、文字化けしてしまう可能性があります。
#### response.encoding
encodingプロパティは、サーバーから返されるレスポンスの文字エンコーディングで、これに従い、コンテンツを変換することができます。

#### response.apparent_encoding
サーバーから返された文字エンコーディングが不明な時にコンテンツの中身をチェックした上で、適切な文字エンコーディングを返してくれます。

#### response.text
取得したHTMLを表示します。

## BeautifulSoup

```python
bs = BeautifulSoup(response.text, "html.parser")
```
BeautifulSoupを使用するには

* 第一引数：HTMLを渡します。
* 第二引数：HTMLパーサーを渡します。種類は多数存在しますが、今回は最初から使える```"html.parser"```を使っています。

### HTMLパーサー
HTMLを字句解析して、タグを判断してデータ構造として取得するプログラムのことです。

### BeautifulSoup.find_all()

```py
for pre in bs.find_all("pre"):
    f.write(pre.text)
```
()内に指定されたタグをすべて取得します。
それをforループにかけることで、一つずつ指定のタグを取得することができます。

## timeメソッド

```py
import time

time.sleep(1)　# 1秒間プログラムを停止する
```
### time.sleep()
任意の時間の間プログラムを停止することができます。
<br>

スクレイピングをすることで重要なのは、相手サイトに迷惑をかけないようにすることです。

**最低でも1秒以上**は時間を開けるようにしましょう。


# リンク
[BeautifulSoup 公式ドキュメント](https://www.crummy.com/software/BeautifulSoup/bs4/doc/)