Office365 (microsoft365)のmicrosoft listに添付されたexcelのリンクをクリックすると、 ファイルダウンロードにはならず、まずは、excel for webで起動されます。
selenium for pythonで excel for web からexcelファイルのダウンロードを 試みましたが、なぜか find_elements(By.CSS_SELECTOR)で elementを取得できない。
どうやら、excel for web の画面で用いられている iframe の影響らしい。
そこで、switch_to.frame() で iframe内へ切り替えることで解消。
python scriptとしては、おおよそ以下のような感じです。
#!python # -*- coding: utf-8 -*- from datetime import datetime from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.keys import Keys from selenium.webdriver.edge.options import Options from selenium.webdriver.edge.service import Service from selenium.webdriver.support.ui import Select import subprocess import sys import time CONF = { "browser": { "browser_driver" : ".\\msedgedriver.exe", "implicitly_wait": 10, "browser_options": [ #"headless", ], "prefs": { #ファイルのダウンロード先 "download.default_directory":"c:\\Users\\xcend0tknr\\tmp" } }, "xmile_sso":{ "url" :"https://portaltop.xmile.sexy.co.jp/", "user_id" :"ないしょ@id.sexy-g.com", "user_pw" :"ないしょ", "proxy_pac":"http://portal.xmile.sexy.co.jp/proxy.pac" }, "o365":{ "qa_list_url": "https://sexyglobal-my.sharepoint.com/personal/ないしょ_id_sexy-g_com/Lists/A/AllItems.aspx" } } def main(): set_proxy_pac("off") browser = init_browser() login_to_xmile(browser) time.sleep(5) # microsoft listsにある問合せ一覧へ browser.get( CONF["o365"]["qa_list_url"] ) time.sleep(10) # 各問合せへのurlを取得 a_href_elms = browser.find_elements(By.CSS_SELECTOR, "div.field-_x8cea__x554f__x5185__x5bb9_ a") qa_urls = [] for a_href_elm in a_href_elms: qa_urls.append( a_href_elm.get_attribute("href") ) # 各問合せにある添付fileへののurlを取得 for qa_url in qa_urls: browser.get( qa_url ) time.sleep(5) attach_elms = browser.find_elements( By.CSS_SELECTOR, "div.ReactFieldEditor-Attachments-Renderer a") attach_urls = [] for attach_elm in attach_elms: attach_url = attach_elm.get_attribute("href") attach_urls.append(attach_url) for attach_url in attach_urls: browser.get( attach_url ) time.sleep(5) # excel for webは iframeで構成される為、そのiframeへ切替え browser.switch_to.frame(0) time.sleep(5) # excel for web画面の「ファイル」タブclick btn_elms =browser.find_elements(By.CSS_SELECTOR,"span#id__3") btn_elms[0].click() time.sleep(5) #browser.switch_to.default_content() # 「名前を付けて保存」click btn_elms =browser.find_elements(By.CSS_SELECTOR,"#FileSaveAsPage") btn_elms[0].click() time.sleep(5) # 「ダウンロード」click btn_elms =browser.find_elements(By.CSS_SELECTOR,"#DownloadACopy") btn_elms[0].click() time.sleep(5) break def login_to_xmile(browser): browser.get( CONF["xmile_sso"]["url"] ) button_elms = browser.find_elements(By.CSS_SELECTOR,"button.aad_login_button") button_elms[0].click() time.sleep( 2 ) input_elms = browser.find_elements(By.CSS_SELECTOR,"input[name='loginfmt']") input_elms[0].send_keys( CONF["xmile_sso"]["user_id"] ) time.sleep( 2 ) input_elms[0].send_keys(Keys.ENTER) time.sleep( 2 ) input_elms = browser.find_elements(By.CSS_SELECTOR,"input[name='passwd']") input_elms[0].send_keys( CONF["xmile_sso"]["user_pw"] ) time.sleep( 2 ) input_elms[0].send_keys(Keys.ENTER) time.sleep( 10 ) return browser def init_browser(): browser = None try: browser_service = Service( executable_path=CONF["browser"]["browser_driver"] ) browser_opts = Options() for tmp_opt in CONF["browser"]["browser_options"]: browser_opts.add_argument( tmp_opt ) browser_opts.experimental_options["prefs"]=CONF["browser"]["prefs"] browser = webdriver.Edge(service = browser_service, options = browser_opts ) # 要素が見つかるまで、最大 ?秒 待つ browser.implicitly_wait( CONF["browser"]["implicitly_wait"] ) except Exception as e: print(e) return browser # cf. https://qiita.com/fetaro/items/a3b3bd4ea197b600ac45 def set_proxy_pac(on_off): reg_key = \ '"HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"' if on_off == "off": off_cmd_cols = [ 'reg delete', reg_key, '/v "AutoConfigURL"', '/f'] off_cmd_str = " ".join( off_cmd_cols ) return exec_subprocess( off_cmd_str ) if on_off == "on": on_cmd_cols = [ 'reg add', reg_key, '/v "AutoConfigURL"', '/t REG_SZ', '/d "%s"' % ( CONF["xmile_sso"]["proxy_pac"] ), '/f'] on_cmd_str = " ".join( on_cmd_cols ) return exec_subprocess( on_cmd_str ) def exec_subprocess(cmd:str, raise_error=True): child = subprocess.Popen( cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) stdout, stderr = child.communicate() rt = child.returncode if rt != 0 and raise_error: print("ERROR",stderr,file=sys.stderr) return (None,None,None) return stdout, stderr, rt if __name__ == '__main__': main()