PythonでWebスクレイピングをしてみよう。
requestsモジュール
Webスクレイピングを行うにはhttp通信をする必要がある。標準モジュールでも通信はできるが、ここではrequestsモジュールを使っていこう。
インストール
インストールの方法は環境によって様々だ。代表的なインストール方法をいかに示す。
(win)
$ pip install requests
or (mac)
$ pip3 install requests
or (win with gitbash)
$ py -m pip install requests
get通信
import requests
#指定urlにget通信
res=requests.get('https://joytas.net/kaba/')
#文字化け対策
res.encoding=res.apparent_encoding
print(res.text)
以下のようにhtmlがレスポンスされていれば成功だ。
post通信
import requests
#指定urlにpost通信
res=requests.post('https://joytas.net/php/calc.php',data={'x':10,'y':7})
#文字化け対策
res.encoding=res.apparent_encoding
print(res.text)
リクエストパラメーターはdata=の後ろにdict等で渡す。
以下のようにxとyを足した値がレスポンスされれば成功だ。
(サーバーサイドはxとyを受け取ったらその和をレスポンスするようにしてある)
BeautifulSoup
http通信ができるようになったのでスクレイピングをしていこう。スクレイピング用のライブラリは復数あるが、ここではBeautiful Soupを使っていく
$ pip install beautifulsoup4
or (mac)
$ pip3 install beautifulsoup4
or (git bash)
$ py -m pip install beautifulsoup4
BeautifulSoupオブジェクト作成
import requests
from bs4 import BeautifulSoup
res=requests.get('https://joytas.net/kaba/')
res.encoding=res.apparent_encoding
#第1引数にhtml文字列,第2引数にパーサーを指定する。今回は追加ライブラリ不要な'html.parser'を指定
soup=BeautifulSoup(res.text,'html.parser')
#BeautifulSoupオブジェクトをprintにそのまま渡すと全文を表示する
print(soup)
要素の取得(単数)
print(soup)をコメントアウトして以下を追記しよう
import requests
from bs4 import BeautifulSoup
res=requests.get('https://joytas.net/kaba/')
res.encoding=res.apparent_encoding
#html全体を取得
soup=BeautifulSoup(res.text,'html.parser')
#print(soup)
#タグで要素取得
ele=soup.find('title') #<title>コビトカバ</title>
#要素のtextコンテントを表示
print(ele.text) #コビトカバ
findメソッドにタグを指定することで要素を取得できる。この際復数ある要素を指定した場合でもfindは最初に見つけた一つだけを返す
要素の取得(復数)
import requests
from bs4 import BeautifulSoup
res=requests.get('https://joytas.net/kaba/')
res.encoding=res.apparent_encoding
#html全体を取得
soup=BeautifulSoup(res.text,'html.parser')
#print(soup)
#タグで要素取得
ele=soup.find('title')
#要素のtextコンテントを表示
print(ele.text)
#要素を結果セット(ResultSet)として取得
imgs=soup.find_all('img')
for img in imgs:
#属性にアクセスするにはgetメソッドを使う
print(img.get('src'))
その他の要素の取得方法
import requests
from bs4 import BeautifulSoup
res=requests.get('https://joytas.net/kaba/')
res.encoding=res.apparent_encoding
#html全体を取得
soup=BeautifulSoup(res.text,'html.parser')
#print(soup)
#タグで要素取得
ele=soup.find('title')
#要素のtextコンテントを表示
print(ele.text)
#要素を結果セット(ResultSet)として取得
imgs=soup.find_all('img')
for img in imgs:
#属性にアクセスするにはgetメソッドを使う
print(img.get('src'))
#その他の要素の取得方法
#idを指定
div=soup.find(id='headerImageBox')
#classで取得
imgs=soup.select('.headerImage')
for img in imgs:
print(img.get('src'))
演習
要素の取得方法がわかったところで、上記コビトカバサイトからコビトカバの名前の一覧を取得してみよう。
実行結果
動物園一覧をファイルに書き込む
それではここで、スクレイピングしたデータをファイルに書き込んでみよう。
import requests
from bs4 import BeautifulSoup
res=requests.get('https://joytas.net/kaba/')
res.encoding=res.apparent_encoding
soup=BeautifulSoup(res.text,'html.parser')
#li要素の中のaを全部取得
links=soup.select('li a')
#ファイル書き込み
with open('zoo.txt','w',encoding='utf-8') as file:
for link in links:
file.write(f'{link.text}:{link.get("href")}\n')
画像ダウンロード
サイトから画像をダウンロードしてみよう。
import requests
from bs4 import BeautifulSoup
#フォルダ操作モジュール
from pathlib import Path
#url操作モジュール
import urllib
#時間操作モジュール
import time
load_url='https://joytas.net/kaba/'
res=requests.get(load_url)
res.encoding=res.apparent_encoding
soup=BeautifulSoup(res.text,'html.parser')
#Pathオブジェクト作成
out_folder=Path('downloaded')
#Pathオブジェクトがdownloadedフォルダを作成
#(downloadedという名のフォルダがすでにあってもエラーにしない)
out_folder.mkdir(exist_ok=True)
#img要素を全部取得
imgs=soup.select('img')
#ファイル書き込み
for img in imgs:
src=img.get('src')
#画像相対URLを絶対URLに変換
img_url=urllib.parse.urljoin(load_url,src)
#get通信で画像をロード
loaded_img=requests.get(img_url)
#ファイル名取得
file_name=img.get('src').split('/')[-1]
#保存画像パス
out_path=out_folder.joinpath(file_name)
#wbはバイナリ書き込み
with open(out_path,"wb") as file:
#contentはバイナリデータ
file.write(loaded_img.content)
#DOS攻撃にならないように時間(1秒)あける
time.sleep(1)
スクレイピングする際はモラルを守ることが大切となる。スクレイピングが禁止されているサイトには行わないのはもちろんのこと、アクセスする際も今回のように間隔を開けながらアクセスすることが大切だ。今回は3枚しか画像がないが大量の画像があるサイトにこの処理を行ったら1秒間に大量のアクセスを行うことになりサーバーに負荷をかけてしまう。必ず今回のように間隔を開けながらアクセスしよう。
コメント