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

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

新規登録して質問してみよう
ただいま回答率
85.35%
Beautiful Soup

Beautiful Soupは、Pythonのライブラリの一つ。スクレイピングに特化しています。HTMLデータの構文の解析を行うために、HTMLタグ/CSSのセレクタで抽出する部分を指定することが可能です。

リストボックス

ユーザーがリストから1つ以上のアイテムを選択できるようにするGUI要素です。

連結リスト

連結リストとは、データ構造のひとつであるリストの中で、要素が前後の要素の情報を持つことで、要素が連結(リンク)しているリストの事を呼びます。

Python

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

selenium

Selenium(セレニウム)は、ブラウザをプログラムで作動させるフレームワークです。この原理を使うことにより、ブラウザのユーザーテストなどを自動化にすることができます。

Q&A

解決済

1回答

1186閲覧

同一ページから取得した複数の要素を一つの要素としてリストに格納したい

YummyD

総合スコア5

Beautiful Soup

Beautiful Soupは、Pythonのライブラリの一つ。スクレイピングに特化しています。HTMLデータの構文の解析を行うために、HTMLタグ/CSSのセレクタで抽出する部分を指定することが可能です。

リストボックス

ユーザーがリストから1つ以上のアイテムを選択できるようにするGUI要素です。

連結リスト

連結リストとは、データ構造のひとつであるリストの中で、要素が前後の要素の情報を持つことで、要素が連結(リンク)しているリストの事を呼びます。

Python

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

selenium

Selenium(セレニウム)は、ブラウザをプログラムで作動させるフレームワークです。この原理を使うことにより、ブラウザのユーザーテストなどを自動化にすることができます。

0グッド

0クリップ

投稿2020/05/09 13:08

beautifulSoup4とSeleniumを用いて単語帳を作成したい。

beautifulSoup4とSeleniumでWebページから要素を取得し、その要素をリストに格納する。その際、同一ページから取得した複数の要素を一つの要素としてリストに格納したい。
単語帳のイメージとしては、同じ行にキーワード、その説明、その関連語と並べたいです。

発生している問題

同色の網掛けがされているセルが同一ページ
上図のように同色で網掛けしてあるセルが同一ページから取得した要素です。複数の要素としてリストに格納すると、上図のように複数セルに出力されてしまい、title語とずれてしまいます。

該当のソースコード

Python

1#! python3.8 2 3import urllib.request,urllib.error 4import bs4 5import openpyxl 6from selenium import webdriver 7from time import sleep 8from openpyxl.styles import Alignment 9 10 11#Webページに遷移 12print('GooGling...') 13driver = webdriver.Firefox(executable_path='/Users/katsuhisaoikawa/opt/anaconda3/bin/geckodriver') 14url = 'http://ssd.cswiki.jp/index.php?%E6%AD%B4%E5%8F%B2%EF%BC%A1%E3%83%A9%E3%83%B3%E3%82%AF' 15driver.get(url) 16sleep(5) 17 18#ページ内のキーワードを示すHTMLを取得 19soup1 = bs4.BeautifulSoup(driver.page_source, 'html.parser') 20titles = [] 21for title in soup1.select('p a'): 22 titles.append(title.getText()) 23titles.remove('歴史キーワード') 24 25#キーワードの説明のページに遷移しHTMLを取得 26##キーワードのリンクのURLを取得 27explain_urls = [] 28elems_explain_url = driver.find_elements_by_css_selector('#body p a') 29for elem_explain_url in elems_explain_url: 30 explain_url = elem_explain_url.get_attribute('href') 31 explain_urls.append(explain_url) 32explain_urls.remove('http://ssd.cswiki.jp/index.php?%E6%AD%B4%E5%8F%B2%E3%82%AD%E3%83%BC%E3%83%AF%E3%83%BC%E3%83%89') 33##取得したリンクに遷移し、そのページのHTMLを取得 34explanations = [] 35related_terms = [] 36for explain_url_list in explain_urls: 37 driver.get(explain_url_list) 38 sleep(10) 39 soup2 = bs4.BeautifulSoup(driver.page_source, 'html.parser') 40 soup3 = bs4.BeautifulSoup(driver.page_source, 'html.parser') 41 for explanation in soup2.select('#body p'): 42 explanations.append(explanation.getText()) 43 for related_term in soup3.select('#body a'): 44 related_terms.append(related_term.getText()) 45 driver.back() 46 47new_explanations1 = [e for e in explanations if '歴史' not in e] 48new_explanations2 = [f for f in new_explanations1 if '【' not in f] 49new_related_terms1 = [s for s in related_terms if '歴史' not in s] 50new_related_terms2 = [t for t in new_related_terms1 if '地理' not in t] 51new_related_terms3 = [u for u in new_related_terms2 if '公民' not in u] 52new_related_terms4 = [v for v in new_related_terms3 if '†' not in v] 53# --- ここからスクレイピング結果を出力するコード --- 54 55# 既に用意しているファイルを開く 56wb = openpyxl.Workbook() 57 58# # 既に用意したファイルがなければ新規ワークブックを作成 59# wb = openpyxl.Workbook() 60 61sheet = wb.active 62sheet.title = 'A_rank' # ついでに「シート名」を変更 63 64# 「タイトル行」を入力(事前に入力していない場合) 65sheet["A1"].value = 'title' 66sheet["B1"].value = 'explaination' 67sheet["C1"].value = 'related_term' 68 69# フォントの設定 70 71#セルの設定 72 73# A2からC6まで順に出力 74n = len(titles) 75m = len(new_explanations2) 76l = len(new_related_terms4) 77 78for i in range(1,n): 79 sheet.cell(column = 1, row = i+1, value = titles[i-1]) 80for i in range(1,m): 81 sheet.cell(column = 2, row = i+1, value = new_explanations2[i-1]) 82for i in range(1,l): 83 sheet.cell(column = 3, row = i+1, value = new_related_terms4[i-1]) 84 85# 保存して閉じる 86wb.save('keyword_ver0.94.xlsx') 87wb.close() 88

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

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

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

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

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

