はじめに
スクレイピングすることがあったので、そのときに得た小技の整理です。
使った環境
- python 3.x
- requests
- Beautiful Soup 4
- Pycharm
補足1
windowsでもpythonのインストールはかなりかんたんです。
pythonの公式サイトから、インストーラーをダウンロードして、実行するだけです。
Pycharmをつかえば、venvでの実行環境をつくるのもかんたんです。
pycharmからのterminalで、つくったpythonスクリプトの実行もできます。とくにこだわりがなく、さくっと実行環境をつくりたいならPycharmはおすすめです。(特に、Java系でIntelliJ IDEAをつかっている人に)
補足2
ライブラリのインストール
pip install requests
pip install beautifulsoup4
import文
import requests
from bs4 import BeautifulSoup
import math
import re
import csv
リクエストの作り方
パスパラメタ
これはpythonの文字列に変数を展開するのを使います
url1 = "https://sample.com/{path1}/{path2}".format(path1='testA', path2='testB')
クエリパラメタ
requestsの機能を使います。
res = requests.get('https://sample.com/test', params={'a': 'testA', 'b': 'testB'})
0埋めして、連番形式のパラメタを生成
01,02, ... 10 のような、数字の連番で2桁の文字列になっている、というようなパラメタのことがあります。このようなパラメタでfor文回すためのリストを、range
とzfill
で生成できます。
[str(i).zfill(2) for i in range(1, 11) ]
00, ... 09のように連番が0はじまりのときは
[str(i).zfill(2) for i in range(10) ]
なにがしかのprefixがつく場合は
[ 'XX' + str(i).zfill(2) for i in range(10) ]
とすると、XX00, ... XX09 となります。
レスポンスの取扱
beautifulsoupはbyte配列からも読み込めるので、requestsのレスポンスオブジェクトのcontentを使います。このやり方が文字化けが起きにくいようです。
res = requests.get(url)
soup = BeautifulSoup(res.content, "html.parser")
クラス名での検索
find_allかfindに、class_パラメタにセットしてやります。
タグを指定したい場合は、最初にそのタグを渡します
soup.find_all('a', class_='list-rst__rst-name-target')
固定のテキストでの検索
textパラメタに正規表現を渡します。
soup.find('th', text=re.compile('テスト'))
改行コード・空白文字の除去
strip()を使えば、だいたいうまくいきます
soup.find_all('a', class_='list-rst__rst-name-target').text.strip()
要素の存在チェック
if式を使えば、そこそこ楽にかけます。
tag = soup.find(id='test')
text = tag.text.strip() if tag else ''
ページング
最終ページの求め方
検索結果の最初のページなどで、全件の数がわかっているものとします。
1ページあたりの件数もわかっているものとします。
全件/1ページあたりの件数を、少数点切り上げするだけです。
割った結果が少数になるように、全件か、1ページあたりの件数のどちらかをfloatにします。
total_count = float(soup.find('p', id='total_count').string)
max_page = math.ceil(total_count / page_size)
ページングのためのfor文
1始まりなら、こうなります。
for page_number in range(1, max_page + 1):
print(page_number)
0はじまりなら、下記のようになります。
for page_number in range(max_page):
print(page_number)
ファイルへの書き込み
項目が決まっている場合は、csv.DictWriterが便利です。
csv、文字コードをUTF-8、囲み文字をダブルクォート、囲み文字をすべてつける場合は下記になります。delimiterを指定すれば、tsvにもできます。
with open('test.csv', 'a', newline='', encoding='utf8') as f:
writer = csv.DictWriter(
f,
fieldnames=['id', 'name'],
quotechar='"',
quoting=csv.QUOTE_ALL
)
id = ...
name = ...
rowdict = {'id': id, 'name': name}
writer.writerow(rowdict)
参考リンク
- https://qiita.com/oppasiri330/items/0f9526a1c507ae170a56
- https://qiita.com/Azunyan1111/items/9b3d16428d2bcc7c9406
- https://qiita.com/akidroid/items/df527a78365437e9b2d0
- https://qiita.com/Atupon0302/items/352811a2d92d6ebab8c2
- https://qiita.com/naka-j/items/ef38498273e036c26f4d
- https://yuki.world/python-requests-beautifulsoup-text-garbling/
- https://qiita.com/shohei-nagano/items/79cc15e22e88b11bb677