90590


selenium・openpyxlを使って、[節ごとプレミアリーグの第一試合](https://soccer.yahoo.co.jp/ws/category/eng/schedule)の結果を抽出してエクセルへ書き込みたいです。

プレミアリーグの試合数の結果を使って勝ち点数の分析をしています。  
先ずは第一試合のみ分析したいので、節ごとの勝ち点が１点より大きい試合の勝ち点を次の行へ追加したいです。

実現したい内容  
❶読み込みエクセルから、節ごとを読み込み、  
[節ごとプレミアリーグの第一試合](https://soccer.yahoo.co.jp/ws/category/eng/schedule)へ検索します。

test_read.xlsx

[code]

    種別
    第1節
    第2節
    
[/code]

  
❷  
節ごとで第一試合のみ抽出して、下記のエクセルのように書き込みたいです。

・勝ち点数が1より大きい場合、次の行（スコア列）へ自動的に書き込みたいです。  
（次の行へ書き込みしたいのは勝ち点数を強調したいからです。）

・前の行の種別,日時の値をコピーして自動的に書き込みたいです。  
・アウェイチームも次の行へ書き込みたいです。  
・勝ち点数が1より小さい場合、特に何もせずtest_read.xlsxの次の行へ繰り返していきます。

test_write.xlsx  
※ヘッダー予め書き込んでおります。

[code]

    種別,日時,ホーム/アウェイ(チーム),スコア
    第1節,8/5（金） 28:00,クリスタル・パレス,0 - 2
    第1節,8/5（金） 28:00,アーセナル,2
    第2節,8/13（土）20:30,アストン・ヴィラ,2 - 1
    第2節,8/13（土）20:30,エヴァートン,2
    
[/code]

第n節が増えると下記の様に出力したいです。  
※第3節、第4節まだ行われていません。

[code]

    種別,日時,ホーム/アウェイ(チーム),スコア
    第1節,8/5（金） 28:00,クリスタル・パレス,0 - 2
    第1節,8/5（金） 28:00,アーセナル,2
    第2節,8/13（土）20:30,アストン・ヴィラ,2 - 1
    第2節,8/13（土）20:30,エヴァートン,2
    第3節,8/20（土）20:30,トッテナム,-
    第3節,8/20（土）20:30,ウルヴァーハンプトン,-
    第4節,8/27（土）20:30,サウサンプトン,-
    第4節,8/27（土）20:30,マンチェスター・Ｕ,-
    
[/code]

現在の結果

問題点  
勝ち点１点より大きい場合、IF分岐は問題なくされますが、  
コード一部の様に前の行の値をコピーする際に次のループで繰り返しする際に上書き保存され  
自動的に次の行へ書き込みされず、実現したい結果と上手くいかないです。

[code]

    種別,日時,ホーム/アウェイ(チーム),スコア
    第2節,"8/13（土）20:30",クリスタル・パレス,0 - 2
    第2節,"8/13（土）20:30",エヴァートン,2
    
    
[/code]

コード一部

[code]

     #勝ち点が１以上であれば、現在の行a2〜a3をコピ~
     if int(winning_points) > 1:
        
      #a2行をコピ次の行へ貼り付け
      ws2["a2"] = ws2["a3"].value
      
      #b2行をコピ次の行へ貼り付け
      ws2["b2"] = ws2["b3"].value
    
    
[/code]

IF分岐後、どのように指定すれば良いでしょうか。  
さらにFor文など必要でしょうか。

もし分かる方がいましたら、教えていただけると幸いです。  
お手数ですが、よろしくお願い致します。

全体のコード

[code]

    from multiprocessing.dummy import Condition
    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 webdriver_manager.chrome import ChromeDriverManager
    from selenium.webdriver.common.keys import Keys
    from selenium.common.exceptions import NoSuchElementException
    
    option = Options()
    
    #ログイン情報を維持するための設定　
    # 参考→https://rabbitfoot.xyz/selenium-chrome-profile
    PROFILE_PATH ="C:\\Users\\test\\AppData\\Local\\Google\\Chrome\\User Data\\" # 変更
    option.add_argument('--user-data-dir=' + PROFILE_PATH)
    option.add_argument('--profile-directory=Default')
    #Getting Default Adapter failed error message
    option.add_experimental_option('excludeSwitches', ['enable-logging'])
    
    # ブラウザを開く設定
    driver = webdriver.Chrome(executable_path=ChromeDriverManager().install() ,options=option)
    
    #soccer yahooURL（試合結果）
    URL= "https://soccer.yahoo.co.jp/ws/category/eng/schedule"
    
    # URLを開く。
    driver.get(URL)
    
    #待機時間
    time.sleep(3)
    
    #エクセル読み込み
    file_excel_r=r"C:\Users\test\Documents\Scrape\test_read.xlsx"
    #エクセル保存
    file_excel_w=r"C:\Users\test\Documents\Scrape\test_write.xlsx"
    
    #エクセルファイルを読み込み
    wb = openpyxl.load_workbook(file_excel_r)
    ws = wb["Sheet1"]
    
    #エクセルファイル書き込み
    wb2 = openpyxl.load_workbook(file_excel_w)
    ws2 = wb2["Sheet1"]
    
    #1行ずつ読み込み
    #2行目からループを行う
    for i in range(2,ws.max_row+1):
     
     options = Options()
     options.add_argument('--headless') 
     options.add_argument('--no-sandbox')
     options.add_argument('--disable-gpu')
         
     driver = webdriver.Chrome(executable_path=ChromeDriverManager().install())
    
     #種別
     kinds = ws['a'+str(i)].value
    
     #url指定
     url="https://soccer.yahoo.co.jp/ws/category/eng/schedule"
     
     #検索サイトを開く
     driver.get(url)
     
     # 3秒待機
     time.sleep(3)
     
     #種別検索
     driver.find_element_by_partial_link_text(kinds).click()
    
     # 2秒待機
     time.sleep(2)
    
     #タブ切り替え
     driver.switch_to.window(driver.window_handles[0])
    
     #種別
     kinds_input = driver.find_element_by_xpath('//*[@id="schedule"]/section/table/tbody/tr[1]/td[2]').text
    
     #種別エクセルへ入力
     ws2['a'+str(i)].value = kinds_input
    
     #日時
     date = driver.find_element_by_xpath('//*[@id="schedule"]/section/table/tbody/tr[1]/td[1]').text
    
     #日時エクセルへ入力
     ws2['b'+str(i)].value = date
    
     #ホームチームエクセルへ入力
     team = driver.find_element_by_xpath('//*[@id="schedule"]/section/table/tbody/tr[1]/td[3]/a[2]').text
     ws2['c'+str(i)].value = team
    
     #TOATAlスコアエクセルへ入力
     total_score = driver.find_element_by_xpath('//*[@id="schedule"]/section/table/tbody/tr[1]/td[4]/a/p[1]').text
     print(total_score) 
     ws2['d'+str(i)].value = total_score
    
     #勝ち点のスコアエクセルへ入力
     winning_points = driver.find_element_by_xpath('//*[@id="schedule"]/section/table/tbody/tr[1]/td[4]/a/p[1]/span').text
     print(winning_points)
    
     #勝ち点が1より大きい場合、現在の行a2〜a3をコピ~
     if int(winning_points) > 1:
        
      #a2行をコピ次の行へ貼り付け
      ws2["a2"] = ws2["a3"].value
      
      #b2行をコピ次の行へ貼り付け
      ws2["b2"] = ws2["b3"].value
    
      #次の行をアウェイチームエクセルへ入力
      away_team = driver.find_element_by_xpath('//*[@id="schedule"]/section/table/tbody/tr[1]/td[5]/a[2]').text
      ws2['c3'].value = away_team
    
      #次の行を勝ち点のスコアエクセルへ入力
      score = driver.find_element_by_xpath('//*[@id="schedule"]/section/table/tbody/tr[1]/td[4]/a/p[1]/span').text
      print(score)
      ws2['d3'].value = score
     
    #エクセル保存
     wb2.save(file_excel_w)
    
[/code]


CC BY-SA 4.0
2022-08-16T12:41:33.227
90585
2022-08-17T04:23:04.603
2022-08-17T04:23:04.603
3060
18859
question
python python3 selenium openpyxl
Pythonでプレミアリーグの第一試合の勝ち点数を分析したい


  * まず勝ち点が1より大きい場合の移動元・移動先・追加先のセル指定を特定座標の固定値で行っているのが間違いです。  
また勝ち点が1より大きい場合の最初の2つのコピー処理は方向が逆だったり、そもそもセルからコピーしなくても変数に情報があるのでそれを代入すれば良いだけです。

  * それからWebページから取ってきたデータを`test_write.xlsx`のセルに書き込む際に、位置指定に`for i in range(2,ws.max_row+1):`の`i`を使っていますが、これは`test_read.xlsx`の行を順番に読み込むためのカウンタであり、`test_write.xlsx`のセルに書き込む位置とは無関係です。左辺が`ws2['a'+str(i)].value = `とかになっているのは間違いです。  
`test_write.xlsx`のセルに書き込む位置は別の変数で管理しましょう。

  * ちなみに`for`ループの中で第n節毎にChromeドライバーオブジェクトを作成していますが、これは必要なことなのでしょうか？ 最初に作ったChromeドライバーを使い回すか、少なくとも`for`ループの直前で別途作って毎回それを利用する方が良いのでは？

  * あとインデントを1桁にするのは見分け難くて間違いが起こりやすそうなので、せめて質問記事に書くときだけでもインデント4桁にした方が良いと思われます。

  * そして`for`ループの中で毎回`wb2.save(file_excel_w)`していますが、ループを終了してから行えば1回で済みます。

上記指摘を反映して、あと`find_element_**`をselenium
4.3.0以後仕様に対応させた、エクセルファイル読み込み以後の処理を以下に示します。

[code]

    #エクセルファイルを読み込み
    wb = openpyxl.load_workbook(file_excel_r)
    ws = wb["Sheet1"]
    
    #エクセルファイル書き込み
    wb2 = openpyxl.load_workbook(file_excel_w)
    ws2 = wb2["Sheet1"]
    
    '''
    #### 試合データを読むためのChromeドライバを最初に作ったオブジェクトで使い回すか、
    #### 以下のように for ループの外で1回だけ作成して使い回す
    options = Options()
    options.add_argument('--headless') 
    options.add_argument('--no-sandbox')
    options.add_argument('--disable-gpu')
    
    driver = webdriver.Chrome(executable_path=ChromeDriverManager().install())
    #url指定
    url="https://soccer.yahoo.co.jp/ws/category/eng/schedule"  #### 1回だけ設定すれば良い処理はループの外へ(そもそも前と同じurlなので設定不要では?)
    '''
    
    ws2_data_row = 2 #### test_write.xlsx に書き込む最初の行を設定
    
    #1行ずつ読み込み
    #2行目からループを行う
    for i in range(2,ws.max_row+1):
    
        #種別
        kinds = ws['a'+str(i)].value
    
        #検索サイトを開く
        driver.get(URL)  #### 最初の設定を使い回すなら大文字の URL 、ループ直前設定の別の情報を使うなら小文字の url 
        # 3秒待機
        time.sleep(3)
    
        #種別検索
        driver.find_element('partial link text', kinds).click()
        # 2秒待機
        time.sleep(2)
    
        #タブ切り替え
        driver.switch_to.window(driver.window_handles[0])
    
        #種別
        kinds_input = driver.find_element('xpath', '//*[@id="schedule"]/section/table/tbody/tr[1]/td[2]').text
        #日時
        date = driver.find_element('xpath', '//*[@id="schedule"]/section/table/tbody/tr[1]/td[1]').text
        #ホームチームエクセルへ入力
        team = driver.find_element('xpath', '//*[@id="schedule"]/section/table/tbody/tr[1]/td[3]/a[2]').text
        #TOATAlスコアエクセルへ入力
        total_score = driver.find_element('xpath', '//*[@id="schedule"]/section/table/tbody/tr[1]/td[4]/a/p[1]').text
        #勝ち点のスコア取得(エクセルへ入力はしない)
        winning_points = driver.find_element('xpath', '//*[@id="schedule"]/section/table/tbody/tr[1]/td[4]/a/p[1]/span').text
    
        ws2.cell(row=ws2_data_row, column=1).value = kinds_input  #### 第n節の第一試合の主な情報を書き込み
        ws2.cell(row=ws2_data_row, column=2).value = date
        ws2.cell(row=ws2_data_row, column=3).value = team
        ws2.cell(row=ws2_data_row, column=4).value = total_score
    
        #勝ち点が1より大きい場合、アウェイチーム情報を追記する
        if int(winning_points) > 1:
    
            ws2_data_row += 1  #### アウェイチーム情報のために行を次へ進める
            ws2.cell(row=ws2_data_row, column=1).value = kinds_input  #### 第n節と日時は同じ値を代入
            ws2.cell(row=ws2_data_row, column=2).value = date
    
            #次の行をアウェイチームエクセルへ入力
            away_team = driver.find_element('xpath', '//*[@id="schedule"]/section/table/tbody/tr[1]/td[5]/a[2]').text
            #次の行を勝ち点のスコアエクセルへ入力
            score = driver.find_element('xpath', '//*[@id="schedule"]/section/table/tbody/tr[1]/td[4]/a/p[1]/span').text
    
            ws2.cell(row=ws2_data_row, column=3).value = away_team  #### アウェイチーム情報書き込み
            ws2.cell(row=ws2_data_row, column=4).value = score
    
        ws2_data_row += 1  #### 次の節の情報のために行を次へ進める
    
    #エクセル保存
    wb2.save(file_excel_w)
    
[/code]


CC BY-SA 4.0
2022-08-17T03:15:32.590
90590
2022-08-17T03:15:32.590
26370
90585
answer