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

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

新規登録して質問してみよう
ただいま回答率
85.50%
Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

2739閲覧

amazonAPIを利用した商品の価格取得が出来ない。(python)

nokonoko_1203

総合スコア17

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2018/02/16 04:29

編集2018/02/17 08:02

いつもお世話になっております。

タイトルの通り、URL・asin・titelは取得できるのですが、商品の価格が取得できません。

from amazon_api import amazon
でシークレットキー等を取得しております。

書いたコードは以下になります。

python

1# -*- coding: utf-8 -*- 2import bottlenose 3import requests 4from bs4 import BeautifulSoup 5import time 6import traceback 7import re 8from urllib.error import HTTPError 9import pprint 10from amazon_api import amazon 11 12item_data = [] 13key = "python" # input("search? >>") 14 15 16def getResponses(): 17 while True: 18 try: 19 # xmlでレスポンスを取得 20 response = amazon.ItemSearch( 21 Keywords=str(key), 22 SearchIndex="All", 23 ItemPage='1', 24 ResponseGroup="Large" 25 ) 26 # xmlをパース 27 soup = BeautifulSoup(response, "lxml") 28 items = soup.findAll("item") 29 for item in items: 30 # print(item.prettify()) 31 price_dict = item.find("formattedprice") 32 # price_data = item.find(re.compile(r"price", item)).text 33 price = price_dict.contents[0] 34 pprint.pprint(price_dict.__dict__) #__dict__メソッドを覗く 35 print("価格を取得しました: ", price) 36 item_data.append({ 37 'asin': item.find('asin').text, 38 'title': item.find('title').text, 39 "price": price, 40 'url': item.find('detailpageurl').text 41 }) 42 print("データをリストへ格納します: ", str(len(item_data))) 43 except HTTPError: #503エラーが出たら2秒後に再取得する 44 print("再取得しています....") 45 time.sleep(2) 46 except TypeError as err: #TypeErrorが出たらエラーメッセージを出力して処理を中断する 47 print("TypeError:処理を中断します") 48 traceback.print_exc() 49 break 50 except AttributeError as err: #パースの仕方に問題があるとき 51 print("パースの仕方に問題があります") 52 traceback.print_exc() 53 print("検索を終了します....") 54 break 55 except : #それ以外のエラー 56 print("エラーが発生しました") 57 traceback.print_exc() 58 print("検索を終了します....") 59 break 60 print("リスト({}件のデータ)を出力します....".format(str(len(item_data))), "\n", item_data) 61 print(item_data) 62 return item_data 63 64if __name__ == '__main__': 65 book_lists = getResponses() 66 print(book_lists) 67 try: 68 print("データの取得に成功しました", "\n", "asin・商品名・URLを出力します", "\n") 69 for book_dicts in book_lists: 70 print("asin: ", book_dicts["asin"]) 71 print("title: ", book_dicts["title"]) 72 # print("price: ", book_dicts["price"]) 73 print("url: ", book_dicts["url"]) 74 print("\t") 75 except TypeError as err: 76 print(err) 77 print("処理を終了します....")

出力は以下になります。

for文の途中で止まっているようなのですが…どうにも対処法が分かりません。

{'attrs': {}, 'can_be_empty_element': False, 'contents': ['¥ 2,376'], 'hidden': False, 'known_xml': False, 'name': 'formattedprice', 'namespace': None, 'next_element': '¥ 2,376', 'next_sibling': None, 'parent': <lowestnewprice><amount>2376</amount><currencycode>JPY</currencycode><formattedprice>¥ 2,376</formattedprice></lowestnewprice>, 'parser_class': <class 'bs4.BeautifulSoup'>, 'prefix': None, 'preserve_whitespace_tags': {'textarea', 'pre'}, 'previous_element': 'JPY', 'previous_sibling': <currencycode>JPY</currencycode>} 価格を取得しました: ¥ 2,376 データをリストへ格納します: 1 パースの仕方に問題があります Traceback (most recent call last): File "/home/ubuntu/workspace/tweetbot123777/amazon_item_search.py", line 33, in getResponses price = price_dict.contents[0] AttributeError: 'NoneType' object has no attribute 'contents' 検索を終了します.... リスト(1件のデータ)を出力します.... [{'title': '独学プログラマー Python言語の基本から仕事のやり方まで', 'url': 'https://...', 'asin': '4822292274', 'price': '¥ 2,376'}] [{'title': '独学プログラマー Python言語の基本から仕事のやり方まで', 'url': 'https://...', 'asin': '4822292274', 'price': '¥ 2,376'}] [{'title': '独学プログラマー Python言語の基本から仕事のやり方まで', 'url': 'https:...', 'asin': '4822292274', 'price': '¥ 2,376'}] データの取得に成功しました asin・商品名・URLを出力します asin: 4822292274 title: 独学プログラマー Python言語の基本から仕事のやり方まで url: https://www.amazon.co.jp/%E7%8B%AC%E5%AD%A6%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9E%E3%83%BC-Python%E8%A8%80%E8%AA%9E%E3%81%AE%E5%9F%BA%E6%9C%AC%E3%81%8B%E3%82%89%E4%BB%95%E4%BA%8B%E3%81%AE%E3%82%84%E3%82%8A%E6%96%B9%E3%81%BE%E3%81%A7-%E3%82%B3%E3%83%BC%E3%83%AA%E3%83%BC%E3%83%BB%E3%82%A2%E3%83%AB%E3%82%BD%E3%83%95/dp/4822292274?SubscriptionId=AKIAIOE4UGAEQ6QGR3RA&tag=nokonoko1200e-22&linkCode=xm2&camp=2025&creative=165953&creativeASIN=4822292274

対応策をご教示願います。

追記:皆様のおかげで無事に解決できました!
有難うございました!

