【问题标题】:Wait before returning contents of web-page等待返回网页内容
【发布时间】:2018-03-30 10:09:34
【问题描述】:

我正在尝试抓取这个网站:http://www.fivb.org/EN/BeachVolleyball/PlayersRanking_W.asp,但是在页面加载之后,这个页面会加载表格的内容(可能通过 AJAX)。

我的尝试:

import requests
from bs4 import BeautifulSoup, Comment
uri = 'http://www.fivb.org/EN/BeachVolleyball/PlayersRanking_W.asp'

r = requests.get(uri)
soup = BeautifulSoup(r.content) 
print(soup)

但是无论我做什么,带有id='BTechPlayM' 的 div 仍然是空的。我试过了:

  • 设置请求超时:requests.get(uri, timeout=10)
  • 传递标头
  • 使用 eventlet 设置延迟
  • 最近尝试使用 selenium-library,使用 PhantomJS (installed from NPM),但这个兔子整体越来越深入。

有没有办法向 URI 发送请求,等待 X 秒,然后返回内容?

... 或者要向 URI 发送请求,请继续检查 div 是否包含元素;并且只返回内容,无论何时?

【问题讨论】:

    标签: python web-scraping python-requests web-crawler


    【解决方案1】:

    简短回答:不。您不能使用requests 来做到这一点。

    但是,正如您所说,表格数据是使用 JavaScript 动态生成的。数据来自this URL。但是,响应不是 JSON 格式;它是 JavaScript。因此,从这些数据中,您可以使用 RegEx 获取列表中可用的所需数据。

    但是,RegEx 返回的数据是字符串格式,而不是实际的列表。您可以使用ast.literal_eval() 将此字符串转换为列表。例如,数据如下所示:

    '["1", "Humana-Paredes", "CAN", "4", "1,720", ""]'
    

    完整代码:

    import re
    import requests
    import ast
    
    r = requests.get('http://www.fivb.org/Vis/Public/JS/Beach/TechPlayRank.aspx?Gender=1&id=BTechPlayW&Date=20180326')
    data = re.findall(r'(\[[^[\]]*])', r.text)
    for player in data:
        details = ast.literal_eval(player)
        print(details)  # this var is a list (format shown below)
    

    部分输出:

    ['1', 'Humana-Paredes', 'CAN', '4', '1,720', '']
    ['', 'Pavan', 'CAN', '4', '1,720', '']
    ['3', 'Talita', 'BRA', '4', '1,660', '']
    ['', 'Larissa', 'BRA', '4', '1,660', '']
    ['5', 'Hermannova', 'CZE', '4', '1,360', '']
    ['', 'Slukova', 'CZE', '4', '1,360', '']
    ['7', 'Laboureur', 'GER', '4', '1,340', '']
    ...
    

    这个列表(details)的基本格式是:

    [<Rank>, <Name>, <Country>, <Nb. part.>, <Points>, <Entry pts.>]
    

    您可以随意使用这些数据。例如,使用details[1] 将提供所有名称。

    【讨论】:

    • @Zeth,作为替代方案,您可以查看requests_html 库,该库在 Python 3.6 及更高版本中可用。
    【解决方案2】:

    您可以使用 selenium,因为请求不提供等待选项 -

    from selenium import webdriver
    from selenium.webdriver.common.by import By
    from selenium.webdriver.common.keys import Keys
    
    from bs4 import BeautifulSoup, Comment
    uri = 'http://www.fivb.org/EN/BeachVolleyball/PlayersRanking_W.asp'
    
    browser = webdriver.Chrome("./chromedriver") #download chromebrowser
    browser.set_page_load_timeout(60)
    browser.get(uri) #open page in browser
    text = browser.page_source
    browser.quit()
    
    soup = BeautifulSoup(text) 
    print(soup)
    

    您必须下载 chromedriver

    【讨论】:

    • 除非我们谈论的是类似 Facebook 的网站,否则对使用 ajax 加载数据的网站进行逆向工程通常相当容易。可以使用来自此 url fivb.org/Vis/Public/JS/Beach/… 的请求检索您查找的数据
    • 顺便说一句,因为您使用的是 Python 3,所以您应该使用 r.text,而不是 r.content。第一个返回一个 str - 这是 bs4 所需的 - 后面的字节......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-18
    • 2014-06-30
    • 2020-03-13
    相关资源
    最近更新 更多