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

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

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

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

Q&A

解決済

1回答

567閲覧

Google Scholarで検索し、基本情報を取得したい

退会済みユーザー

退会済みユーザー

総合スコア0

Python

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

0グッド

0クリップ

投稿2022/09/08 01:45

前提

Google Scholarで検索キーワードを設定して、その結果の基本情報を取得したいと考えています。サイトにあったコードを参考に自分で少し手直ししたのですが、うまくいきません。

実現したいこと

pdfのリンク先も一緒に入手したいのですが、今のものだと、すべて一番上にあるものが表示されてしまいます。また、csvに書き出した場合文字化けが起こってしまうのでそれを解消したいです。encodingを設定したのですが、ない場合と'utf-8'では文字化けあり、'shift_jis'と'cp932'は2つ目のキーワードに設定しているものがエラーが出て表示されませんでした。

発生している問題・エラーメッセージ

pdfのリンクがすべて同じになってしまう。encodingのエラーは下記の通りです。

UnicodeEncodeError: 'cp932' codec can't encode character '\xe9' in position 180: illegal multibyte sequence UnicodeEncodeError: 'shift_jis' codec can't encode character '\xe9' in position 180: illegal multibyte sequence

該当のソースコード

python

1import pandas as pd 2import time 3import datetime 4import random 5import csv 6 7# 検索したいキーワード 8query_list = ["construction", "3d printer"] 9 10# 検索結果を格納するためのデータフレームの作成、検索クエリ・タイトル・リンク・取得日からなる 11search_result_df = pd.DataFrame( columns=["keyword", "title", "link", "author&year", "pdf","timestamp"]) 12 13 14# 検索したいキーワードの数だけ処理を繰り返す 15for each_query in query_list: 16 from selenium import webdriver # Google検索をブラウザを通じて自動的に行う際に使う 17 from selenium.webdriver.common.keys import Keys # ブラウザ操作のための諸々設定 18 from selenium.common.exceptions import NoSuchElementException,TimeoutException # ブラウザ操作のための諸々設定 19 from selenium.webdriver.common.desired_capabilities import DesiredCapabilities # ブラウザ操作のための諸々設定 20 from selenium.webdriver.chrome.options import Options # ブラウザ操作のための諸々設定 21 from selenium.webdriver.common.by import By #AttributeError: 'WebDriver' object has no attribute 'find_element_by_name'の回避 22 # https://qiita.com/jinyahiga/items/46f9a925f4a21bbef794 回避方法 23 24 # ブラウザ操作のための諸々設定 25https://boardtechlog.com/2020/08/programming/seleniumchrome%E3%81%A7%E3%82%88%E3%81%8F%E4%BD%BF%E3%81%86chromeoptions%E3%81%BE%E3%81%A8%E3%82%81/ 26 options = webdriver.ChromeOptions() 27 options.add_argument('--headless') 28 options.add_argument('--no-sandbox') 29 options.add_argument('--disable-dev-shm-usage') 30 31 driver = webdriver.Chrome(executable_path="./chromedriver.exe",options=options) # GoogleChromeのブラウザを開く 32 driver.implicitly_wait(10) # 画面が表示されるまで10秒待つように命令 33 34 # Googleの検索画面を表示(仮想のブラウザ) 35 driver.get('https://scholar.google.com/') 36 37 # 検索語を入力して送信する。 38 input_element = driver.find_element_by_name('q') 39 input_element.send_keys(each_query) 40 # エンターキーを押す 41 input_element.send_keys(Keys.RETURN) 42 43 # 検索結果を表示する。10件まで取得 44 for i in driver.find_elements_by_class_name('gs_ri'): 45 # 取得日時を残す用のデータ 46 time_stamp = str(datetime.datetime.now()) 47 each_h3 = i.find_element_by_tag_name('h3').text 48 each_href = i.find_element_by_tag_name('a').get_attribute('href') 49 each_author = i.find_element_by_class_name('gs_a').text #著者名と年代のところ 50 51 for j in driver.find_elements_by_class_name('gs_or_ggsm'): 52 each_pdf_href = j.find_element_by_tag_name('a').get_attribute('href') # pdfの部分を表示させたい 53 54 # 取得結果の格納用のデータフレーム作成 55 df = pd.DataFrame([[each_query, 56 str(each_h3), 57 str(each_href), 58 str(each_author), 59 str(each_pdf_href), 60 time_stamp]], 61 columns=search_result_df.columns) 62 print(each_h3) 63 print(each_author) 64 print(each_href) 65 print(each_pdf_href) 66 search_result_df = search_result_df.append(df).reset_index(drop=True) 67 68 69 # 仮想のブラウザを閉じる 70 driver.quit() 71 72 print(each_query) 73 74 75 # ランダムに40~60秒間処理を止める 76 t = random.randint(40, 60) 77 time.sleep(t) #sleep(秒指定) 78 79 # 保存 80 search_result_df.to_pickle("search_result_df_gs.pickle") 81 search_result_df.to_csv("search_result_df_gs_2.csv", encoding = 'shift_jis')

