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

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

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

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

Beautiful Soup

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

Python

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

selenium

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

Q&A

解決済

1回答

3134閲覧

リンクを順にクリックして個別ページの要素を取得を繰り返す(スクレイピング)

pasomtr

総合スコア20

スクレイピング

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

Beautiful Soup

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

Python

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

selenium

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

0グッド

2クリップ

投稿2020/01/27 10:29

編集2020/01/28 01:32

行いたい内容

現在、BeautifulSoupとseleniumを用いてスクレイピング行っています。

1.一覧ページのリンクをクリック
2.個別ページを開いて要素取得
3.一覧に戻って次のリンクをクリック
4.個別ページを開いて要素取得
上記のように大枠としては動かしたいのですが、思うように要素が取得出来ませんので、お力添え頂けますと幸いです。

参考サイト
https://qiita.com/Gen6/items/66f190d3c9e345e97ed2

処理の流れ

1.beautiful soup の.find_elements_by_xpathに渡す文字列を記述
2.以下の内容を10回繰り返す
3.beautiful soup の.find_elements_by_xpathでリンクをクリック
4.for page_title in bs.find_all('meta', attrs={'property': 'og:title'}):でタイトル要素取得
5.for script_ele in bs.find_all ( "script" ):で<script>内のイメージurlを全て抽出
6.blanks = ['' for _ in range(1,len(image_url))]でimageの数だけ空白を追加
7.ウィンドウをバックして一覧にもどる
8.カウントに1を加え次の要素をクリック

問題点

上記の様に行いたいのですが、
for page_title in bs.find_all('meta', attrs={'property': 'og:title'}):

image_urlが出力されません。

記述しているコード

python

1import urllib.request 2import pandas as pd 3from bs4 import BeautifulSoup 4from selenium import webdriver 5from selenium.common.exceptions import NoSuchElementException 6import time 7driver = webdriver.Chrome ( executable_path=r'C:\Users\chromedriver.exe' ) 8driver.get ("https://hogehoge.com/" ) 9 10html = driver.page_source 11bs = BeautifulSoup ( html, "html.parser" ) 12time.sleep ( 5 ) 13 14 15for i in range(1): 16 try: 17 name_list = [] 18 19 path_front = '//*[@id="j-wishlist-container"]/div/div[1]/div[' 20 count = 2 21 path_end = ']/div/div[1]' 22 23 for _ in range(10): 24 path = path_front + str(count) + path_end 25 for l in driver.find_elements_by_xpath(path): 26 l.click() 27 try: 28 driver.find_element_by_class_name('next-dialog-close').click() 29 except: 30 pass 31 break 32 break 33 for page_title in bs.find_all('meta', attrs={'property': 'og:title'}): 34 print (page_title['content']) 35 for script_ele in bs.find_all ( "script" ): 36 text_list = str(script_ele).split("\"")# 引用符「"」で分割 37 image_url = [] 38 for img_url in text_list: 39 if img_url.startswith("http") and img_url.endswith("jpg"): 40 image_url.append(img_url) 41 blanks = ['' for _ in range(1,len(image_url))] 42 print (image_url) 43 break 44 break 45 break 46 break 47 driver.back() 48 count += 1 49 for name_title in zip(name_list): 50 print (name_title, "\n+++++++++++++++++++++++++++++++++++++++++++++++++++") 51 l.click() 52 except: 53 pass

for文の使い方に問題があるのではないかと思っています。

ちなみに、順にクリックするという構文をなくし、

python

1import urllib.request 2import pandas as pd 3from bs4 import BeautifulSoup 4from selenium import webdriver 5from selenium.common.exceptions import NoSuchElementException 6import time 7driver = webdriver.Chrome ( executable_path=r'C:\Users\chromedriver.exe' ) 8driver.get ("https://hogehoge.com/個別ページ" ) 9 10html = driver.page_source 11bs = BeautifulSoup ( html, "html.parser" ) 12time.sleep ( 5 ) 13 14 15for page_title in bs.find_all('meta', attrs={'property': 'og:title'}): 16 print (page_title['content']) 17 for script_ele in bs.find_all ( "script" ): 18 text_list = str(script_ele).split("\"")# 引用符「"」で分割 19 image_url = [] 20 for img_url in text_list: 21 if img_url.startswith("http") and img_url.endswith("jpg"): 22 image_url.append(img_url) 23 blanks = ['' for _ in range(1,len(image_url))] 24 print (image_url) 25 26

