<jupyter_start><jupyter_text>2.1.6 APIによる入手 Yahoo APIを利用してショッピングのレビューコメントを取得<jupyter_code># リスト 2.1.20
# Yahoo ショッピングのカテゴリID一覧を取得する

import requests
import json
import time
import csv

# エンドポイント
url_cat = 'https://shopping.yahooapis.jp/ShoppingWebService/V1/json/categorySearch'

# アプリケーションid (p.34の方法で取得した値を設定して下さい)
appid = 'xxxx'

# 全カテゴリファイル
all_categories_file = './all_categories.csv'

# APIリクエスト呼び出し用関数
def r_get(url, dct):
    time.sleep(1) # 1回で1秒あける
    return requests.get(url, params=dct)

# カテゴリ取得用関数
def get_cats(cat_id):
    try:
        result = r_get(url_cat, {'appid': appid, 'category_id': cat_id})
        cats = result.json()['ResultSet']['0']['Result']['Categories']['Children']
        for i, cat in cats.items():
            if i != '_container':
                yield cat['Id'], {'short': cat['Title']['Short'], 'medium': cat['Title']['Medium'],  'long': cat['Title']['Long']}
    except:
        pass
# リスト 2.1.21
# カテゴリ一覧CSVファイルの生成

# ヘッダ
output_buffer = [['カテゴリコードlv1', 'カテゴリコードlv2', 'カテゴリコードlv3',
    'カテゴリ名lv1', 'カテゴリ名lv2', 'カテゴリ名lv3', 'カテゴリ名lv3_long']]

with open(all_categories_file, 'w') as f:
    writer = csv.writer(f, lineterminator='\n')
    writer.writerows(output_buffer)
    output_buffer = []  

# カテゴリレベル１
for id1, title1 in get_cats(1):
    print('カテゴリレベル１ :', title1['short'])
    try:
        # カテゴリレベル２
        for id2, title2 in get_cats(id1):

            # カテゴリレベル３
            for id3, title3 in get_cats(id2):
                wk = [id1, id2, id3, title1['short'], title2['short'], title3['short'], title3['long']]
                output_buffer.append(wk)

            # ファイル書き込み
                with open(all_categories_file, 'a') as f:
                    writer = csv.writer(f, lineterminator='\n')
                    writer.writerows(output_buffer)
                    output_buffer = []                
    except KeyError:
        continue    
# リスト 2.1.22
# CSVファイルの内容確認

import pandas as pd
from IPython.display import display
df = pd.read_csv(all_categories_file)
display(df.head())
# リスト 2.1.23
# スマホのコード確認

df1 = df.query("カテゴリコードlv3 == '49331'")
display(df1)
# リスト 2.1.24
#  レビューコメントの取得

import requests
import time

url_review = 'https://shopping.yahooapis.jp/ShoppingWebService/V1/json/reviewSearch'

# アプリケーションid
# 書籍ではappidは伏せ字にしてください
appid = '<KEY>

# レビュー取得件数。最大50。APIの仕様。
num_results = 50
num_reviews_per_cat = 99999999

# テキストの最大・最小文字数。レビュー本文がこれより長い・短いものは読み飛ばす。
max_len = 10000
min_len = 50

def r_get(url, dct):
    time.sleep(1) # 1回で1秒あける
    return requests.get(url, params=dct)

# 指定したカテゴリidのレビューを返す
def get_reviews(cat_id, max_items):
    # 実際に返した件数
    items = 0
    # 結果配列
    results = []
    # 開始位置
    start = 1

    while (items < max_items):
        result = r_get(url_review, {'appid': appid, 'category_id': cat_id, 'results': num_results, 'start': start})
        if result.ok:
            rs = result.json()['ResultSet']
        else:
            print('エラーが返されました : [cat id] {} [reason] {}-{}'.format(cat_id, result.status_code, result.reason))
            if result.status_code == 400:
                print('ステータスコード400(badrequestは中止せず読み飛ばします')
                break
            else:
                exit(True)
                
        avl = int(rs['totalResultsAvailable'])
        pos = int(rs['firstResultPosition'])
        ret = int(rs['totalResultsReturned'])
        #print('総ヒット数: %d  開始位置: %d  取得数: %d' % (avl, pos, ret))
        reviews = result.json()['ResultSet']['Result']
        for rev in reviews:
            desc_len = len(rev['Description'])
            if min_len > desc_len or max_len < desc_len:
                continue
            items += 1
            buff = {}
            buff['id'] = items
            buff['title'] = rev['ReviewTitle'].replace('\n', '').replace(',', '、')
            buff['rate'] = int(float(rev['Ratings']['Rate']))
            buff['comment'] = rev['Description'].replace('\n', '').replace(',', '、')
            buff['name'] = rev['Target']['Name']
            buff['code'] = rev['Target']['Code']
            results.append(buff)
            if items >= max_items:
                break
        start += ret
        #print('有効件数: %d' % items)
    return results
# リスト2.1.25
# コメント一覧の取得と保存

import json
import pickle
# get_reviews(code, count) レビューコメントの取得
# code: カテゴリコード (all_categories.csv)に記載のもの
# count: 何件取得するか

result = get_reviews(49331,5)
print(json.dumps(result, indent=2,ensure_ascii=False))<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1465324384787472, 'fraction_numerical': 0.024384787472035794, 'mean_word_length': 2.722731057452123, 'pattern_counts': {'":': 0, '<': 8, '<?xml version=': 0, '>': 8, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 1, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '1', 'dir': 'jupyter-structured-clean-dedup', 'id': '45657', 'license': 'Apache-2.0', 'n_tokens_mistral': 1934, 'n_tokens_neox': 1860, 'n_words': 306, 'path': 'samples/ch02-01/ch02-01-20.ipynb', 'repo_name': 'TaikiOkamoto/sample_code', 'size': '4522'}