試したこと

初めはpdfのclassやtagの入れ方を変えたりしてみたのですが、classが違うaタブなので
for i in driver.find_elements_by_class_name('gs_ri'):で設定している('gs_ri')を変えて別に設定しました。
for文のインデントを変えると、上のものがすべて同じになり、pdfはバラバラのものになりました。

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

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

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

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

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

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

guest

回答1

0

ベストアンサー

PDFが全て同じURLになる部分に関しては、for文でPDFのURLのリストを回していますが変数each_pdf_hrefに上書きする形で代入しているため、結局のところfor文を抜ける直前(つまり最後)のPDFのURLがeach_pdf_hrefに常に代入されています。
ここで言っているPDFのURLのリストというのは、ある一つの論文に関してではなく、Google Scholarのページ全体についてのものです。
これを、各論文について要素を見つけるように変更し、存在しない場合は空文字としています。

文字化けについては解消できませんでした。
代わりに、英語版ページだと「書籍」は「BOOK」だったためそのように置き換えることで文字化けを回避しています。

その他、Autopep8に従うように色々書き換えたりしました。

Python

1import datetime 2import pandas as pd 3from selenium import webdriver 4from selenium.webdriver.common.keys import Keys 5from selenium.webdriver.common.by import By 6from selenium.webdriver.support.ui import WebDriverWait 7from selenium.webdriver.support import expected_conditions as EC 8 9 10PATH_CHROMEDRIVER = './chromedriver.exe' 11PATH_TO_SAVE = 'search_result.csv' 12# 検索したいキーワード 13QUERY_LIST = ['construction', '3d printer'] 14 15 16def main(): 17 # 検索結果を格納するためのデータフレームの作成、検索クエリ・タイトル・リンク・取得日からなる 18 search_result_df = pd.DataFrame( 19 columns=['keyword', 'title', 'link', 'author&year', 'pdf', 'timestamp']) 20 21 # ブラウザ操作のための諸々設定 22 options = webdriver.ChromeOptions() 23 options.add_argument('--headless') 24 options.add_argument('--no-sandbox') 25 options.add_argument('--disable-dev-shm-usage') 26 # GoogleChromeのブラウザを開く 27 driver = webdriver.Chrome(executable_path=PATH_CHROMEDRIVER, 28 options=options) 29 30 # 検索したいキーワードの数だけ処理を繰り返す 31 for each_query in QUERY_LIST: 32 print(f'QUERY: {each_query}', end='\n\n') 33 34 # Googleの検索画面を表示(仮想のブラウザ) 35 driver.get('https://scholar.google.com/') 36 37 # 検索語を入力して送信する。 38 input_element = driver.find_element_by_name('q') 39 input_element.send_keys(each_query) 40 # エンターキーを押す 41 input_element.send_keys(Keys.RETURN) 42 WebDriverWait(driver, 60).until( 43 EC.presence_of_element_located((By.CSS_SELECTOR, 44 'div.gs_r.gs_or.gs_scl'))) 45 46 # 検索結果を表示する。10件まで取得 47 for idx, i in enumerate(driver.find_elements_by_css_selector( 48 'div.gs_r.gs_or.gs_scl')): 49 # 取得日時を残す用のデータ 50 time_stamp = str(datetime.datetime.now()) 51 each_h3 = \ 52 i.find_element_by_tag_name('h3').text.replace('書籍', 'BOOK') 53 each_href = i.find_element_by_tag_name('a').get_attribute('href') 54 # 著者名と年代のところ 55 each_author = i.find_element_by_class_name('gs_a').text 56 57 elem = i.find_elements_by_css_selector('div.gs_ggs.gs_fl a') 58 each_pdf_href = elem[0].get_attribute('href') if elem else '' 59 60 # 取得結果の格納用のデータフレーム作成 61 df = pd.DataFrame([[each_query, 62 str(each_h3), 63 str(each_href), 64 str(each_author), 65 str(each_pdf_href), 66 time_stamp]], 67 columns=search_result_df.columns) 68 print('-' * 10 + str(idx) + '-' * 10) 69 print(each_h3) 70 print(each_author) 71 print(each_href) 72 print(each_pdf_href, end='\n\n') 73 search_result_df = \ 74 pd.concat([search_result_df, df]).reset_index(drop=True) 75 76 # 保存 77 search_result_df.to_csv(PATH_TO_SAVE) 78 79 # 仮想のブラウザを閉じる 80 driver.quit() 81 82 83if __name__ == '__main__': 84 main() 85