では正しく要素が2つとも抽出出来ます。

###追記
記述しているコードで動作させると以下のように関数に値が格納されるのですが、
image_urlとpage_titleが出てきません。

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

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

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

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

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

meg_

2020/01/27 10:51

l.click()」の後、画面遷移が完了するまえに処理をしていませんか?
pasomtr

2020/01/27 11:09

meg_様 ありがとうございます! for i in range(1): try: name_list = [] path_front = '//*[@id="j-wishlist-container"]/div/div[1]/div[' count = 2 path_end = ']/div/div[1]' for _ in range(10): path = path_front + str(count) + path_end for l in driver.find_elements_by_xpath(path): l.click() time.sleep ( 5 ) try: driver.find_element_by_class_name('next-dialog-close').click() except: pass break break for page_title in bs.find_all('meta', attrs={'property': 'og:title'}): print (page_title['content']) for script_ele in bs.find_all ( "script" ): text_list = str(script_ele).split("\"")# 引用符「"」で分割 image_url = [] for img_url in text_list: if img_url.startswith("http") and img_url.endswith("jpg"): image_url.append(img_url) blanks = ['' for _ in range(1,len(image_url))] print (image_url) break break break break driver.back() count += 1 for name_title in zip(name_list): print (name_title, "\n+++++++++++++++++++++++++++++++++++++++++++++++++++") l.click() except: pass としてみましたが要素を取得出来ませんでした。
meg_

2020/01/27 12:11

エラーは出ていませんか? エラーを出力してみてください。
pasomtr

2020/01/28 01:34

エラーは出力されませんでした。追記として上部に画像を掲載しています。 image_urlとpage_titleの関数が処理されていないのか、表示されませんでした。
meg_

2020/01/28 02:04

エラーが出力されないのは「except」節でpassしているからです。ここでエラーを出力するようにしてみてください。おそらくは「NoSuchElementException」だとは思いますが、確認しないと何とも言えませんので。
guest

回答1

0

ベストアンサー

おおよそ以下のようなものだと思いますが、
DOMを見ない事にはこれ以上正確に回答するのが難しいです。

blanksは宣言だけしていてそのあとのプログラムで
どこにも表れていないので無意味です。
これは何のために使おうとしたリストなのでしょうか。

そもそも、「10個ある個別ページにそれぞれ遷移して、
そのページのタイトルとそのページにある全てのjpg画像のurlリストを
取得したい」ということで正しいですか?

python

1path_front = '//*[@id="j-wishlist-container"]/div/div[1]/div[' 2path_end = ']/div/div[1]' 3name_dict = {} 4 5for i in range(2, 13): 6 7 path = path_front + str(i) + path_end 8 driver.find_element_by_xpath(path).click() 9 10 try: 11 # 変なダイアログが出ていたら閉じる 12 driver.find_element_by_class_name('next-dialog-close').click() 13 except NoSuchElementException: 14 # なけりゃ無視でいい 15 pass 16 17 image_url_list = [] 18 19 for script_tag in bs.find_all("script"): 20 21 # 引用符「"」で分割 22 text_list = str(script_tag).split("\"") 23 24 for img_url in text_list: 25 26 if img_url.startswith("http") and img_url.endswith("jpg"): 27 28 image_url_list.append(img_url) 29 30 # ちなみにこの2重forループは1行でも書ける 31 # image_url_list = [img_url for script_tag in bs.find_all("script") for img_url in str(script_tag).split("\"") if img_url.startswith("http") and img_url.endswith("jpg")] 32 33 name_dict[i - 1] = {'title': driver.title, 'image_url_list': image_url_list} 34 35 driver.back() 36 37print(name_dict) 38# {1: {'title': '1ページ目のタイトル', 'image_url_list': ['http://www.hogehoge.com/media/1/1.jpg', 'http://www.hogehoge.com/media/1/2.jpg']}, 2: {'title': '2ページ目のタイトル', 'image_url_list': ['http://www.hogehoge.com/media/2/1.jpg', 'http://www.hogehoge.com/media/2/2.jpg', 'http://www.hogehoge.com/media/2/3.jpg']}, ...}

