title: Pandas read_html() doesn't give my all entries in a table
body: <p>I'm building a web scraper that logs into an authenticated webpage, navigates to a table, and scrapes this table every minute. The table on the webpage updates automatically with new entries. Here's how the webpage looks like:</p>
  <p><a href="https://i.stack.imgur.com/6Xnrj.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/6Xnrj.png" alt="enter image description here" /></a></p>
  <p>I want to scrape the RANKING table on the page. Until now, I have done this by using:</p>
  <pre><code>df = pd.read_html(driver.page_source)[7] 
  </code></pre>
  <p>However, my experience with this is that I don't always get all the entries (rows) in the table. In such cases, I can use:</p>
  <pre><code>df = pd.read_html(driver.page_source)[8] 
  df = pd.read_html(driver.page_source)[9] 
  or even 
  df = pd.read_html(driver.page_source)[10] 
  </code></pre>
  <p>As a result, my scraping pipeline is prone to errors. Therefore, I'm asking if there is a better method to scrape this table, that is more robust? The outcome must be a Pandas DataFrame. The xpaths to the table are the following:</p>
  <pre><code>columns = len(driver.find_elements_by_xpath(&quot;/html/body/div[2]/div/form[3]/div[2]/div[1]/div/div/div/div[2]/div[4]/section[1]/div[2]/div/div/table/thead/tr[2]/th&quot;))
  rows = len(driver.find_elements_by_xpath(&quot;/html/body/div[2]/div/form[3]/div[2]/div[1]/div/div/div/div[2]/div[4]/section[1]/div[2]/div/div/table/tbody/tr&quot;))
  
  </code></pre>
  <p>Here's all my code</p>
  <pre><code>
  
  from selenium import webdriver
  from selenium.webdriver.common.by import By
  from selenium.webdriver.support.ui import WebDriverWait
  from selenium.webdriver.support import expected_conditions as EC
  import pandas as pd
  import time
  import schedule
  
  class Skraper:
      &quot;&quot;&quot;
      Klassen Skraper inneholder metoder som kjører skraperen
      &quot;&quot;&quot;
      @staticmethod 
      def oppstart():
          &quot;&quot;&quot;
          Returns:
          driver -- en Chrome webdriver med notifications av, og som navigerer til startsiden.
          &quot;&quot;&quot;
          driver = webdriver.Chrome()
          url = &quot;http://www.hctiming.com/myphp/resources/login/browse_results.php?live_action=yes&amp;smartphone_action=no&quot; #a redirect to a login page occurs
          driver.get(url)
          driver.find_element_by_id(&quot;open&quot;).click()
  
          user = driver.find_element_by_name(&quot;username&quot;)
          password = driver.find_element_by_name(&quot;password&quot;)
          user.clear()
          user.send_keys(&quot;sorry cannot give you this&quot;)
          password.clear()
          password.send_keys(&quot;sorry cannot give you this&quot;)
          driver.find_element_by_name(&quot;submit&quot;).click()
  
          try:
              element = WebDriverWait(driver, 10).until(
                  EC.presence_of_element_located((By.LINK_TEXT, &quot;Results Services&quot;))
              )
              element.click()
  
              element = WebDriverWait(driver, 10).until(
                  EC.presence_of_element_located((By.LINK_TEXT, &quot;View Live&quot;))
              )
              element.click()
  
          except:
              driver.quit()
          
          return driver
  
      @staticmethod
      def henteTabell():
  
          #Jeg har satt sleep til 2, slik at jeg er sikker på at tabellen er lastet inn med Ajax før jeg skraper denne.
          #Dette er nok ikke beste praksis, men den funker så langt. Et alternativ er å legge den i en eksplisitt wai
  
          driver.refresh()
          time.sleep(4)
          #Her bruker jeg pandas read_html() til å lokalisere tabellen på siden. Denne metoden lokaliserer tabeller på en side og lagrer disse som en liste.
          #Jeg fant ut at tabellen jeg ønsker å skrape ligger i listeindex nr 10
          #Jeg assigner denne som en pandas dataframe objekt.
          print(&quot;dette er en test&quot;)
         # df = pd.read_html(driver.page_source)[7]
         
  
  
          print(df)
          
          
          
          #Tabellen er ikke ryddet og klar til analyse enda, så noen trinn må gjøres.
          #Jeg må om COMMENT til string
          df[&quot;COMMENT&quot;] = df['COMMENT'].astype(str)
          #Jeg gjør noen replace(), slik at jeg får string verdien som jeg vil ha.
          df[&quot;COMMENT&quot;] = df['COMMENT'].str.replace('1', '1')
          df[&quot;COMMENT&quot;] = df['COMMENT'].str.replace('2', '2')
          df[&quot;COMMENT&quot;] = df['COMMENT'].str.replace('3', '3')
          df[&quot;COMMENT&quot;] = df['COMMENT'].str.replace('9', 'STRAIGHT-GLIDING')
          #Jeg renamer kolonnene slik jeg vil ha. D3.JS har problemer med '#', så jeg fjerner disse
          df = df.rename(columns={'COMMENT': 'COURSE'})
          df = df.rename(columns={'RUN#': 'RUN'})
          df = df.rename(columns={'STA#': 'STA'})
          df = df.rename(columns={'BIB#': 'BIB'})
          #Verdiene har i FINISH kolonnen har et veldig rart format fordi jeg skraper to kolonner. Jeg har funnet ut at denne anonyme labda funksjonen gjør nytten.
          #Den fjerner de fire siste stringene for alle verdiene i FINISH kolonnnen.
          #Jeg fant ut at jeg ikke trenger denne funksjonen (under)
          #df['FINISH']# = df['FINISH'].map(lambda x: str(x)[:-3])
          #Det neste jeg gjør er å endre dette fra et string objekt til et float objekt. Deklarerer dette til en ny variabel, siden dette er beste praksis.
          
  
          df['FINISH'] = pd.to_numeric(df['FINISH'], downcast='float', errors='raise')
          # print(df)
  
          # #Her velger jeg ut alle Straight-Gliding rundene
          filtrerStraightGliding = df['COURSE'] == 'STRAIGHT-GLIDING'
  
          velgStraightGliding = df.loc[filtrerStraightGliding].copy()
          # print(&quot;test 2&quot;)
          # print(velgStraightGliding)
  
          velgForsteStraightGlidingRunde = velgStraightGliding[velgStraightGliding.groupby(['BIB','COURSE']).cumcount() == 0][['BIB','FINISH']].copy()
          velgForsteStraightGlidingRunde = velgForsteStraightGlidingRunde.rename(columns={'FINISH':'REFERENCE'})
  
          ferdigstiltDF = pd.merge(df,velgForsteStraightGlidingRunde,on='BIB',how='left')
          ferdigstiltDF['RATIO'] = ferdigstiltDF['FINISH'] - ferdigstiltDF['REFERENCE']
          #Det jeg gjør nå er at jeg sorterer STA fra lav til høy. Dette er et superviktig trinn, hvis ikke vil skriptet mitt ikke fungere. Da vil den beste den dårlisgte rangerte utøveren.
          final_df = ferdigstiltDF.sort_values('STA', ascending=True)
          print(final_df)
  
          #print(final_df)
  
          final_df = final_df.iloc[[-1]]
          
          
  
  
          final_df.to_csv(&quot;lagplot.csv&quot;)
          #print(final_df)
          return ferdigstiltDF
  
  driver = Skraper.oppstart()
  
  schedule.every(5).seconds.do(Skraper.henteTabell)
  
  while True:
      schedule.run_pending()
      time.sleep(1)
  
  
  
  
  
  
  
  </code></pre>