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

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

新規登録して質問してみよう
ただいま回答率
85.35%
スクレイピング

スクレイピングとは、公開されているWebサイトからページ内の情報を抽出する技術です。

JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

解決済

3回答

2739閲覧

Python3 スクレイピングでjson部分の括弧が入れ子になっている場合の抽出方法について教えて下さい

tanatomo

総合スコア19

スクレイピング

スクレイピングとは、公開されているWebサイトからページ内の情報を抽出する技術です。

JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

0グッド

0クリップ

投稿2020/10/04 03:07

編集2020/10/04 03:37

こんにちは
WEBページのjson表記部分で、
以下になっている場合の抽出方法が知りたいです。
抽出したい箇所は"line1"の”神奈川県”です。

▮json表記部分(例)▮

<script type="application/ld+json"> { "url": "**********", "title": "***", "description":"***", "Location": { "place": "***", "address": { "type": "***", "line1": "神奈川県", "line2": "横浜市", "line3": "磯子区", "Country": "JP" } } } </script>

▮コードで以下のように抽出しようとしましたが、エラーになりました。
json_2= soup.find("script", {"type": "application/ld+json"})
a=json_2["line1"]

⇒KeyError: 'line1'

どうぞよろしくお願いいたします。

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

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

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

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

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

meg_

2020/10/04 03:20

json表記部分(例)は{}の対応が合わない( } が足りない)と思いますが記入ミスでしょうか?
tanatomo

2020/10/04 03:26

ご指摘ありがとうございます。 閉じ括弧が一つ足りなかったので修正しました。
meg_

2020/10/04 03:29

他にも「,」が足りない部分があります。適当に修正したもので回答しましたので、実際のデータと違う部分があれば教えてください。
tanatomo

2020/10/04 03:41 編集

ありがとうございます。 「,」不足は、"description":"*"の後の部分ですね。 頂いた回答を元に実行してみたのですが、 今度は、 KeyError:'Location' となりました。 ちなみに先頭に<script type="application/ld+json">と表記されているのですが、 頂いた回答でいう、aと["Location"]の間に何かを入れる必要はあるのでしょうか。 ※そのまま入れてもエラーになりました。 引き続きよろしくお願いいたします。
tanatomo

2020/10/04 03:42

ありがとうございました。
guest

回答3

0

ベストアンサー

質問者様がsoup.find("script")で取り出しているのはjsonデータではなく
あくまでもjsonが表示される様になっているhtml上のソースであり
それを変数に代入したとしても、jsonデータとしては使用出来ません。
今一度、print(json_2, type(json_2))と、json_2の中身をprintして確認してみると良いでしょう。
otnさんが回答している様に、bs4で取得したタグ要素である事がわかると思います。

print(json_2, type(json_2))

<script type="application/ld+json"> { "url": "******", "title": "*", "description":"*", "Location": { "place": "*", "address": { "type": "*", "line1": "神奈川県", "line2": "横浜市", "line3": "磯子区", "Country": "JP" } } } </script> <class 'bs4.element.Tag'>

その為、それらをjsonデータとして取り扱うには
まずは取り出したjson_2の文字列だけを取得し、辞書型に変換する必要があります。

python

1from bs4 import BeautifulSoup 2import json 3 4html = '''<script type="application/ld+json"> 5{ 6"url": "******", 7"title": "*", "description":"*", 8"Location": { 9"place": "*", "address": { "type": "*", 10"line1": "神奈川県", 11"line2": "横浜市", 12"line3": "磯子区", 13"Country": "JP" 14} 15} 16} 17</script>''' 18 19soup = BeautifulSoup(html, 'html.parser') 20json_2 = soup.find('script', {'type': 'application/ld+json'}) 21data = json_2.text # 文字列を取得 22 23json_dict = json.loads(data) # 文字列をjsonとして辞書型で読み込む 24print(json_dict)

投稿2020/10/04 04:30

編集2020/10/04 04:48
nto

総合スコア1438

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

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

otn

2020/10/04 04:40

文字列がJSONであり、json.loadsしたものはdict形式ですね。 dictやlistなどをある形式で文字列化した物がJSONです。 (まあ、構造を持ってないデータも対象ですが)
nto

2020/10/04 04:48

私の解説がややおかしかったですね。 修正しておきました。
otn

2020/10/04 05:32

ところで、Python 3.8.6 for Windowsだと、json_2.text が空文字列になるのですが、 ntoさんの実行環境は何でしょうか?
nto

2020/10/04 05:46

python 3.8.1,windows10となります。
tanatomo

2020/10/04 05:53

