2024年7月にPythonプログラミングVTuberサプーさんが書かれた「VTuberサプーが教える! Python 初心者のコード/プロのコード」という書籍が発売されました。
以前からサプーさんのYouTubeの動画でPythonを学ぶこともあり、以前から知っていたので購入して読んでみましたが、自分のスクレイピングのコードに落とし込める部分が多くあったのでその一例を紹介できればと思います。
書籍紹介
「VTuberサプーが教える! Python 初心者のコード/プロのコード」のAmazonリンクはこちらとなります。
基本的なコーディングルールから効率的なテクニックまで、プロの視点でコードを書き直す方法を解説しています。Pythonを使いこなし、よりクリーンで安全なコードを書くためのヒントが満載の一冊です。初心者だけでなく、中級者にも役立つ内容が詰まっています。
コードへの落とし込み
zip関数に引数strict=Trueの指定追加
Pythonの組み込み関数としてzip関数というものが用意されています。zip関数は引数に繰り返し可能なオブジェクト(リスト、タプル等)を指定することで各引数で指定されたオブジェクトの要素を順番にタプルとして取り出すことができます。
使用例は以下の通りです。
names = ['西岡', '荻野', '井口']
nums = [7, 4, 6]
for name, num in zip(names, nums):
print(f'{name}: {num}')
# 出力
西岡: 7
荻野: 4
井口: 6zip関数の性質として指定したオブジェクトのいずれかがすべての値を返すと処理を終了します。例えばnamesの長さが3、numsの長さが2の場合は2回しかループしません。
names = ['西岡', '荻野', '井口']
nums = [7, 4]
for name, num in zip(names, nums):
print(f'{name}: {num}')
# 出力
西岡: 7
荻野: 4これだとスクレイピング時に不都合が生じることがありました。良い例が思いつかずあくまでサンプルのコードですが、names_tagとnums_tagの数が違った場合、何もなかったように一つのデータが消えてしまうことがあります。
names_tag = soup.select('.names')
nums_tag = soup.select('.nums')
for name_tag, num_tag in zip(names_tag, nums_tag):
print(f'{name_tag.text}: {num_tag.text}')ループする前にlen(names_tag)とlen(nums_tag)を比較してエラーを発生させればよいのですが、84ページを読むとzip関数に引数strict=Trueを指定することで指定したオブジェクトの長さが違う場合にエラーを発生させることができることが分かりました。
names_tag = soup.select('.names')
nums_tag = soup.select('.nums')
for name_tag, num_tag in zip(names_tag, nums_tag, strict=True): # strict=Trueを追加
print(f'{name_tag.text}: {num_tag.text}')このようにコードを置き換えることで以下のようなメリットが見込めます。
- 意図しないデータの消失/未取得に気付くことができる。
- if文によるデータの長さを比較して確認するためのコードの記載が不要となる。
loggerのexceptionメソッドの使用
スクレイピングツールを作成し、お客様に納品することがあります。納品後にサイトのHTML構造が変わったりしてエラーが発生することもあり、調査しやすいようにエラーログを掃き出す仕組みを入れています。これまでは例として以下のコードのようにしていました。
import logging
import traceback
try:
# エラーが発生しそうな処理
except Exception:
logger = logging.getLogger(__name__)
formatter = logging.Formatter(fmt='%(asctime)s - %(levelname)s : %(message)s')
fh = logging.FileHandler('./log.txt')
fh.setFormatter(formatter)
logger.addHandler(fh)
logger.error('Scraping error.\n%s', traceback.format_exc())何かしらのエラーが発生した際にloggerのerrorメソッドを使用して引数にtracebackモジュールのformat_exc関数を指定することでtracebackの内容をテキストファイルに出力しています。
しかし、書籍の182ページを読むと以下のコードで置き換えられることが分かりました。
import logging
try:
# エラーが発生しそうな処理
except Exception:
logger = logging.getLogger(__name__)
formatter = logging.Formatter(fmt='%(asctime)s - %(levelname)s : %(message)s')
fh = logging.FileHandler('./log.txt')
fh.setFormatter(formatter)
logger.addHandler(fh)
logger.exception('Scraping error.')loggerにはexceptionメソッドがあり、引数に指定した文字列の後にtracebackの内容が出力されます。更にlogger.exceptionを使用することで内部的にはlogger.errorと指定したときと同じようにERRORとして処理されます。
このようにコードを置き換えることで以下のようなメリットが見込めます。
- tracebackモジュールのimportが不要となる。
- traceback.format_exc()の記載が不要となる。
- tracebackを見やすくするために使用していた引数のmsgの後の改行(\n%s)が不要となる。


コメント