投稿2020/01/28 02:40

shirai

総合スコア1289

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

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

pasomtr

2020/01/28 04:04

ご回答ありがとうございます! そもそも、「10個ある個別ページにそれぞれ遷移して、 そのページのタイトルとそのページにある全てのjpg画像のurlリストを 取得したい」ということで正しいですか? ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー その通りでございます。 宣言だけしていてそのあとのプログラムで どこにも表れていないので無意味です。 ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー こちらは、その後pandasでcsv出力する際、行が他の要素と合わないと出力出来ない為、 Datef = pd.DataFrame({'Title':['A'] + blanks, という形で使用していました。 頂きました内容で検証したところ、タイトルの要素は取得できました! ありがとうございます! しかし、image_URLは取得できず、以下のように空となります。 {1: {'imgURL': []}, 2: {'imgURL': []}, 3: {'imgURL': []}, 4: {'imgURL': []}, 5: {'imgURL': []}, 6: {'imgURL': []}, 7: {'imgURL': []}, 8: {'imgURL': []}, 9: {'imgURL': []}, 10: {'imgURL': []}, 11: {'imgURL': []}} ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー for i in range(2, 13):を外し、個別ページに直アクセスさせて、 html = driver.page_source bs = BeautifulSoup ( html, "html.parser" ) time.sleep ( 5 ) try: # 変なダイアログが出ていたら閉じる driver.find_element_by_class_name('next-dialog-close').click() except NoSuchElementException: # なけりゃ無視でいい pass time.sleep ( 5 ) image_url_list = [img_url for script_tag in bs.find_all("script") for img_url in str(script_tag).split("\"") if img_url.startswith("http") and img_url.endswith("jpg")] print (image_url_list) とすると要素が取得できます。 取得元の個別ページのimage_urlの取得する要素は以下の様に記述されています。 <script> window.runParams = { data: {  "imageModule":{"features":{},"i18nMap":{},"id":0,"imagePathList":["https://hogehoge.com/hogehoge.jpg","https://hogehoge.com/hogehoge1.jpg","https://hogehoge.com/hogehoge2.jpg","https://hogehoge.com/hogehoge3.jpg","https://hogehoge.com/hogehoge4.jpg","https://hogehoge.com/hogehoge5.jpg"],"name":"ImageModule","summImagePathList":["https://hogehoge.com/hogehoge.jpg_50x50.jpg","https://hogehoge.com/hogehoge1.jpg_50x50.jpg","https://hogehoge.com/hogehoge2.jpg_50x50.jpg","https://hogehoge.com/hogehoge3.jpg_50x50.jpg","https://hogehoge4.com/hogehoge4.jpg_50x50.jpg","https://hogehoge.com/hogehoge5.jpg_50x50.jpg"]}, } </script> for i in range(2, 13):などforを使用した際に空になるようなのですが、 なぜなのか、原因を出力する方法がございますでしょうか?
pasomtr

2020/01/28 04:55

問題の糸口がみつかりました! img_url for script_tag in bs.find_all("script")で<script>の要素が取得出来ているか出力したところ、 個別ページでなく、一覧ページの<script>要素が取得されていました。 image_url_list = [img_url for script_tag in bs.find_all("script") for img_url in str(script_tag).split("\"") if img_url.startswith("http") and img_url.endswith("jpg")] print (image_url_list) の前にtime.sleep ( 15 )入れてみましたが、個別ページの要素を取得出来ません。 なぜなのか、理由はわかりますでしょうか?
shirai

2020/01/28 05:38

手動で一覧ぺージでクリックして個別ページに行くときはブラウザの別タブで開かれますか?
pasomtr

2020/01/28 06:05

同じタブで開かれていたので、 single_page = driver.page_source bs = BeautifulSoup (single_page, "html.parser" ) for page_title in bs.find_all('meta', attrs={'property': 'og:title'}): とすることで、遷移した個別ページのURLからソースを取得することが出来ました! 最後までお付き合い頂きまして誠にありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問