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

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

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

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

Python

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

データマイニング

データマイニングは、購買履歴やクレジットカードの利用履歴、電話の通話履歴など企業にある大量のデータを解析して、その中に隠れたパターンやルールを探し出す技術です。DMと略されることもあります。

Q&A

解決済

2回答

982閲覧

同じ種類のタグの中から異なる種類のデータを出力するースクレイピングー

jury_new

総合スコア31

スクレイピング

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

Python

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

データマイニング

データマイニングは、購買履歴やクレジットカードの利用履歴、電話の通話履歴など企業にある大量のデータを解析して、その中に隠れたパターンやルールを探し出す技術です。DMと略されることもあります。

0グッド

0クリップ

投稿2020/05/20 20:28

同じ種類のタグから異なる種類のデータを出力するースクレイピングー

wikipediaより歴代総理大臣の漢字のフルネームとその任期について別々にスクレイピングしようと考えています。
最初になんとなく書いたコード(発生している問題の上記の方のコード)に修正を加えているような状況です。

今回ご教示頂きたい点はコードの修正中に起こった問題に関してです。
修正中に起こった問題は最初に書いていたコード(発生している問題の上記のコード)ではデータが複数得られたのですが、その後書いたコード(発生している問題の下記のコード)ではデータが一つだけしか得られませんでした。
上記のコードのようにデータを複数取得したいと考えているのですが、同じようにデータを得られない理由及びどうしたら複数のデータを取得することが可能なのかご教示頂きたいです。

余談ですが、修正途中に起こった問題のため最終的な僕がしようとしているスクレイピングのゴールではありません。

発生している問題

エラーではないです。出力内容に問題があります。
上記の場合だと複数のタグの中身が返されるのですが、下記の場合のコードは返されません。最終的に取得したい内容が少し異なるのですが、遡って上記のコードと同じ部分の出力を確かめてみました。その結果、データを取得してこようとした階層が同じにも関わらず取得できるデータの量が異なっています。

このコードでは複数の結果が得られました。 import requests import matplotlib.pyplot as plt from matplotlib.offsetbox import AnchoredText from bs4 import BeautifulSoup from requests.exceptions import Timeout url = 'https://ja.wikipedia.org/wiki/%E5%86%85%E9%96%A3%E7%B7%8F%E7%90%86%E5%A4%A7%E8%87%A3#%E5%86%85%E9%96%A3%E7%B7%8F%E7%90%86%E5%A4%A7%E8%87%A3%E3%81%AE%E4%B8%80%E8%A6%A7_2' try: r = requests.get(url,timeout=3.5) except Timeout: print('this is timeout error') pass html_soup = BeautifulSoup(r.text,'html.parser') all = html_soup.find('table',class_='sortable wikitable') def person(): for per in all: for two in all.find_all('tr'): for three in two.find_all('td'): new = three.get_text(strip=True) print(new) person()
このコードはデータは一つしか出力できませんでした。(最初の一つのタグの中身のみの出力) import requests import re import matplotlib.pyplot as plt import numpy as np from matplotlib.offsetbox import AnchoredText from bs4 import BeautifulSoup from requests.exceptions import Timeout url = 'https://ja.wikipedia.org/wiki/%E5%86%85%E9%96%A3%E7%B7%8F%E7%90%86%E5%A4%A7%E8%87%A3#%E5%86%85%E9%96%A3%E7%B7%8F%E7%90%86%E5%A4%A7%E8%87%A3%E3%81%AE%E4%B8%80%E8%A6%A7_2' try: r = requests.get(url,timeout=3.5) except Timeout: print('this is timeout error') pass html_soup = BeautifulSoup(r.text,'html.parser') all = html_soup.find('table',class_='sortable wikitable') def person_name(): for per in all: for two in all.find_all('tr'): for three in two.find_all('td'): un = three.get_text(strip=True) for more in three.find_all('b'): for final in more.find_all('a'): text = more.get_text(strip=True) #上記のコードと比べるためにあえて出力する内容を戻しています。 return print(un) person_name()

