【问题标题】:How to scrape page with BeautifulSoup? Page Source not matching Inspect Element如何用 BeautifulSoup 抓取页面?页面源与检查元素不匹配
【发布时间】:2019-03-25 10:01:00
【问题描述】:

我正在尝试从this fantasy basketball page 中抓取一些东西。我在 Python 3.5+ 中使用 BeautifulSoup 来做到这一点。

source_code = requests.get('http://fantasy.espn.com/basketball/league/standings?leagueId=633975')
plain_text = source_code.text
soup = BeautifulSoup(plain_text, 'lxml')

首先,我想将 9 个类别的标题抓取到 Python 列表中。所以我的列表应该看起来像categories = [FG%, FT%, 3PM, REB, AST, STL, BLK, TO, PTS]

我希望做的事情如下:

tableSubHead = soup.find_all('tr', class_='Table2__header-row')
tableSubHead = tableSubHead[0]
listCats = tableSubHead.find_all('th')
categories = []
for cat in listCats:
  if 'title' in cat.attrs:
  categories.append(cat.string)

但是,soup.find_all('tr', class_='Table2__header-row') 返回一个空列表,而不是我想要的表格行元素。我怀疑这是因为当我查看页面源代码时,它与 Chrome Dev Tools 中的 Inspect Element 完全不同。我知道这是因为 Javascript 会动态更改页面上的元素,但我不确定解决方案是什么。

【问题讨论】:

    标签: python web-scraping beautifulsoup


    【解决方案1】:

    您面临的问题是因为该网站是一个网络应用程序,这意味着必须运行 javascript 才能生成您所看到的内容,您无法使用 request 运行 javascript,这就是我所做的使用selenium 得到结果,它会打开一个无头浏览器,并通过等待一段时间使 javascript 先运行:

    import requests
    from bs4 import BeautifulSoup
    from selenium import webdriver
    from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
    import time
    
    # source_code = requests.get('http://fantasy.espn.com/basketball/league/standings?leagueId=633975')
    
    options = webdriver.ChromeOptions()
    options.add_argument('headless')
    capa = DesiredCapabilities.CHROME
    capa["pageLoadStrategy"] = "none"
    driver = webdriver.Chrome(chrome_options=options, desired_capabilities=capa)
    driver.set_window_size(1440,900)
    driver.get('http://fantasy.espn.com/basketball/league/standings?leagueId=633975')
    time.sleep(15)
    
    plain_text = driver.page_source
    soup = BeautifulSoup(plain_text, 'lxml')
    
    soup.select('.Table2__header-row') # Returns full results.
    
    len(soup.select('.Table2__header-row')) # 8
    

    这种方法将允许您运行设计为 web 应用程序的网站,并大大扩展您的功能。 - 您甚至可以添加命令来执行,例如滚动或单击以在飞行中加载更多源。

    使用pip install selenium 安装 selenium。如果您喜欢该浏览器,还允许您使用 Firefox。

    【讨论】:

    • 这很有意义。让我试试看,如果可行,我会将其标记为已接受的答案。
    • 注意 soup.select 使用 css 选择器,我认为使用这些选择器并运行循环来提取特征后记要容易得多 - 这里只是个人意见。
    【解决方案2】:

    这可能不是您正在寻找的,但由于页面源没有任何内容,因此它并不是真正可用的。但是,显然,在加载记分板时,该站点会进行几个 API 调用,这些调用很可能包含您要查找的所有数据。

    API call here 似乎包含您要查找的所有信息。

    import requests
    payload = {"view":["mMatchupScore","mScoreboard","mSettings","mTeam","modular","mNav"]}
    r = requests.get("http://fantasy.espn.com/apis/v3/games/fba/seasons/2019/segments/0/leagues/633975", params=payload).json()
    
    # r is a json object with all the data in it
    

    【讨论】:

    • 使用 selenium 的良好替代方案,但请注意,有时劫持 API 调用将不起作用,因为它依赖于为强制浏览器使用的会话生成的 API 密钥。
    猜你喜欢
    • 2020-05-22
    • 2018-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-27
    • 1970-01-01
    • 1970-01-01
    • 2015-05-08
    相关资源
    最近更新 更多