Python3とSelenium, openpyxlを使ってExcelのデータを読み込みYahoo! 乗換案内の検索をしています。
各駅を検索したらExcelのD列に処理済みの結果を記載しています。
WEB上で検索できない場合、
エラーが表示されたらループを抜けて、次のループに(日暮里)進み
下記のようにフラグに処理済みのデータを記載したいです。
エラーした場合処理済みのフラグを記載しないようにしたいです。
Excelデータ(実現内容)
No | 駅 | 駅2 | フラグ |
---|---|---|---|
1 | 東京 | 品川 | 処理済み |
2 | 原宿 | 原宿 | |
3 | 日暮里 | 秋葉原 | 処理済み |
4 | 東京 | 原宿 | 処理済み |
5 | 池袋 | @@@ |
tryでWEB側でエラーを検知して下記のコードに入れてみましたが、 実現したい処理と上手く処理できず、 全てのデータに処理済みと記載されます。 ifには検索後にタイトルを取得すれば処理済みのフラグを記載するように組みました。 eleseのようにエラーしたら処理済みを記載しないようにプログラムを記載 しましたが何故か全てのデータに処理済みと記載されます。 ご指導をお願いできますでしょうか。 try:#タイトルを取得 message = driver.find_element_by_xpath('//*[@id="cat-pass"]').text print(message) #Print結果:路線情報トップ > ルート、運賃検索結果 except: print("error") if "路線情報トップ > ルート、運賃検索結果"== message: # 処理済みのでデータをD列へ入力 df.loc[i,'フラグ']='処理済み' print("処理済み・書込み") #EXCEL保存 df.to_excel("test.xlsx", header=False, index=False) else: print("エクセルへフラグ記載しない") Excelデータ(現在の結果) |No | 駅 | 駅2 |フラグ| |-----:|:---------|:---------------|---------------| |1 | 東京 |品川|処理済み| |2 | 原宿 | 原宿 |処理済み| |3 | 日暮里 | 秋葉原|処理済み| |4 | 東京 | 原宿|処理済み| |5 | 池袋 | @@@ |処理済み
# Excel用ライブラリ読込 import openpyxl from selenium.webdriver.common.keys import Keys import time from selenium.webdriver.chrome.options import Options from selenium.webdriver.support.select import Select from selenium import webdriver from selenium.common.exceptions import NoSuchElementException import pyautogui import pandas as pd # Excelファイルを開く v_wb = openpyxl.load_workbook("test.xlsx") # アクティブなシートを変数へ v_ws = v_wb.active # シートのロード ws = v_wb.worksheets[0] # convert to pandas dataframe df = pd.DataFrame(ws.values) print("test") print(df) # generate search words # sort=False データソートせずにエクセル順番で行う lst = df.iloc[0:,1:].values print(lst) df['フラグ'] = '' URL = "https://transit.yahoo.co.jp/" # ブラウザを開く。 #options=option background options = Options() options.add_experimental_option('detach', True) driver = webdriver.Chrome(executable_path="C:\Program Files\chromedriver_win32\chromedriver.exe", options=options) #ループ処理の部分とエクセルへの書き込み処理(行)が合っていないので、 #row = 1を追加 for i, query in enumerate(lst): # Googleの検索TOP画面を開く。 if i > 0: driver.execute_script('window.open()') driver.switch_to.window(driver.window_handles[i]) driver.get(URL) # 2秒待機 time.sleep(2) # from fromid = driver.find_element_by_name("from") fromid.send_keys(query[0]) # to to = driver.find_element_by_name("to") to.send_keys(query[1]) #search time.sleep(2) pyautogui.press(['enter']) try:#タイトルを取得 message = driver.find_element_by_xpath('//*[@id="cat-pass"]').text print(message) #Print結果:路線情報トップ > ルート、運賃検索結果 except: print("error") if "路線情報トップ > ルート、運賃検索結果"== message: # 処理済みのでデータをD列へ入力 df.loc[i,'フラグ']='処理済み' print("処理済み・書込み") #EXCEL保存 df.to_excel("test.xlsx", header=False, index=False) else: print("エクセルへフラグ記載しない")
> ただ同じ駅だったら乗換案内で下記のエラーメッセージが表示されます。
同じ駅ならスクレイピングの処理自体をスキップした方が良いのではないでしょうか?
回答ありがとうございます。スキップできますがただまた駅以外に5行目のように池袋と@@
検索すると別のエラーが表示されます。 WEB側でエラーしたら例外で処理し,正常のみ処理済みと記載したいです。可能でしょうか。
処理はtryの中に全て書けば良いのでは?
回答ありがとうございます。早速やってみたところですが、上記のように
エラーした箇所に処理済みのフラグが記載されます。逆に正常に終了したものに記載したいですが、可能でしょうか。ご確認をお願い致します。
> df.loc[(df[1] == query[0]), 'フラグ'] = "処理済み"
上記がtryの中にないからではないですか?
回答ありがとうございます。
tryの中に入れましたら処理済みのフラグが記載されないです。ご確認をお願い致します。
質問のコードですと、for,try,except,elseが同じインデントに見えますが実際のコードも同じですか?
また、「> df.loc[(df[1] == query[0]), 'フラグ'] = "処理済み"」のdf[1] == query[0]は意図した条件ですか?
早速返事ありがとうございます。
質問のコードですと、for,try,except,elseが同じインデントに見えますが実際のコードも同じですか?
>はい、同じです。
df.loc[(df[1] == query[0]), 'フラグ'] = "処理済み"」のdf[1] == query[0]は意図した条件ですか?
>処理済みのデータをD列に入力したので、上記の条件を作成しました。
確認です。
「df.loc[(df[1] == query[0]), 'フラグ'] = "処理済み"」をtryの中に入れる前は、"2 原宿 原宿"と"5 池袋 @@@"の処理済み列に "処理済み"が入力されたのですね?(最後の画像を参照)
回答ありがとうございます。ただ下記の方法で行うと同じ駅と'@@@'でエラーした場合
回避できると思いますが、WEB側上で別のエラーが表示されても対応できるようにしたいです。例;NoSuchElementExceptionが見つからない時とかであればどのエラーでも回避できると思います。
分かりにくい質問で申し訳ありませんでした。質問内容を修正いたしました。selenium.common.exceptions.NoSuchElementException: Message: no such element: のエラーが表示されたらエラー処理を検知しエクセルのデータを追加したいです。
度々、すいません。
午前中で回答してもらった方法で上手くいけそうですが、
下記のように行いましたが、 print('エラー')4回表示されます。
希望通りの操作にするにはどのようにすればよろしいでしょうか。
ご確認をお願い致します。
for i, query in enumerate(lst):
# Googleの検索TOP画面を開く。
if i > 0:
driver.execute_script('window.open()')
driver.switch_to.window(driver.window_handles[i])
driver.get(URL)
# 2秒待機
time.sleep(2)
# from
fromid = driver.find_element_by_name("from")
fromid.send_keys(query[0])
# to
to = driver.find_element_by_name("to")
to.send_keys(query[1])
#search
time.sleep(2)
pyautogui.press(['enter'])
for i, query in enumerate(lst):
try:
cheap = driver.find_element_by_xpath('//*[@id="tabflt"]/li[3]/a').text
# print(cheap)
if df.iloc[i,0]!=df.iloc[i,1] :
# print(cheap)
df.loc[i,'フラグ']='処理済み'
else:
raise ValueError
except:
print('エラー')
df.to_excel("test.xlsx", header=False, index=False)
for i, query in enumerate(lst):
# Googleの検索TOP画面を開く。
if i > 0:
driver.execute_script('window.open()')
driver.switch_to.window(driver.window_handles[i])
driver.get(URL)
# 2秒待機
time.sleep(2)
# from
fromid = driver.find_element_by_name("from")
fromid.send_keys(query[0])
# to
to = driver.find_element_by_name("to")
to.send_keys(query[1])
#search
time.sleep(2)
pyautogui.press(['enter'])
for i, query in enumerate(lst):
try:
cheap = driver.find_element_by_xpath('//*[@id="tabflt"]/li[3]/a').text
# print(cheap)
if df.iloc[i,0]!=df.iloc[i,1] :
# print(cheap)
df.loc[i,'フラグ']='処理済み'
else:
raise ValueError
except:
print('エラー')
df.to_excel("test.xlsx", header=False, index=False)
raise ValueErrorの部分はテストコードのために書いたものなので、実際のコードには不要です。
回答ありがとうございます。下記のようにraise ValueErrorの部分はテストコードを消しましたが、
同じく希望通りの操作にならないです。
またデータ何も保存できないです。
もし可能であればもう少し詳しく教えていただけますか。
お手数ですが、よろしくお願い致します。
for i, query in enumerate(lst):
# Googleの検索TOP画面を開く。
if i > 0:
driver.execute_script('window.open()')
driver.switch_to.window(driver.window_handles[i])
driver.get(URL)
# 2秒待機
time.sleep(2)
# from
fromid = driver.find_element_by_name("from")
fromid.send_keys(query[0])
# to
to = driver.find_element_by_name("to")
to.send_keys(query[1])
#search
time.sleep(2)
pyautogui.press(['enter'])
for i, query in enumerate(lst):
try:
cheap = driver.find_element_by_xpath('//*[@id="tabflt"]/li[3]/a').text
# print(cheap)
if df.iloc[i,0]!=df.iloc[i,1] :
# print(cheap)
df.loc[i,'フラグ']='処理済み'
except:
print('エラー')
df.to_excel("test.xlsx", header=False, index=False)
if "路線情報トップ > ルート、運賃検索結果"== message:
をelse:に変えて、else:
print("エクセルへフラグ記載しない")は削除します。
また、df.to_excel("test.xlsx", header=False, index=False) はforループを抜けた後に一回だけ実行すれば良いと思います。
※エラーが発生した際もmessageは前回の値を持ってませんか?
ありがとうございます。上記の方法できました。
因みにIF必要ないのは、exceptが手前にあるからでしょうか。
エラー発生したらelse:は実行されないです。
それから「if "路線情報トップ > ルート、運賃検索結果"== message:」では条件分岐できていないので「全てのデータに処理済みと記載されます。」となったのでは?(message = driver.find_element_by_xpath('//*[@id="cat-pass"]').textの前にmessage=''とか書けば前のコードでも動作したかもしれませんが、シンプルなコードの方が良いかとは思います)
説明ありがとうございます。現在問題なく利用できます。
回答1件
あなたの回答
tips
プレビュー