丁寧に回答頂きありがとうございました。 「あくまでもjsonが表示される様になっているhtml上のソースであり それを変数に代入したとしても、jsonデータとしては使用出来ません。」 ⇒なるほど…理解ができました。 ありがとうございました!
otn

2020/10/04 06:03

あ、Python事態のバージョンというより、bs4のバージョンですね。 beautifulsoup4 4.9.3
nto

2020/10/04 06:19

先程コードを書いた端末に使用されたBeautifulSoupのバージョンは4.8.2となっております。 マイナーバージョンでの仕様の齟齬でしょうか。 その場合.stringで対処可能ですね。
otn

2020/10/04 06:30

そうなんですよ。stringで取れるのにtextで取れない理由が分からないため、コードが書けなかったのです。 4.8では取れるということで、変更情報を見るてみると、4.9で変わったみたいです。 * Embedded CSS and Javascript is now stored in distinct Stylesheet and Script tags, which are ignored by methods like get_text().
nto

2020/10/04 06:31

確認した所、4.9.0のリリース時に「Embedded CSS and Javascript is now stored in distinct Stylesheet and Script tags, which are ignored by methods like get_text() since most people don't consider this sort of content to be 'text'. This feature is not supported by the html5lib treebuilder.」と声明があり、要するにはインラインでのcssとjsなどの中身はテキストとして考えずget_text()や.textでの取得は出来ない様に仕様が変更されたとの事でした。
nto

2020/10/04 06:32

あ、同時のコメントになってしまい失礼しました。 頭に入れとかなきゃな情報でした。 ご指摘ありがとうございました。
guest

0

KeyError:'Location'

json_2は、bs4のノードなので、テキストを取り出して、JSONとしてパースしないといけないのでは?

あと、他の方のコメントにもありますが、実物をコピペしないと話が始まりません。

投稿2020/10/04 03:48

編集2020/10/04 03:49
otn

総合スコア85901

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

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

tanatomo

2020/10/04 04:09 編集

テキストを取り出して、JSONとしてパースしないといけないのでは? →なるほど! 自分があまりわかっていないようなので質問したいのですが、それはつまり"line1"を探して、 "神奈川県"を抽出するようなコードは、この場合難しいことを指していますか? 一度テキスト形式に直すことも試してしてみたのですが、その場合『○文字目〜▲文字』のような検索しかできなかった(繰り返し処理では、その時々で得られる箇所がズレる?)ため、キーワードで探す方法がないか聞きたくて投稿しました。 よろしければ教えてください。 よろしくお願いします。 ※そのまま載せるのは難しい事情があり、一方でどこまで加工して良いかがわからない状態でした。そのため質問が分かりにくくご迷惑をおかけしました。申し訳ありません。
otn

2020/10/04 04:14

> そのまま載せるのは難しい事情があり、一方でどこまで加工して良いかがわからない状態でした。 乗せても良い加工したデータを使ったテスト環境を作り、そのテスト環境で同じ現象が発生することを確認した上で、テスト環境のデータをコピペします。実行もしていないコードを載せてはいけません。 > この場合難しいことを指していますか? 難しくは無いと思いますけど。 > その場合『○文字目〜▲文字』のような検索しかできなかった(繰り返し処理では、その時々で得られる箇所がズレる? JSONとしてパースしてdict型に直せば良いです。
tanatomo

2020/10/04 05:54

回答ありがとうございました!
guest

0

a=json_2["line1"]KeyError: 'line1'が発生するのであれば下記でどうでしょうか?

質問のjsonではエラーが出るので下記とします。

json

1{ 2"url": "******", 3"title": "*", 4"description":"*", 5"Location": { 6"place": "*", 7"address": { "type": "*", 8 "line1": "神奈川県", 9 "line2": "横浜市", 10 "line3": "磯子区", 11 "Country": "JP" 12 } 13 } 14}

Python

1print(a["Location"]["address"]["line1"]) 2# '神奈川県'

投稿2020/10/04 03:27

meg_

総合スコア10760

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

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

tanatomo

2020/10/04 03:34

ありがとうございます。 「,」不足は、"description":"*"の後の部分ですね。 頂いた回答を元に実行してみたのですが、 今度は、 KeyError:'Location' となりました。
meg_

2020/10/04 03:38

ということは、 > WEBページのjson表記部分 と、質問に記載されているjson文字列が異なっているのでしょう。よく確認してみてください。 こちらでは実際のデータが分からないため、エラーの真因は判りません。
tanatomo

2020/10/04 03:41

かしこまりました。 ありがとうございます。 お手数をおかけしました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問