【问题标题】:Selenium scraping JS loaded pagesSelenium 抓取 JS 加载的页面
【发布时间】:2019-12-25 02:25:42
【问题描述】:

我正在尝试从https://surviv.io/stats/player787 中抓取一些加载的 JS 数据,例如总击杀数。有人可以告诉我如何用 selenium 抓取 js 加载的数据。谢谢。

编辑:这里是一些代码

from selenium import webdriver
browser = webdriver.Firefox()
browser.get('https://surviv.io/stats/player787')
b = browser.find_element_by_tag_name('tr')

包含我想要的数据的'tr'没有被selenium抓取

【问题讨论】:

  • 到目前为止你尝试了什么?
  • @AndreiSuvorkov 我已经添加了代码
  • The 'tr' which contains the data that i want is not grabbed by selenium - 哪些数据? HTML中有多个标签
  • @AaravM4 : 有很多 tr 标签,你需要在帖子中提到哪些表数据。
  • 这是代码中的第一个'tr'。这是 tr:i.stack.imgur.com/8rY4b.png

标签: selenium beautifulsoup


【解决方案1】:

获取击杀数。诱导WebDriverWaitvisibility_of_all_elements_located

from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium import webdriver

browser = webdriver.Firefox()
browser.get('https://surviv.io/stats/player787')
allkills = WebDriverWait(browser,20).until(EC.visibility_of_all_elements_located((By.XPATH,"//div[@class='card-mode-stat-name' and text()='KILLS']/following-sibling::div[1]")))
for item in allkills:
    print(item.text)

【讨论】:

    【解决方案2】:

    找不到它的原因是页面没有完全呈现。您可以使用 selenium 添加等待,因此在指定元素首先呈现之前不会继续。

    另外,如果它在<table> 标签中,让pandas 为你解析(它在后台使用beautifulsoup 提取<table><th><tr><td> 标签,获得渲染的 html 源代码后,将它们作为数据框列表返回:

    from selenium import webdriver
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    from selenium.webdriver.common.by import By
    from selenium.common.exceptions import TimeoutException
    import pandas as pd
    
    browser = webdriver.Chrome('C:/chromedriver_win32/chromedriver.exe')
    browser.get('https://surviv.io/stats/player787')
    delay = 3 # seconds
    WebDriverWait(browser, delay).until(EC.presence_of_element_located((By.CLASS_NAME, 'player-stats-overview')))
    
    df = pd.read_html(browser.page_source)[0]
    
    print (df.loc[0,'Kills'])
    
    browser.close()
    

    输出:

    18884
    
    
    print (df)
       Wins  Kills  Games  K/G
    0   638  18884   8896  2.1
    

    【讨论】:

      【解决方案3】:

      您可以避免浏览器的开销,并简单地模仿页面发出的 POST 请求。

      import requests
      
      headers = {'content-type': 'application/json; charset=UTF-8'}
      data = {"slug":"player787","interval":"all","mapIdFilter":"-1"}
      r = requests.post('https://surviv.io/api/user_stats', headers=headers, json=data)
      data = r.json()
      desired_stats = ['wins', 'kills', 'games', 'kpg'] 
      for stat in desired_stats:
          print(stat, ': ' , data[stat])
      

      对于 OP:

      当您单击我的答案中 url 指示的相应 xhr 时,网络选项卡中的有效负载视图可见(您需要向下滚动才能查看有效负载信息)

      【讨论】:

      • 我不是很清楚,你能详细说明一下吗,@QHarr
      • 使用浏览器很慢。如果您运行上面的无浏览器代码,您将获得 json 格式的统计信息。这是相同的请求,简化后,页面在浏览器中运行 javascript 时发出。
      • 您特别想要哪些项目?
      • 你是如何理解如何得到这个的?
      • 我在开发工具 F12 的网络窗格中监控了来自浏览器的网络流量,并看到了页面发出的请求。
      【解决方案4】:

      从你加载的 JS 页面中抓取 6521915289262.1 等值必须为visibility_of_all_elements_located() 诱导 WebDriverWait 并且您可以使用以下任一Locator Strategies

      • 使用CSS_SELECTOR

        driver.get('https://surviv.io/stats/player787')
        print([my_elem.get_attribute("innerHTML") for my_elem in WebDriverWait(driver, 5).until(EC.visibility_of_all_elements_located((By.CSS_SELECTOR, "table.player-stats-overview td")))])
        
      • 使用XPATH

        driver.get('https://surviv.io/stats/player787')
        print([my_elem.get_attribute("innerHTML") for my_elem in WebDriverWait(driver, 5).until(EC.visibility_of_all_elements_located((By.XPATH, "//table[@class='player-stats-overview']//td")))])
        
      • 控制台输出:

        ['652', '19152', '8926', '2.1']
        
      • 注意:您必须添加以下导入:

        from selenium.webdriver.support.ui import WebDriverWait
        from selenium.webdriver.common.by import By
        from selenium.webdriver.support import expected_conditions as EC
        

      【讨论】:

        猜你喜欢
        相关资源
        最近更新 更多
        热门标签