試したこと

1、関係ないかとは思ったのですが一応、
returnでデータを返すと出力されるデータの量が減るのかと考え、
returnを削除したのですが結果は変わりませんでした。

2、下記のコードを遡ってprint関数でデータが複数取得できる階層を探したのですが見つかりませんでした。自分の解釈では同じ階層から情報を取ろうとしているのにも関わらずデータの量が変わっているためどこが問題点なのかも分かりません。

3、上記のコードと下記のコードではfor文の次の行のインデントが若干異なっていることに気づき修正しましたが改善がなかったためコードを元に戻しています。エラーが出ない理由は分からずじまいだったため無視しました。

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

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

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

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

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

guest

回答2

0

python

1target = 'https://ja.wikipedia.org/wiki/%E5%86%85%E9%96%A3%E7%B7%8F%E7%90%86%E5%A4%A7%E8%87%A3#%E5%86%85%E9%96%A3%E7%B7%8F%E7%90%86%E5%A4%A7%E8%87%A3%E3%81%AE%E4%B8%80%E8%A6%A7_2' 2soup = BeautifulSoup(requests.get(target).content, 'html.parser') 3table = soup.find('table', class_='sortable wikitable') 4 5minister_dict = {} 6 7for tr in table.find_all('tr'): 8 cnt = 0 9 for td in tr.find_all('td'): 10 if cnt == 0: 11 name = td.find('a').get('title') 12 elif cnt == 3: 13 if td.string is None: 14 a = td.find_all('a') 15 signal = [title.get('title') for title in a] 16 else: 17 signal = td.string.replace('\n', '') 18 minister_dict[name] = signal 19 cnt += 1

投稿2020/05/22 06:08

nto

総合スコア1438

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

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

jury_new

2020/05/22 13:13

ntoさん、ご回答ありがとうございます! 今回は、x98000さんがいち早くご回答いただいたと言う点と質問応対に応じていただけたためベストアンサーはx98000さんに選ばせていただきました。申し訳ありません。 この度はご回答ありがとうございました。
guest

0

ベストアンサー

1つ目

python

1 for three in two.find_all('td'): 2 3 new = three.get_text(strip=True) 4 print(new)

forループの中でprint(new)が複数回呼ばれていますが、

2つ目

python

1 for three in two.find_all('td'): 2 un = three.get_text(strip=True) 3 for more in three.find_all('b'): 4 for final in more.find_all('a'): 5 text = more.get_text(strip=True) 6 #上記のコードと比べるためにあえて出力する内容を戻しています。 7 return print(un)

forループが終わったあとに**「最後の」**unをprintしているためです。

ちなみに、return print(un)の表記はおかしいです。これでは値が戻りません。
書くとしたら、

python

1 return un 2ret = person_name() 3print(ret)

です。

投稿2020/05/21 00:08

x98000

総合スコア1096

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

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

jury_new

2020/05/21 11:53

x98000さん、返答ありがとうございます! コードを書き換えてみたのですが、変化がありません。 上記で指摘して頂いた2つ目の点について、returnの行にprintを置いてしまったことが失敗の原因だと言うことでしょうか?それともそもそものfor文の行に原因があるのでしょうか? 何度かコードを修正していたのですが、、上手くいきません。 申し訳ないのですが、もしよろしければ今回のエラーの根底にある原因の考察についてお聞かせいただけないでしょうか。重ねて質問申し訳ありません。
x98000

2020/05/21 22:23

new も un も<td>...</td>内の1項目しか入ってきません。「あへ しんそう/安倍晋三」とか「平成-令和」とかです。 1つ目の例では、forループの中でnewを次々とprintしているので全て出力されます。 2つ目の例では、forループが終わったあとに、最後のunの値(昭和)を1回だけ出力しているためです。 return文は根本原因ではありません。 理解出来ないようであれば、修正したソースコードを質問に追記してください。
jury_new

2020/05/22 07:28

解決しました。ありがとうございました! 見落としていたミスが何個か見つかりました。 この度は本当にありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問