出来上がったコードを下に記載しておきます!****

python

1# -*- coding: utf-8 -*- 2import bottlenose 3import requests 4from bs4 import BeautifulSoup 5import time 6import traceback 7import re 8from urllib.error import HTTPError 9import pprint 10from amazon_api import amazon 11 12item_data = [] 13key = "アフィリエイト" # input("search? >>") 14 15 16def getResponses(): 17 while len(item_data) < 10: 18 print("データを取得します...") 19 try: 20 # xmlでレスポンスを取得 21 response = amazon.ItemSearch( 22 Keywords=str(key), 23 SearchIndex="All", 24 ItemPage='1', 25 ResponseGroup="Large" 26 ) 27 # xmlをパース 28 soup = BeautifulSoup(response, "lxml") 29 # itemタグを子・孫要素全て含めてリストで取得 30 items = soup.findAll("item") 31 for item in items: # 商品情報を1件ずつ取り出す 32 price_dict = item.find("amount") # 商品の価格情報を取得 33 try: 34 price = price_dict.contents[0] 35 except AttributeError: # Kindleの商品の場合<amount>タグが存在しない 36 print("xmlに<amount>タグが記載されていないため商品価格が取得できません...再取得します...") 37 url = item.find('detailpageurl').text 38 request = requests.get(url) 39 soup_url = BeautifulSoup(request.content, "lxml") 40 text = str(soup_url.find("td", {'class':'a-color-price a-size-medium a-align-bottom'})) 41 try: 42 search = re.search(r"\s+¥(\s\d+),(\d+)\s", text) #検索パターンのサーチ 43 price = search.group(1) + search.group(2) 44 except AttributeError: 45 print("価格が1000円以下ですので、情報を再取得します...") 46 for i in range(10): 47 try: 48 url = item.find('detailpageurl').text 49 request = requests.get(url) 50 soup_url = BeautifulSoup(request.content, "lxml") 51 text = str(soup_url.find("td", {'class':'a-color-price a-size-medium a-align-bottom'})) 52 search = re.search(r"\s+¥(\s\d+)\s", text) #検索パターンのサーチ 53 price = search.group(1) 54 except: 55 print("再取得しています...({}回目)".format(i)) 56 else: 57 break 58 print("価格を取得しました: ", price) 59 item_data.append({ 60 'asin': item.find('asin').text, 61 'title': item.find('title').text, 62 "price": price, 63 'url': item.find('detailpageurl').text 64 }) 65 print("データをリストへ格納します: ", str(len(item_data)), "\n") 66 except HTTPError: #503エラーが出たら2秒後に再取得する 67 print("HTTPError: 再取得しています...") 68 time.sleep(2) 69 except TypeError as err: #TypeErrorが出たらエラーメッセージを出力して処理を中断する 70 print("TypeError: 処理を中断します") 71 traceback.print_exc() 72 break 73 except AttributeError as err: #パースの仕方に問題があるとき 74 print("パースの仕方に問題があります") 75 traceback.print_exc() 76 print("検索を終了します...") 77 break 78 except : #それ以外のエラー 79 print("エラーが発生しました") 80 traceback.print_exc() 81 print("検索を終了します....") 82 break 83 print("合計{}件のデータリストに格納しました....".format(str(len(item_data))), "\n") 84 return item_data 85 86 87if __name__ == '__main__': 88 book_lists = getResponses() 89 try: 90 print("データの取得に成功しました", "\n", "asin・商品名・URLを出力します", "\n") 91 for book_dicts in book_lists: 92 print("asin: ", book_dicts["asin"]) 93 print("title: ", book_dicts["title"]) 94 print("price: ", book_dicts["price"]) 95 print("url: ", book_dicts["url"]) 96 print("\t") 97 except TypeError as err: 98 print(err) 99 print("処理を終了します....")

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

namnium1125

2018/02/16 04:47

一見価格も取得できているように見えるのですが、具体的にどこでどういう風な結果にならないことが問題なのでしょうか?
nokonoko_1203

2018/02/16 05:18 編集

すいません。正常に取得出来ていれば価格が10件拾えるはずなのですが、現状では最初の商品の1件しか取得できておらず、for item in itemsのループの途中でエラーが発生しています。
nokonoko_1203

2018/02/16 05:17

出力結果の中央部緑色の箇所でAttributeError: 'NoneType' object has no attribute 'contents'が発生しています。最終的には出力結果の最下段のようなものに商品の価格を追加したものが10件表示されるようにしたいです。宜しくお願い致します。
guest

回答2

0

ベストアンサー

kindle商品でフォーマットが異なるのかもしれませんね。

try~exceptで囲むか、if price_dict is None: continueを入れておくのはどうでしょう。

投稿2018/02/16 08:53

mkgrei

総合スコア8560

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

nokonoko_1203

2018/02/17 06:04

xmlをしっかりと確認したところ、どうやら仰る通りKindleの商品は<formattedprice>タグがありませんでした! if price_dict is None: でkindleの商品だけURLからhtmlを拾ってきてパースし、その後に正規表現で検索することで無事に金額を取得することができました! 有難うございます!
guest

0

とりあえずエラー名から言えるのは2回目以降はprice_dict = item.find("formattedprice")price_dictに代入されるのがNoneであるということです。

なぜNoneになるかはレスポンスのxmlを見てみないとわかりません。

投稿2018/02/16 06:02

編集2018/02/16 10:53
namnium1125

総合スコア2043

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

nokonoko_1203

2018/02/17 06:05

xmlをしっかりと確認したところ、<formattedprice>タグが無い商品がありました! タグがないものはURLからhtmlを拾ってきてパースし、その後に正規表現で検索することで無事に金額を取得することができました! 有難うございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問