住所データをスクレイピング、JSONへ保存

投稿者: | 2023-02-23
  • P237
  • URLに日本語を含む場合、URL(パーセント)エンコードが必要(urllib.parse.quote())
    • URLをコピーペーストすると%などで化ける
    • hを除きコピぺした後、hを後付けすればよい
    • ブラウザの見た目上はきちんと日本語が表示されている。
    • ただし、実際はエンコードされた状態(こちらが正)。なぜなら日本語はURLに使えないため。
    • そのためコピペするとエンコードされたものがコピーされてしまう
# 住所データをスクレイピング、JSONへ保存

import requests, time, json
from bs4 import BeautifulSoup
import urllib.parse
import sys

# 初期設定
datafile = './zipcode.json'
ken = '東京都'
shi = '目黒区'
# URLに日本語を含む場合、URL(パーセント)エンコードが必要(urllib.parse.quote())
target_url = 'https://{}?m=shi&shi={}&ken={}'.format(
    'api.aoikujira.com/zip/list.php',
    urllib.parse.quote(shi),
    urllib.parse.quote(ken),
)

# HTMLファイルをダウンロード
html = requests.get(target_url).text
time.sleep(1)
# HTMLを解析
soup = BeautifulSoup(html, 'html.parser')
# 郵便番号と住所が記述された要素を取得
tr_list = soup.select('#ziplist tr')
if len(tr_list) == 0:
    print('[Error]要素の取得に失敗')
    sys.exit()

result = []
# テーブルの各行を取得
for tr in tr_list:
    children = list(tr.children)
    code = children[0].text
    addr = children[1].text
    # ヘッダー行なら飛ばす
    if code == '郵便番号':
        continue
    result.append({'code': code, 'addr': addr})

# ファイルへ保存
with open(datafile, 'w', encoding='utf-8') as fp:
    json.dump(result, fp, indent=4, ensure_ascii=False)


# CSVへ書き出しとく
import csv
with open('zipcode.json', 'r', encoding='utf-8') as fp:
    data = json.load(fp)

with open('zipcode.csv', 'w', encoding='cp932', newline='') as fp:
    writer = csv.writer(fp)
    writer.writerow(['郵便番号', '住所'])
    for row in data:
        writer.writerow([row['code'], row['addr']])