投稿2022/09/21 03:25

aiueo12345

総合スコア41

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

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

退会済みユーザー

退会済みユーザー

2022/09/21 04:26

ご回答いただきありがとうございました。 置き換え、全く気がつきませんでした。 結果もラインと数字を入れてくださり、とても見やすくなりました! リンク先の設定部分ですが、自分のところでやってみたらリンク先が2つあるものが同じリンク先が表示されてしまうのですが・・・。 何か設定の違いがあるのでしょうか。
aiueo12345

2022/09/21 04:41

リンク先が2つというのは、googlescholar上の論文タイトル部分のリンクとPDFへのリンクの2つということでしょうか。 もしそうであれば、その動作は恐らく問題なく、googlescholar上のPDFリンク部分に設定されているURLがタイトル部分のリンクのURLと同一のものになっているのだと思います。 これはgooglescholar上でそれぞれ踏んでみれば確認できるかと思います。
退会済みユーザー

退会済みユーザー

2022/09/22 04:33

しつこくて申し訳ありません。 おっしゃる通り、googlescholar上の論文タイトル部分のリンクとPDFへのリンクの部分です。 同じところもあるのですが、違う論文もあるのですが、その区分けはできなそうですか?現状2つ出てくるものはすべて同じで出力されているかと思います。 ----------4---------- [BOOK] Research methods for construction RF Fellows, AMM Liu - 2021 - books.google.com http://tailieudientu.lrc.tnu.edu.vn/Upload/Collection/brief/brief_53537_57907_20161006171250_CN201603208.pdf http://tailieudientu.lrc.tnu.edu.vn/Upload/Collection/brief/brief_53537_57907_20161006171250_CN201603208.pdf ⇒pdfの方は上記のリンク先なのですが、論文名の方は https://books.google.com/books?hl=ja&lr=lang_ja|lang_en&id=b61JEAAAQBAJ&oi=fnd&pg=PR9&dq=construction&ots=S36bKzrYIs&sig=fJMRJnt5dlDrV-8X1WthdNTHwNQ だったりするのですが。(エラーで載せたコードだとこちらが出てきます)
aiueo12345

2022/09/22 05:21

確かに二つともPDF側を取ってくるコードになっていました。 この原因は、 ``` each_href = i.find_element_by_tag_name('a').get_attribute('href') ``` の部分であり、これは最初に引っかかった要素を取り出してくるもので、HTMLでPDFの方が先に書かれているために、そちらが取得されていました。 そのため、該当部分を ``` each_href = i.find_element_by_css_selector('div.gs_ri a').get_attribute('href') ``` のように条件を加えてPDF側が引っかからないようにしてあげることで想定する動作をしてくれると思います。 また何かあったら教えてください。
退会済みユーザー

退会済みユーザー

2022/10/14 02:18

すみません、せっかくご回答いただいていたのに確認できていませんでした。 ご指摘の箇所を変更したら、希望通りのものが出力できました! 本当にどうもありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問