質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.58%

商品価格比較サービスロジックについて。

受付中

回答 2

投稿

  • 評価
  • クリップ 2
  • VIEW 644

score 1

前提・実現したいこと

https://zaikosokuho.com/のようなサービスを作成しながらpython学習しようと思っています。

amazon 楽天 ヤフーの商品一覧を作りたいのですがすべてが1つのAPIで取得することができない場合

どのような方法があるのでしょうか?

一覧ページには30件表示させページネーションを設けようと思っています。
*もしくはjsで取得しツイッターのようにスクロールで取得させる。

現在各APIより全件取得し表示では30件ずづと考えていますが、パフォーマンス、サーバー負荷を考えるとあまり得策ではない気がしています。

皆さんであればどのようにさせるのでしょうか?

使用するAPI

商品Aの一覧を作成する際、
下記のAPIを使用して取得する際

rakuten : rakuten develop
yahoo : valuecommerce
amzon: amazon develop

AMAZON 

商品名 金額
商品A 100
商品A 110
商品A 120
商品A 130
商品A 140
商品A 150

楽天

商品名 金額
商品A 200
商品A 210
商品A 220
商品A 230
商品A 240
商品A 250

yahoo

商品名 金額
商品A 10
商品A 310
商品A 320
商品A 330
商品A 340
商品A 350

一覧表示

商品名 金額 *補足*
商品A 10 yahoo
商品A 100 amazon
商品A 110 amazon
商品A 120 amazon
商品A 130 amazon
商品A 140 amazon

ご教授ください。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

+2

アクセスするたびにリアルタイムで価格を取得するのは負荷を考えると難しいので、
「API を使って価格を取得して、ローカルのデータベースに保存する処理」をスクリプトで書いておき、それを crontab とかで一定間隔 (例えば、1時間ごと) で実行、ページを表示する際はそのローカルのデータベースにキャッシュしたデータを引っ張ってくればいいのではないでしょうか。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/08/17 20:05

    とても参考になります。
    ありがとうございます。

    一点疑問な点として価格.comのように全商品対応となるとこの方法だと難しいのかと思いますがその際どのようにするものなのでしょうか?

    質問ばかりで申し訳ありませんがよろしくお願いします。

    キャンセル

  • 2020/08/17 20:08 編集

    > 全商品対応となるとこの方法だと難しいのかと思います

    どのような点が難しいと考えているのでしょうか?
    各ショッピングサイトの API の詳細についてはわかりかねますが、API で取得できる内容であれば、対象商品が複数あるとしてもそれをローカルのデータベースにキャッシュしておくことには変わりないのではないでしょうか?

    キャンセル

  • 2020/08/17 20:14

    難しい理由ですが楽天で出品されている商品は、2018年6月現在においての楽天市場の商品の出品数は「253,558,740点」です。 もう少しわかりやすい表記に直すと、2.5億点の商品が楽天市場に出品され、販売されているわけです。

    とのことです、これらをすべてローカルのデータベースにキャッシュさせるということでしょうか?

    それとも検索がかかった際に一回目のみAPiから取得しキャッシュ させるという意味でしょうか?

    よろしくおねがしいます。

    キャンセル

  • 2020/08/17 20:25 編集

    いろいろなカテゴリが対象であるとしても、売上上位100件とかある程度制限は必要かと思います。
    なので、例えば 30カテゴリあって、各カテゴリの上位100件とかであれば、30*100 = 3000 レコードなので、十分可能なデータ量だと思います。

    例えば、以下の価格比較サイトを見てみると、カテゴリごとに上位100件までが載っています。
    右上にかかれている更新日が現時刻より古いことから、回答に記載したようなローカルにキャッシュするアプローチであると推測できます。
    https://www.saiyasune.com/I2505.html

    自分ひとりしか使わないサービスなら、処理時間も気にしなくていいので、その場で API から必要な分だけとってきてもいいと思いますが、Web サイトとして公開するのであれば、アクセスのたびに API でデータをとってきたら、API の使用上限にすぐ引っかかります。

    キャンセル

0

シンプルに1商品のみで考えます。
また、各店舗は金額の低い順で返すものとし、ページネーションにも対応しているとします。

ただし、結果として出力したい順をAPIで指定できるのであれば、どんな順番でもよいです。
どのような順番であれ、各店舗のAPIは最大でもページネーションに必要な件数のみ取得すればよいでしょう。
その結果を並び替えて保持しておけばよいです。
ページネーションの結果、そのページ表示に足りなくなれば、その都度各APIから次のページ分を取得すればよいです。

以下、模擬コードです。
なお、このコードでは各ページにおいて厳密に金額の昇順の結果を返しません。
(たとえば3ページ目と4ページ目の結果など)
ちゃんとやろうとすれば、各APIの結果の最小値>現結果リストの最大値となるまで各API結果を取得しておく必要があります。

import random
import pprint

random.seed(110)

N_API = 3 # 各APIからの結果数
N_RET = 5 # 結果として返すページ当たりの件数

# 各API。呼び出し毎に金額の低い順にN_API個の値を返す
def api():
    i = 0
    while True:
        l = []
        for _ in range(N_API):
            i = i + random.randint(0,10)
            l.append(i)
        yield l

# 各API
apis = [('ama', api()), ('rak', api()), ('yah', api())]

# 各APIから必要な数の結果を返す
# 必要な数:各APIともに最低N_RETだけあればよい
def get_api_list():
    lst = []
    for api in apis:
        api_ret = []
        while len(api_ret) < N_RET:
            api_ret += [(api[0],v) for v in api[1].__next__()]
        lst += api_ret
    return lst

lst = []
for i in range(10): # 適当な回(ページ)数

    # ページ表示に必要な件数を割った
    if len(lst) < N_RET:
        lst += get_api_list()
        lst.sort(key=lambda x:x[1])

    top = lst[:N_RET]
    print('-----')
    pprint.pprint(top)
    lst = lst[N_RET:]

結果例

-----
[('yah', 5), ('yah', 5), ('ama', 6), ('yah', 6), ('rak', 10)]
-----
[('yah', 14), ('ama', 15), ('yah', 15), ('yah', 17), ('ama', 18)]
-----
[('rak', 18), ('rak', 19), ('ama', 24), ('rak', 27), ('ama', 31)]
-----
[('yah', 25), ('yah', 26), ('yah', 32), ('rak', 33), ('ama', 35)]
-----
[('yah', 40), ('rak', 41), ('ama', 42), ('yah', 47), ('rak', 51)]
-----
[('yah', 51), ('ama', 52), ('ama', 52), ('rak', 54), ('rak', 58)]
-----
[('ama', 60), ('rak', 62), ('ama', 66), ('rak', 67), ('rak', 72)]
-----
[('yah', 56), ('yah', 61), ('yah', 64), ('yah', 66), ('yah', 70)]
-----
[('yah', 72), ('ama', 75), ('rak', 75), ('rak', 77), ('rak', 84)]
-----
[('ama', 85), ('ama', 87), ('rak', 87), ('rak', 88), ('ama', 90)]

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.58%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る