guest

回答1

0

ベストアンサー

[改善案]
同一ページにある内容は、クラスを利用して、ひとまとまりのデータに集めてしまいましょう。

ひとまとまりのデータに集めておけば書き出しもわかりやすくなります。

各キーワードページの構造は、投稿された画像から察するに、おそらく以下のようになっていることでしょう。

| キーワード
|   └キーワード文字列(タイトル)
|   └説明1、説明2、説明3・・・
|   └関連用語1、関連用語2、関連用語3・・・

これをクラスを使って表現すると、以下のようになります、

class Keyword: title # キーワードテキスト explanations = [] # 説明 のリスト related_terms = [] # 関連用語 のリスト

各キーワードページで、このKeywordオブジェクトにデータを集約していけばよいのです。

また、集めたキーワードデータは、説明と関連用語で数が異なっている場合が考えられるため、エクセルへの書き出しの際は、それを念頭に置いて工夫する必要があります。

私はネットワーク上でテストしていないため、実際にうまく動くかはわかりませんが、上記に基づいたコード案が以下です。

[一部略してありますので、ご自分で補完してください]

#! python3.8 # copyright of below codes of modified part is © 2020 taizan-hokuto # Do not abuse. # In no event will I be liable to any person for any damage or loss that may arise from # the use of any information contained in, or displayed on, my codes. import urllib.request,urllib.error import bs4 import openpyxl from selenium import webdriver from time import sleep from openpyxl.styles import Alignment class Keyword: def __init__(self, title): self.title = title self.explanations = [] self.related_terms = [] def add_explanation(self, explanation): self.explanations.append(explanation) def add_related_terms(self, related_term): self.related_terms.append(related_term) # Webページに遷移 [略] # ページ内のキーワードを示すHTMLを取得 soup1 = bs4.BeautifulSoup(driver.page_source, 'html.parser') # Keywordオブジェクトを格納するためのリスト keywords = [] for keyword_part in soup1.select('p a'): # キーワード文字列を取得 title = keyword_part.getText() if title == '歴史キーワード': continue # Keyword オブジェクトの生成 kw = Keyword(title) # キーワードの説明のページに遷移しHTMLを取得 url = keyword_part.get('href') driver.get(url) sleep(10) soup2 = bs4.BeautifulSoup(driver.page_source, 'html.parser') soup3 = bs4.BeautifulSoup(driver.page_source, 'html.parser') for explanation_p in soup2.select('#body p'): explanation = explanation_p.getText() if ('歴史' in explanation) or ('【' in explanation): continue kw.add_explanation(explanation) for related_term_a in soup3.select('#body a'): related_term = related_term_a.getText() if ('歴史' in related_term) or ('地理' in related_term) or ('公民' in related_term) or ('†' in related_term): continue kw.add_related_terms(related_term) keywords.append(kw) # --- ここからスクレイピング結果を出力するコード --- [略] # 「タイトル行」を入力(事前に入力していない場合) [略] # 書き込み行 初期値 cursor = 2 for keyword in keywords: sheet.cell(column=1, row=cursor, value=keyword.title) sheet.cell(column=2, row=cursor, value=' '.join(keyword.explanations)) sheet.cell(column=3, row=cursor, value=','.join(keyword.related_terms)) cursor += 1 # 保存して閉じる [略]

投稿2020/05/09 15:58

編集2020/05/09 18:33
patapi

総合スコア820

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

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

YummyD

2020/05/10 12:28

ありがとうございます! 無事できました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問