【初心者向け】Pythonでスクレイピングする環境を作る⑨ テストしてみる
Naruhiko です。
ここまで Python を理解してきましたか?
どんどん楽しくなって来たのではないでしょうか。
あとは、自分のやりたいことを考えてそれをコードに起こせるようになれば
もう次の次元へ進むことができますね。
この連載では基礎的な事はほとんど説明していません。
こうやって実際に作ってみて興味が出てきてからでも遅くはありません。
そうじゃないと覚えられないですしね。
さて、Class を作って、オブジェクト指向でのコードの書き方を少しだけ説明しました。
今回は、テストについてです。
テストについて
今回は、少しずつ機能を追加しながら、大きくしていきました。
修正するたびにコード内にテスト的にデータを入れて確かめていましたね。
こうやっていろいろなところを修正しながら作っていきましたが、
それで本当にどんなデータでも正常に行くことができるのでしょうか。
いろいろな条件をもって本当にうまく行くのかわかりませんよね。
バグをなくすためにはできるだけテストケースを多く上げて行かなければなりません。事前に全パターンがわかれば、リリース前にバグを潰すことが可能だからです。
といってもなかなか難しいものです。
本当はコード内にテスト的にデータを入れて確かめることはあまり良いことではありません。
そのテストデータをコードから取り除く時にもしかしたら大事なところも取り除いてしまうかもしれなからです。
そういう危険を侵さないように、外部からテストをすることができるツールも存在します。
今回は、unittest という、python 標準ライブラリを使って、テストをしてみたいと思います。
テスト用のファイル作成
外部からテストするとは、外部ファイルからテストを実行するということです。
crawler.py と同じところに、test_crawler.py を作ってみましょう。
unittest を書き込むファイル名はもう決まっています。
テストしたいファイル名に「test_」を付け加えることが決まりとなっています。
ですので、別のファイルがある場合は、そのファイルごとにテスト用のファイルを作っていくことになります。
VSCode で新しくファイルを作るには、左のエクスプローラーの
ファイルの作りたいフォルダを右クリックして「New File」を選びます。
入力できるようになりますので、そこに test_crawler.py を作りましょう。
unittest を使う前に
今まで作った crawler.py を外部ファイルからインポートした場合
困ったことが起きてしまいます。
それは、実行されてしまうことです。
try:
# インスタンス化
crawler = Crawler()
urls = crawler.get_search_url("python")
if urls != None:
for url in urls:
if crawler.get_robots_txt(url):
soup = crawler.get_html(url)
print(soup.title.get_text())
else:
print("クロールが拒否されました [{}]".format(url))
else:
print("取得できませんでした")
except Exception as e:
print("エラーになりました")
ここですね。
ここは今度どうしていくか考えるとして、まずは外部から実行されないようにします。
もし、直接このファイルを実行したのなら、このコードを実行するようにしましょう。
最初にこれを入れてしまいます。
if __name__ == '__main__':
こうすることで、自分だったら実行するようになります。
if __name__ == '__main__':
try:
# インスタンス化
crawler = Crawler()
urls = crawler.get_search_url("python")
if urls != None:
for url in urls:
if crawler.get_robots_txt(url):
soup = crawler.get_html(url)
print(soup.title.get_text())
else:
print("クロールが拒否されました [{}]".format(url))
else:
print("取得できませんでした")
except Exception as e:
print("エラーになりました")
unittest を使ってみる
では、test_crawler.py を開きます。
最初に unittest をインポートしましょう。
import unittest
次に、テスト対象の crawler.py ファイルの Crawler クラスをインポートします。
from crawler import crawler
これで準備完了です。
まずは、unittest.TestCase クラスを継承するクラスを作ります。
クラス名は Test + テストしたクラスです。
class TestCrawler(unittest.TestCase):
次にテストしたいメソッドを指定します。
メソッド名は、test_ + テストしたいメソッド名です。
def test_get_robots_txt(self):
各メソッドはこの中に書いていきます。
例えば、成功するメソッドは以下のようになります。
crawler = Crawler()
self.assertEqual(crawler.get_robots_txt("https://note.com/"), True)
1行目はクラスを作った時にやりましたね。
crawler 変数に Crawler() クラスのインスタンスを作成します。
self.assertEqual が成功確認をするためのメソッドです。
第1引数が実行するコード、第2引数が返ってくるであろう結果です。
実行結果と、第2引数の値が同じであればテストが成功です。
そして、このメソッドを実行するコードを最後に追加します。
if __name__ == '__main__':
unittest.main()
まとめるとこうなります。
import unittest
from crawler import Crawler
class TestCrawler(unittest.TestCase):
def test_get_robots_txt(self):
crawler = Crawler()
self.assertEqual(crawler.get_robots_txt("https://note.com/"), True)
if __name__ == '__main__':
unittest.main()
では、これを実行してみましょう。
コマンドラインで以下のコマンドを実行します。
python -m unittest test_crawler.py
root@e973f742a9b6:/workspaces/Workspaces/crawler# python -m unittest test_crawler.py
.
----------------------------------------------------------------------
Ran 1 test in 1.095s
OK
OKが表示されれば全て成功です。
詳細が知りたいときには、-v オプションを追加します。
python -m unittest -v test_crawler.py
root@e973f742a9b6:/workspaces/Workspaces/crawler# python -m unittest -v test_crawler.py
test_get_robots_txt (test_crawler.TestCrawler) ... ok
----------------------------------------------------------------------
Ran 1 test in 0.447s
OK
基本的な unittest の使い方でした。
テスト観点を洗い出そう
テストが必要な条件がどれくらいあるのでしょうか。
テストをする前に、必ず確認をする必要があります。
コードを書きながら書いたところをテストに書いていくのが理想です。
しかし、今回はここまで出来上がったものにテストをしていくことになります。
ですので、コードを見てどのようなテストをする必要があるのか考えてまとめないといけません。
ということで、一つずつ見ていきましょう。
get_robots_txt()
このメソッドの目的は、スクレイピングしたいアドレスに対してロボットがデータをスクレイピングしていいかどうかの判断をするものでした。
返す値は、True か False です。
True だとスクレイピングしていいよ。
False だとスクレイピングしないでね。
になります。
処理の流れは以下になります。
①渡された url を使ってそのサイトの robots.txt のアドレスを作成する。
②RobotFileParser() クラスの set_url() メソッドを使って robots.txt の情報を取得する。
③RobotFileParser() クラスの can_fetch() メソッドを使って 渡された url のデータのスクレイピングが可能かどうかを返す。
④エラーが起こった場合は、スクレイピングをしない。
このような流れですね。
企業などがよく採用するウォーターフォールモデルという開発手法ではこのような処理の流れを最初の基本設計で決めてから開発していきます。
最初に仕組みを明確化しておくことで複数人での開発の認識の差異を埋めることもできますし、改修が入ったときの確認用として使われます。
では、ここからわかるテストの観点はなんでしょうか。
・渡す url によって True か False を求める。
・True の条件
1. 渡した url の robots.txt でスクレイピングが許可されている。… ③
2. 渡した url の robots.txt が存在しない。… ②
・False の条件
3. 渡した url の robots.txt でスクレイピングが許可されていない。… ③
4. 渡した url が存在しない。… ④
5. サイト自体のアクセス不可。… ② or ④
6. そもそもネット自体に接続できない。… ④
今回はここを考えていくことにしましょう。
もしかしたら他にも観点があるかもしれません。
できるだけいろいろな角度で見つける必要があります。
人によって角度が違うので複数人で考えるのもありだと思います。
このテストではいろいろな url を渡していくことになります。
このようなテストケースはデータバリエーションと呼ばれます。
いろいろなバリエーションのデータを渡すことで条件通りの結果が得られるかをテストしていくものです。
エラーを確認するテストもありますが、このメソッドではエラーになった場合は False を返しログにエラー内容を渡す仕組みなのでエラー発生のテストはしないこととします。
それぞれの条件に合う url は以下の通りとします。
僕がよく使っているサイトを使いました。
1) https://note.com/
1) https://www.notion.so/
1) https://github.com/humans.txt
2) https://mikutter.hachune.net/
2) https://app.simplenote.com/
3) https://github.com/
3) https://www.google.com/
4) https://www.aaabbbccc.com/
4) https://nooooooooote.com/
5) こんなサイトはそもそも記事に載せれないので除外しました。
6) これは環境なので除外しました。
これをコードに入れるとこうなりました。
def test_get_robots_txt(self):
crawler = Crawler()
# 1. 渡した url の robots.txt でスクレイピングが許可されている
self.assertEqual(crawler.get_robots_txt("https://note.com/"), True)
self.assertEqual(crawler.get_robots_txt("https://www.notion.so/"), True)
self.assertEqual(crawler.get_robots_txt("https://github.com/humans.txt"), True)
# 2. 渡した url の robots.txt が存在しない
self.assertEqual(crawler.get_robots_txt("https://mikutter.hachune.net/"), True)
self.assertEqual(crawler.get_robots_txt("https://app.simplenote.com/"), True)
# 3. 渡した url の robots.txt でスクレイピングが許可されていない
self.assertEqual(crawler.get_robots_txt("https://github.com/"), False)
self.assertEqual(crawler.get_robots_txt("https://www.google.com/"), False)
# 4. 渡した url が存在しない
self.assertEqual(crawler.get_robots_txt("https://www.aaabbbccc.com/"), False)
self.assertEqual(crawler.get_robots_txt("https://nooooooooote.com/"), False)
実行結果
root@e973f742a9b6:/workspaces/Workspaces/crawler# python -m unittest -v test_crawler.py
test_get_robots_txt (test_crawler.TestCrawler) ...
[2020-02-22 19:07:38,922][get_robots_txt()][WARNING]<urlopen error [Errno 110] Connection timed out>
[2020-02-22 19:07:38,968][get_robots_txt()][WARNING]<urlopen error [Errno -2] Name or service not known>
ok
----------------------------------------------------------------------
Ran 1 test in 133.693s
OK
2つほどエラーログが出ているのは④の存在しない url を指定したものです。
全てのテストが通りました。
get_html()
続いて、get_html() も同じ様に観点を見てみましょう。
このメソッドの目的は、渡されたアドレスをスクレイピングするものでした。
返す値は、Beautefil Soup で整形されたデータです。
エラーになった場合は、None を返します。
処理の流れは以下になります。
①5秒待つ。
②渡された url と params と headers を使ってそのサイトのデータ。を requests.get を使って取得する。
③取得したデータをエンコードする。
④Beautefil Soup を使って html 要素を取得し、返す。
⑤エラーが起こった場合は、None を返す。
このような流れですね。
では、ここからわかるテストの観点はなんでしょうか。
・requests.get パラメータの条件を洗い出す。 … ②⑤
・引数 url params headers の組み合わせと取得有無の組み合わせ。
・html 要素を取り出す条件を洗い出す。 … ④⑤
・取得したデータの変換の有無の組み合わせ。
⇒ ただし、ただ要素を取得するだけでのエラーに対しては難しい。
・上記を考えると、④でのエラー条件を出すのが難しい。
ココらへんがテストの項目を作成するうえでの大事な観点になります。
今回はとりあえずここまでの観点を使って洗い出してみます。
キーになるのは②⑤になります。
1) 引数は url のみ
・url ○ 、 が存在しデータも取得できる。
・url ○ 、 が存在するがデータが取得できない。
・url ☓ 、 が存在しない。
2) 引数は url params のみ(○は正常、☓は異常)
・url ○ 、params ○ ⇒ データを取得出来る。
・url ○ 、params ○ ⇒ データを取得出来ない。
・url ○ 、params ☓ ⇒ データを取得出来る。
・url ○ 、params ☓ ⇒ データを取得出来ない。
・url ☓ 、params ○ ⇒ データを取得出来ない。
・url ☓ 、params ☓ ⇒ データを取得出来ない。
3) 引数は url headers のみ
・url ○ 、headers ○ ⇒ データを取得出来る。
・url ○ 、headers ○ ⇒ データを取得出来ない。
・url ○ 、headers ☓ ⇒ データを取得出来る。
・url ○ 、headers ☓ ⇒ データを取得出来ない。
・url ☓ 、headers ○ ⇒ データを取得出来ない。
・url ☓ 、headers ☓ ⇒ データを取得出来ない。
4) 引数は url params headers
・url ○ 、params ○ 、headers ○ ⇒ データを取得出来る。
・url ○ 、params ○ 、headers ○ ⇒ データを取得出来ない。
・url ○ 、params ○ 、headers ☓ ⇒ データを取得出来る。
・url ○ 、params ○ 、headers ☓ ⇒ データを取得出来ない。
・url ○ 、params ☓ 、headers ○ ⇒ データを取得出来る。
・url ○ 、params ☓ 、headers ○ ⇒ データを取得出来ない。
・url ○ 、params ☓ 、headers ☓ ⇒ データを取得出来る。
・url ○ 、params ☓ 、headers ☓ ⇒ データを取得出来ない。
・url ☓ 、params ○ 、headers ○ ⇒ データを取得出来ない。
・url ☓ 、params ○ 、headers ☓ ⇒ データを取得出来ない。
・url ☓ 、params ☓ 、headers ○ ⇒ データを取得出来ない。
・url ☓ 、params ☓ 、headers ☓ ⇒ データを取得出来ない。
条件を総当りで表示しましたが、これを全てやるのかは考えものです。
もちろん全ての条件でやるのがいいのですが、それはテスト期間に余裕があるなどの工数的に大丈夫であればの話です。
実際は時間の余裕はないものです。
ですので、似たようなものに関しては条件をつけてまとめてしまいます。
・url は "https://www.google.com/" または "https://gooooole.com/" とする。
正しい値と、間違った値の2パターンのみに絞りました。
・params パラメーターは、{"q": "python"} または{"aaa"} とする。
こちらも正しい値と、間違った値の2パターンのみに絞りました。
"q" の値のみのパターンにします。
値の複数パターンはなしとします。
・headers パラメーターは、{"user_agent": "〜"} または{"aaa"} とする。
こちらも正しい値と、間違った値の2パターンのみに絞りました。
user_agent の値のみのパターンにします。
値の複数パターンはなしとします。
・条件がOKでデータが取得できない場合は除外する
例えばサーバ側のレスポンスに時間がかかっている、
basic認証などで拒否されている、権限がないなど、
いろいろな原因が考えれます。
実際はできるだけ拾い上げるべきですが、今回は除外します。
1) 引数は url のみ
・url ○ 、 が存在しデータも取得できる。
・url ☓ 、 が存在しない。
2) 引数は url params のみ(○は正常、☓は異常)
・url ○ 、params ○ ⇒ データを取得出来る。
・url ○ 、params ☓ ⇒ データを取得出来ない。
・url ☓ 、params ○ ⇒ データを取得出来ない。
・url ☓ 、params ☓ ⇒ データを取得出来ない。
3) 引数は url headers のみ
・url ○ 、headers ○ ⇒ データを取得出来る。
・url ○ 、headers ☓ ⇒ データを取得出来ない。
・url ☓ 、headers ○ ⇒ データを取得出来ない。
・url ☓ 、headers ☓ ⇒ データを取得出来ない。
4) 引数は url params headers
・url ○ 、params ○ 、headers ○ ⇒ データを取得出来る。
・url ○ 、params ○ 、headers ☓ ⇒ データを取得出来ない。
・url ○ 、params ☓ 、headers ○ ⇒ データを取得出来ない。
・url ○ 、params ☓ 、headers ☓ ⇒ データを取得出来ない。
・url ☓ 、params ○ 、headers ○ ⇒ データを取得出来ない。
・url ☓ 、params ○ 、headers ☓ ⇒ データを取得出来ない。
・url ☓ 、params ☓ 、headers ○ ⇒ データを取得出来ない。
・url ☓ 、params ☓ 、headers ☓ ⇒ データを取得出来ない。
これをコードにするとこうなります。
def test_get_html(self):
ok_url = "https://www.google.com"
ng_url = "https://gooooole.com/"
ok_params = {"q": "python"}
ng_params = {"aaa"}
user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) \
AppleWebKit/537.36 (KHTML, like Gecko) \
Chrome/69.0.3497.100"
ok_headers = {"User-Agent": user_agent}
ng_headers = {"aaa"}
title = "Google"
crawler = Crawler()
# 1) 引数は url のみ
self.assertEqual(crawler.get_html(ok_url).title.get_text(), title)
self.assertEqual(crawler.get_html(ng_url), None)
# 2) 引数は url params のみ
self.assertEqual(crawler.get_html(
ok_url, params=ok_params).title.get_text(), title)
self.assertEqual(crawler.get_html(ok_url, params=ng_params), None)
self.assertEqual(crawler.get_html(ng_url, params=ok_params), None)
self.assertEqual(crawler.get_html(ng_url, params=ng_params), None)
# 3) 引数は url headers のみ
self.assertEqual(crawler.get_html(
ok_url, headers=ok_headers).title.get_text(), title)
self.assertEqual(crawler.get_html(ok_url, headers=ng_headers), None)
self.assertEqual(crawler.get_html(ng_url, headers=ok_headers), None)
self.assertEqual(crawler.get_html(ng_url, headers=ng_headers), None)
# 4) 引数は url params headers
self.assertEqual(crawler.get_html(
ok_url, params=ok_params, headers=ok_headers).title.get_text()
, title)
self.assertEqual(crawler.get_html(
ok_url, params=ok_params, headers=ng_headers), None)
self.assertEqual(crawler.get_html(
ok_url, params=ng_params, headers=ok_headers), None)
self.assertEqual(crawler.get_html(
ok_url, params=ng_params, headers=ng_headers), None)
self.assertEqual(crawler.get_html(
ng_url, params=ok_params, headers=ok_headers), None)
self.assertEqual(crawler.get_html(
ng_url, params=ok_params, headers=ng_headers), None)
self.assertEqual(crawler.get_html(
ng_url, params=ng_params, headers=ok_headers), None)
self.assertEqual(crawler.get_html(
ng_url, params=ng_params, headers=ng_headers), None)
実行結果
ok
test_get_robots_txt (test_crawler.TestCrawler) ... ok
----------------------------------------------------------------------
Ran 1 tests in 96.423s
OK
OKがでれば、全てのテストが成功です。
get_search_url()
最後に get_search_url() を見てみましょう。
これに関しては、今後改善が必要ですが、とりあえず今の状態でのテスト観点を見てみましょう。
このメソッドを動かすためのパラメーターは2つです。
・検索エンジン(デフォルトは Google)
・検索ワード
指定した検索エンジンに検索ワードを元に検索した結果のURLの一覧を取得するものです。
処理の流れは以下になります。
①インスタンスを生成する際に、検索エンジンを指定する(デフォルトは Google)
②検索エンジンが Google だったら検索URLとパラメーターとヘッダーを作成する
③検索エンジンが Google 以外だったらエラーを出して終了
④ get_html メソッドを使って、検索結果のページを取得する
⑤要素を抽出する
⑥要素が存在してれば、検索結果先のURLの一覧を作成する
⑦要素が存在していなければ、エラーを出して終了
これを元にテスト観点を洗い出してみます。
・検索エンジンは Google かそれ以外 … ①③
・今のコードでは Google のみ検索開始 … ①
・パラメーターは "q" 固定で検索ワードはどんなものでも行ける(はず)… ②④
・Google検索でURLが取得できない検索ワードがわからない … ⑥
こんなところでしょうか。
どうしても No Data エラーの検索ワードが思いつきませんでした。
いつか思いついたら追加したいと思います。
これを元にテスト項目を作ってみましょう。
1) Google で検索ワード「Python」⇒ 10件データ取得できる
2) Google 以外で検索ワード「Python」⇒ None
3) Google で検索ワード "" ⇒ 0件データ取得できる
少なかったので、とりあえず 3) を無理やり付け加えました。
検索ワードがないので、結果は返しますが検索画面に戻っているはずです。
ということでURLを取得できずに0件で受け取るはずです。
これをコードにするとこうなります。
def test_get_search_url(self):
# 1) Google で検索ワード「Python」
crawler1 = Crawler()
self.assertEqual(len(crawler1.get_search_url("Python")), 10)
# 2) Google 以外で検索ワード「Python」
crawler2 = Crawler("yahoo")
self.assertEqual(crawler2.get_search_url("Python"), None)
# 3) Google で検索ワード ""
crawler3 = Crawler("Google")
self.assertEqual(len(crawler1.get_search_url("")), 0)
実行結果
ok
----------------------------------------------------------------------
Ran 1 test in 14.572s
OK
OKが出ると全てのテストが完了です。
最後に
テストの考え方、やり方を説明しました。
もっと複雑なテストもできますので、徐々に慣れてみてください。
最初は、どのような観点からテスト項目を作っていいか悩むと思います。
やりやすいのは、コードの流れを全て抜き出すのがおすすめです。
分岐があれば、全ての分岐を通したりします。
今回はちょっと甘かったかもしれませんが、こうしてやっていくことでテストの大事さを理解できると思います。
最後に今回作った test_crawler.py を載せておきます。
import unittest
from crawler import Crawler
class TestCrawler(unittest.TestCase):
def test_get_robots_txt(self):
crawler = Crawler()
# 1. 渡した url の robots.txt でスクレイピングが許可されている
self.assertEqual(crawler.get_robots_txt("https://note.com/"), True)
self.assertEqual(crawler.get_robots_txt("https://www.notion.so/"), True)
self.assertEqual(crawler.get_robots_txt("https://github.com/humans.txt"), True)
# 2. 渡した url の robots.txt が存在しない
self.assertEqual(crawler.get_robots_txt("https://mikutter.hachune.net/"), True)
self.assertEqual(crawler.get_robots_txt("https://app.simplenote.com/"), True)
# 3. 渡した url の robots.txt でスクレイピングが許可されていない
self.assertEqual(crawler.get_robots_txt("https://github.com/"), False)
self.assertEqual(crawler.get_robots_txt("https://www.google.com/"), False)
# 4. 渡した url が存在しない
self.assertEqual(crawler.get_robots_txt("https://www.aaabbbccc.com/"), False)
self.assertEqual(crawler.get_robots_txt("https://nooooooooote.com/"), False)
def test_get_html(self):
ok_url = "https://www.google.com"
ng_url = "https://gooooole.com/"
ok_params = {"q": "python"}
ng_params = {"aaa"}
user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) \
AppleWebKit/537.36 (KHTML, like Gecko) \
Chrome/69.0.3497.100"
ok_headers = {"User-Agent": user_agent}
ng_headers = {"aaa"}
title = "Google"
crawler = Crawler()
# 1) 引数は url のみ
self.assertEqual(crawler.get_html(ok_url).title.get_text(), title)
self.assertEqual(crawler.get_html(ng_url), None)
# 2) 引数は url params のみ
self.assertEqual(crawler.get_html(
ok_url, params=ok_params).title.get_text(), title)
self.assertEqual(crawler.get_html(ok_url, params=ng_params), None)
self.assertEqual(crawler.get_html(ng_url, params=ok_params), None)
self.assertEqual(crawler.get_html(ng_url, params=ng_params), None)
# 3) 引数は url headers のみ
self.assertEqual(crawler.get_html(
ok_url, headers=ok_headers).title.get_text(), title)
self.assertEqual(crawler.get_html(ok_url, headers=ng_headers), None)
self.assertEqual(crawler.get_html(ng_url, headers=ok_headers), None)
self.assertEqual(crawler.get_html(ng_url, headers=ng_headers), None)
# 4) 引数は url params headers
self.assertEqual(crawler.get_html(
ok_url, params=ok_params, headers=ok_headers).title.get_text()
, title)
self.assertEqual(crawler.get_html(
ok_url, params=ok_params, headers=ng_headers), None)
self.assertEqual(crawler.get_html(
ok_url, params=ng_params, headers=ok_headers), None)
self.assertEqual(crawler.get_html(
ok_url, params=ng_params, headers=ng_headers), None)
self.assertEqual(crawler.get_html(
ng_url, params=ok_params, headers=ok_headers), None)
self.assertEqual(crawler.get_html(
ng_url, params=ok_params, headers=ng_headers), None)
self.assertEqual(crawler.get_html(
ng_url, params=ng_params, headers=ok_headers), None)
self.assertEqual(crawler.get_html(
ng_url, params=ng_params, headers=ng_headers), None)
def test_get_search_url(self):
# 1) Google で検索ワード「Python」
crawler1 = Crawler()
self.assertEqual(len(crawler1.get_search_url("Python")), 10)
# 2) Google 以外で検索ワード「Python」
crawler2 = Crawler("yahoo")
self.assertEqual(crawler2.get_search_url("Python"), None)
# 3) Google で検索ワード ""
crawler3 = Crawler("Google")
self.assertEqual(len(crawler1.get_search_url("")), 0)
if __name__ == '__main__':
unittest.main()
---
気に入っていただけたら、フォローや好きをお願いします!
note 連載目次
【初心者向け】Pythonでスクレイピングする環境を作る① はじめに
【初心者向け】Pythonでスクレイピングする環境を作る② Dockerの使い方
【初心者向け】Pythonでスクレイピングする環境を作る③ VSCodeでDocker環境を構築する
【初心者向け】Pythonでスクレイピングする環境を作る④ requestsでデータを取得してみる
【初心者向け】Pythonでスクレイピングする環境を作る⑤ Google検索をしてみる
【初心者向け】Pythonでスクレイピングする環境を作る⑥ スクレイピングでの注意事項
【初心者向け】Pythonでスクレイピングする環境を作る⑦ 検索結果のページのタイトルを取得する
【初心者向け】Pythonでスクレイピングする環境を作る⑧ クラスにまとめてみる
【初心者向け】Pythonでスクレイピングする環境を作る⑨ テストしてみる
【初心者向け】Pythonでスクレイピングする環境を作る⑩ crawler と scraper を分ける
ここから先は
¥ 100
この記事が気に入ったらサポートをしてみませんか?