91988


pythonやプログラミングの初心者です。  
色々なサイトを調べましたが、問題が解決されなかったため、こちらに投稿させていただいています。  
基本的な内容かもしれませんが、ご協力いただけますと幸いです。

### やりたいこと

Google Colaboratoryを使って下記のサイトに載っているリストをスクレイピングして  
csvとして出力して、データ解析をしたいです。

<http://regalkes.kemkes.go.id/info.php#home/produk/lstPkrt/02>

このサイトを見ると、リストが複数ページに跨っていることが分かります。  
そして、ページを遷移するリンクがJavaScriptになっているため、Seleniumを使用することにしました。

考えたフローは、以下の通りです。

### フロー

1.最初に上記のサイトにアクセスして、DataFrameとしてデータを取得する。  
2.[1](https://i.stack.imgur.com/535tM.jpg)で取得したデータをcsv出力する。  
3.次のページに遷移して、DataFrameとしてデータを取得する。  
4.[3]で取得したDataFrameをcsvデータとして出力して、[2]で出力したcsvデータの最終行に追加する。  
5.[3],[4]の作業をforループで繰り返して、サイトに掲載されているデータをすべて追加する。  
このフローに沿って、作成したプログラムが下記の通りです。

[code]

    !pip install selenium
    !pip install lxml
    !pip install html5lib
    !pip install beautifulsoup4
    !pip install webdriver-manager
    
    !apt-get update
    !apt install chromium-chromedriver
    !cp /usr/lib/chromium-browser/chromedriver /usr/bin
    
    from selenium import webdriver
    from selenium.webdriver.common.by import By
    from selenium.webdriver.chrome.options import Options
    from selenium.webdriver.support.ui import Select
    from selenium.webdriver.chrome.service import Service
    from webdriver_manager.chrome import ChromeDriverManager
    from google.colab import files
    from bs4 import BeautifulSoup
    import time 
    import requests
    import pandas as pd
    import io
    import csv
    
    # Chrome Driver Option
    options = webdriver.ChromeOptions()
    options.add_argument('--headless') # Headless Mode
    options.add_argument('--no-sandbox') # Sandbox off 
    options.add_argument('--disable-dev-shm-usage') # /dev/shmパーティションの使用を禁止
    
    # Web Driver Set
    driver = webdriver.Chrome('chromedriver',options=options)
    
    # URL
    URL = "http://regalkes.kemkes.go.id/info.php#home/produk/lstPkrt/02"
    driver.get(URL)
    
    
    #上記フローの[1],[2]
    from pandas.core.describe import DataFrameDescriber
    from selenium.webdriver.chrome import service
    from selenium.webdriver.common.by import By
    from selenium.webdriver.common.keys import Keys
    import numpy as np
    import pandas as pd
    import matplotlib.pyplot as plt
    
    url = 'http://regalkes.kemkes.go.id/info.php#home/produk/lstPkrt/02'
    df1 = pd.read_html(driver.page_source)
    df1
    df1[0].to_csv('/content/output.csv')
    
    
    #pagesにページ数を入力
    pages = 2
    
    for i in range(pages+1):
      #上記フローの[3]
      driver.find_element(By.LINK_TEXT, "›").click()
      time.sleep(1)
      df2 = pd.read_html(driver.page_source, header = 1)
      df2
      df2[0].to_csv('/content/output2.csv')
      df1 = pd.read_csv("output.csv")
      #上記フローの[4]
      df1.append(df2, ignore_index=True)
      df1
      df1.to_csv('/content/OUTPUT.csv', mode='a', header=True)
      break
    
[/code]

### 出力結果(11/4追記)

求めている出力結果と実際の出力データはは、添付した画像の通りです。  
データベース上のNo.を連番で追加していくように設定したいのですが、  
同一のページのデータ（[2]で出力したcsvデータ）が"pages ="で設定した数値の数だけ繰返し追加されるようになってしまいます。

[![画像の説明をここに入力](https://i.stack.imgur.com/535tM.jpg)](https://i.stack.imgur.com/535tM.jpg)

データの結合がうまくいっておりません。  
ページを遷移するプログラムや、遷移したページでcsvデータを出力するプログラムは動作しているようなのですが…

お力添えいただけますと幸いです。


CC BY-SA 4.0
2022-11-02T07:57:40.163
91946
2022-11-04T11:17:25.987
2022-11-04T05:04:51.860
3060
55145
question
python pandas selenium web-scraping
Seleniumで同じcsvが重複して追加されてしまうのはなぜ？


最初の問題点は、ページの遷移完了待ち時間が1秒では不足していると思われることでしょう。  
どのくらいの時間が適当なのかは対象サイトの性能？やスクリプトの動作環境に依存すると思われるので実験して決めてください。

それからサイトの情報をDataFrameに入れたり、CSVファイルに書いたりする時に余計な情報が付いたままだと思われるので、それらは削った方が良いでしょう。  
例えば変更箇所の該当部分は以下のようになるでしょう。

[code]

    df1 = pd.read_html(driver.page_source, header=1) #### ヘッダー行の指定を追加
    #### 以下は有効なデータである先頭10行のみファイル出力。かつインデックスは不要なのでは？
    df1[0].head(10).to_csv('/content/output.csv', index=False)
    
    #pagesにページ数を入力
    pages = 2
    
    for i in range(pages+1):
      #上記フローの[3]
      driver.find_element(By.LINK_TEXT, "›").click()
      time.sleep(5) #### ここが一番最初の問題点で十分な待ち時間が指定されていなかった。
      df2 = pd.read_html(driver.page_source, header=1)
      #### 最初と同じく先頭10行のみファイル出力。かつヘッダーとインデックスは不要なのでは？
      df2[0].head(10).to_csv('/content/output.csv', mode='a', index=False, header=False)
    
[/code]


CC BY-SA 4.0
2022-11-04T07:26:27.063
91988
2022-11-04T07:26:27.063
26370
91946
answer


私の環境では下記コードで取得出来ました。  
※ DataFrame.append()でWarningが出たためコードを変更しています。（pandas 1.4.3）

[code]

    from selenium import webdriver
    from selenium.webdriver.chrome.service import Service
    from selenium.webdriver.common.keys import Keys
    from selenium.webdriver.common.by import By
    
    import pandas as pd
    import time
    
    service = Service(executable_path="chromedriver.exe")
    driver = webdriver.Chrome(service=service)
    URL = "http://regalkes.kemkes.go.id/info.php#home/produk/lstPkrt/02"
    driver.get(URL)
    time.sleep(2)
    
    pages = 2
    dfs = []
    for i in range(pages+1):
        dfs.append(pd.read_html(driver.page_source, header=1)[0])
        driver.find_element(By.LINK_TEXT, "›").click()
        time.sleep(2)
    df = pd.concat(dfs, axis=0)
    
[/code]


CC BY-SA 4.0
2022-11-04T11:17:25.987
91995
2022-11-04T11:17:25.987
39819
91946
answer