【问题标题】:Wait page to load before getting data with requests.get in python 3在 python 3 中使用 requests.get 获取数据之前等待页面加载
【发布时间】:2018-01-08 23:31:17
【问题描述】:

我有一个页面,我需要获取与 BS4 一起使用的源,但页面中间需要 1 秒(可能更少)来加载内容,并且 requests.get 在该部分之前捕获页面的源加载,如何在获取数据之前等待一秒钟?

r = requests.get(URL + self.search, headers=USER_AGENT, timeout=5 )
    soup = BeautifulSoup(r.content, 'html.parser')
    a = soup.find_all('section', 'wrapper')

The page

<section class="wrapper" id="resultado_busca">

【问题讨论】:

标签: python-3.x web-scraping beautifulsoup python-requests


【解决方案1】:

看起来不是等待的问题,看起来元素是由 JavaScript 创建的,requests 无法处理 JavaScript 动态生成的元素。一个建议是使用 seleniumPhantomJS 来获取页面源,然后您可以使用BeautifulSoup 进行解析,如下所示的代码即可就是这样:

from bs4 import BeautifulSoup
from selenium import webdriver

url = "http://legendas.tv/busca/walking%20dead%20s03e02"
browser = webdriver.PhantomJS()
browser.get(url)
html = browser.page_source
soup = BeautifulSoup(html, 'lxml')
a = soup.find('section', 'wrapper')

此外,如果您只查找一个元素,则无需使用 .findAll

【讨论】:

  • 更新:Selenium 对 PhantomJS 的支持已被弃用,您应该改用无头版本的 Chrome 或 Firefox。
  • @SethConnell 那么如何解决这个问题呢?
  • @3kstc 试试this
【解决方案2】:

在 Python 3 中,在加载动态网页时,在实践中使用模块 urllib 比使用 requests 模块效果更好。

import urllib.request
try:
    with urllib.request.urlopen(url) as response:

        html = response.read().decode('utf-8')#use whatever encoding as per the webpage
except urllib.request.HTTPError as e:
    if e.code==404:
        print(f"{url} is not found")
    elif e.code==503:
        print(f'{url} base webservices are not available')
        ## can add authentication here 
    else:
        print('http error',e)

【讨论】:

  • 对我没有任何影响。我收到了 200 条带有骨架 html 结构的回复,但主 div 没有填充使用 Web 浏览器时的数据。
【解决方案3】:

我找到了办法!!!

r = requests.get('https://github.com', timeout=(3.05, 27))

在这里,timeout 有两个值,第一个是设置会话超时,第二个是你需要的。第二个决定在多少秒后发送响应。您可以计算填充数据所需的时间,然后将数据打印出来。

【讨论】:

【解决方案4】:

只是列出我的做法,也许它对某人有价值:

max_retries = # some int
retry_delay = # some int
n = 1
ready = 0
while n < max_retries:
  try:
     response = requests.get('https://github.com')
     if response.ok:
        ready = 1
        break
  except requests.exceptions.RequestException:
     print("Website not availabe...")
  n += 1
  time.sleep(retry_delay)

if ready != 1:
  print("Problem")
else:
  print("All good")

【讨论】:

    【解决方案5】:

    我遇到了同样的问题,提交的答案都没有真正适合我。 但经过长时间的研究,我找到了解决办法:

    from requests_html import HTMLSession
    s = HTMLSession()
    response = s.get(url)
    response.html.render()
    
    print(response)
    # prints out the content of the fully loaded page
    # response can be parsed with for example bs4
    

    requests_html 包 (docs) 是一个官方包,由 Python 软件基金会分发。它有一些额外的 JavaScript 功能,例如等待页面的 JS 完成加载的能力。

    希望我能帮助到别人!

    【讨论】:

    • 我们如何在其中添加等待时间。有什么办法吗?
    • @IbtsamCh 是的!有两种方法:在渲染中使用wait 参数以秒为单位添加等待时间在呈现javascript 之前,使用sleep 参数以秒为单位添加等待时间之后js 已渲染。两个参数都只接受整数值。示例:response.html.render(wait=2, sleep=3) 在 javascript 渲染之前等待 2 秒,之后等待 3 秒。
    【解决方案6】:

    Selenium 是解决该问题的好方法,但已被接受的答案已被弃用。正如@Seth 在 Firefox/Chrome(或可能的其他浏览器)的 cmets 无头模式中提到的那样,应该使用而不是 PhantomJS。

    首先你需要下载特定的驱动程序:
    Geckodriver for Firefox
    ChromeDriver for Chrome

    接下来,您可以将下载的驱动程序的路径添加到系统 PATH 变量中。但这不是必需的,您也可以在代码中指定可执行文件所在的位置。

    火狐:

    from bs4 import BeautifulSoup
    from selenium import webdriver
    
    options = webdriver.FirefoxOptions()
    options.add_argument('--headless')
    # executable_path param is not needed if you updated PATH
    browser = webdriver.Firefox(options=options, executable_path='YOUR_PATH/geckodriver.exe')
    browser.get("http://legendas.tv/busca/walking%20dead%20s03e02")
    html = browser.page_source
    soup = BeautifulSoup(html, features="html.parser")
    print(soup)
    browser.quit()
    

    Chrome 也是如此:

    from bs4 import BeautifulSoup
    from selenium import webdriver    
    
    options = webdriver.ChromeOptions()
    options.add_argument('--headless')
    # executable_path param is not needed if you updated PATH
    browser = webdriver.Chrome(options=options, executable_path='YOUR_PATH/chromedriver.exe')
    browser.get("http://legendas.tv/busca/walking%20dead%20s03e02")
    html = browser.page_source
    soup = BeautifulSoup(html, features="html.parser")
    print(soup)
    browser.quit()
    

    最好记住browser.quit() 以避免在代码执行后挂起进程。如果您担心您的代码在浏览器被处理之前可能会失败,您可以将其包装在 try...except 块中并将 browser.quit() 放入 finally 部分以确保它会被调用。

    此外,如果使用该方法仍未加载部分源代码,您可以要求 selenium 等待特定元素出现:

    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
    
    options = webdriver.FirefoxOptions()
    options.add_argument('--headless')
    browser = webdriver.Firefox(options=options, executable_path='YOUR_PATH/geckodriver.exe')
    
    try:
        browser.get("http://legendas.tv/busca/walking%20dead%20s03e02")
        timeout_in_seconds = 10
        WebDriverWait(browser, timeout_in_seconds).until(ec.presence_of_element_located((By.ID, 'resultado_busca')))
        html = browser.page_source
        soup = BeautifulSoup(html, features="html.parser")
        print(soup)
    except TimeoutException:
        print("I give up...")
    finally:
        browser.quit()
    

    如果您对 Firefox 或 Chrome 以外的其他驱动程序感兴趣,请查看docs

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多