はじめてのスクレイピング
サイト上にある、膨大なデータを自動で収集したいそこのあなた、”必見”です。
目次
はじめに
動作環境
注意点1
作った理由
サンプルコード説明
注意点2
最後に
はじめに
初めまして、クラウドソリューショングループ、新人のtakagirです。
ネット上にある大量のデータを持ってきて、ちょっとデータ分析してみたいな、と思った人がまず最初にぶつかる障壁、データをどう取ってくるかというテーマについて、共有していければいいなと思います。
知らなければいけないことは多いですが、実はやることは非常に簡単です。
動作環境
今回使用する環境は以下の通りです。
- python 3.9.4
必要になるライブラリは以下のものです。
- BeautifulSoup
コマンドプロンプトなどでpip install beautifulsoup を用いてインストールする必要があります。
サンプルコード解説にて使用方法の一例を紹介しますが、こちらのサイトを参考にするとインストールからより詳しい使い方解説まで載っています。→https://www.python.ambitious-engineer.com/archives/981
注意点1
いきなりですが先に注意点です。
スクレイピングでは、DoS攻撃になってしまわないかに注意をする必要があります。
「DoS攻撃とは――ッ、同一サイトに短期間で大量のリクエストを送ることで、サーバに負荷を与え、サービスを利用不能に陥らせる攻撃のことであるッ!!」
詳しくはDOS攻撃(Denial of Services attack)を参照ください。
ゆるーく説明をすると、某人気漫画の主人公もニッコリな“オラオララッシュ”をサーバーめがけてブチかますことであり、下手をすると逮捕されます。 → 岡崎市立中央図書館事件
またこれ以外にも忘れてはいけない点があり、それはウェブサイトも「著作物」であること、そしてそこにあるデータは場合によっては「個人情報」であること、です。またサイトによってはrobot.txtというものがあり、そこにサイトに対してやってはいけないことなどが書かれています。
この辺の話については私はこのqiitaを起点に調べましたので、こちらも参考にどうぞ。
以上、ほかにも注意すべき点はありますが、まずは先にしっかり押さえておきたい注意点となります。
作った理由
理由はサーバーにある自分のゲームのスコアデータを自分なりに収集したかったからです。
近年ずいぶん公式の開発側もその辺の要望に応えて、公式でサポートしてくれている場合も多い(有料)のですが、対応していないものも当然あります。
そこで、自分で作ってしまおう、となったわけです。
サンプルコード説明
import csv import requests from bs4 import BeautifulSoup import time
まずはimportしたものから。
一行目はcsvを扱うためのもの。せっかく情報を取ってきても、ちゃんとした形式で書き出しをしないと後から扱うのに苦労します。
二行目はサイトの情報を取得するために使います。ただ取ってくるだけになってしまうので、三行目のものと合わせて使用します。
三行目は取得した情報から特定のものを抽出するために使います。requestで情報を取得し、beautifulsoupで取得した情報からほしいものだけを抽出する、という形になります。
四行目はsleepを使うためです。サイトへのアクセス速度を落とすためにsleepを使用します。
load_url = URL html = requests.get(load_url) soup = BeautifulSoup(html.content, "html.parser")
次は早速サイト情報を取得してしまいましょう。
一行目で情報を取得したいサイトのURLを指定します。
二行目でrequestsを用いてそのサイトから情報を取得します。
三行目で取得した情報の解析をします。正確には二行目で得られるのはbyte列なので、解析をしないと後の抽出ができなくなってしまいます。また、万が一解析がうまくいかず、文字化けなどした場合は第二引数”html.parser”のところを別のものに変えてください。
text = soup.find(class_= HTMLタグ).text
さてこちらが抽出部分になります。
soup.findでそのサイトに最初に出てくる指定した「HTMLタグ」の内容を取得します。
もしすべてのタグの内容が取得したい場合はsoup.find_allですが、この時返ってくる値はsoup.findと違ってリスト型で返ってくるので、扱いが変わることに注意してください。
with open("test.csv","a", newline="") as test: writer = csv.writer(test , delimiter = ',' , quotechar = '"' , quoting = csv.QUOTE_ALL) writer.writerow([text,])
最後に抽出してきたデータをcsvに書き出してしまいましょう。
まず一行目with openでcsvファイルを開きます。引数は(ファイル名,新規か上書きか,改行指定)です。上書きしないと一回分しか残らないので上書き指定の”a”で指定します。
二行目で書き出し方を指定します。delimiterは区切り文字です。今回は「,」を区切り文字にします。ちなみに区切り文字は一文字です。「,,」などとやるとエラーします。quotecharは囲む文字の指定です。今回は「”」を指定します。またquoting = csv.QUOTE_ALLですべての要素を指定した文字で囲むするように指定します。これをしないと余計なエラーを吐くことがあります。
そして三行目で書き出す内容を指定します。今回抽出したtextを書き出しましょう。もし複数要素を書き出したい場合は([text1,text2,])などとします。
これで一回分のスクレイピングが完了です。
もし複数ページに対して行いたい場合はfor文などを用いて繰り返し行いましょう。
例えばexample_1からexample_999までの999個のサイトをスクレイピングするなら、
for i in range(1,999): load_url = "example_" + str(i)
などとすれば取ってこれるでしょう。
…さて、注意点を忘れていませんか?平気ですか?
このままでは“オラオララッシュ”が始まります。
というわけで、繰り返す場合はsleepを使いましょう。
time.sleep(1)
などと指定し、アクセス間隔をあけましょう。アクセス間隔は最低でも1秒はあけましょう。サイトによってはちゃんと指定がある場合があります。
全体としては以下のような形になります。
import csv import requests import time from bs4 import BeautifulSoup FLAG = False //繰り返す場合はここからfor文を開始 load_url = 「URL」 html = requests.get(load_url) soup = BeautifulSoup(html.content, "html.parser") try: FLAG = True text = soup.find(class_= 「HTMLタグ」).text except: //データが取れなかった場合、csvに書き出さないようにする。 FLAG = False if FLAG: with open("test.csv","a", newline="") as test: writer = csv.writer(test , delimiter = ',' , quotechar = '"' , quoting = csv.QUOTE_ALL) writer.writerow([text,]) time.sleep(1)
注意点2
先ほどはスクレイピングによって違法にならないようにという注意点を行いました。おさらいしておきましょう。
- DoS攻撃にならないように注意する
- ウェブサイトも著作物だと認識する
- サイトの情報はものによっては個人情報である
大丈夫でしょうか?逮捕されてからでは遅いので、くれぐれも注意しましょう。
ではここではもっと軽い注意を並べていきます。
まずは動作時間です。例えば、とある大人気格闘ゲームの非公式レートサイトの登録者数は9万人を上回っています。(2021/8月時点)
ではこのサイトでのレートがどのような分布なのかを調べたいと思ったとします。
情報の抽出に0.5秒。sleepで最低限の1秒間アクセス間隔をあけたとして、一人分の情報抽出に1.5秒かかることになります。全員分を取得するには最低135000秒、すなわち約38時間かかることになります。
つまり、あなたの愛用するPCは38時間の間、火を噴きながら唸り続けることになります。(※性能による)
軽い気持ちで「このくらい全部とってやろう」などと思ってプログラムを動かしたが最後、土日がまるまる全部吹き飛ぶなんてこともあります。くれぐれも実行前にざっくりと実行時間を見積もっておきましょう。
最後に
読んでくださりありがとうございました。
この記事でスクレイピングって難しくないんだなと思っていただければ幸いです。ですが、きちんと注意しなければならない点があることも理解していただければと思います。
以上で本記事を終わります。
改めて読んでいただいてありがとうございました。