【问题标题】:What is wrong with my Beautiful Soup find_all code here?我的 Beautiful Soup find_all 代码有什么问题?
【发布时间】:2020-01-15 23:55:19
【问题描述】:

我觉得我错过了一些非常基本的东西,但我被困住了。我只是想用 Beautiful Soup 返回一张桌子,但由于某种原因,它没有按 ID 抓取带有线分数的桌子。我可以通过他们在这个页面上的 ID 来定位其他 div 和表格,但由于某种原因,这个没有返回任何东西。知道我缺少什么吗?

from urllib.request import urlopen
from bs4 import BeautifulSoup
import ssl

url = 'https://www.sports-reference.com/cbb/boxscores/2020-01-14-19-clemson.html'
html = urlopen(url)
soup = BeautifulSoup(html.read(), 'html.parser')
ls = soup.find_all('table', {"id": "line-score"})

Web inspector screenshot

【问题讨论】:

  • 看来问题出在调用那个id
  • 我试过了,我自己也搞糊涂了
  • 我建议使用 requests 包,这对我有帮助

标签: python web-scraping beautifulsoup


【解决方案1】:

该表似乎是由 javascript 添加的,如果您实际查看源代码(右键单击查看源代码而不是检查),您将看到该表在 html 中被注释掉。
您需要在浏览器中呈现实际页面并获取生成的源代码。

【讨论】:

    【解决方案2】:

    正如 Ipellis 所说,您尝试抓取的表格是由 Javascript 添加的。这意味着该表格是在您发出初始请求后呈现的,因此 HTML 代码不包含它。

    要从中获取数据,我建议你从BeautifulSoup 切换到requests-html(一个非常相似的库)。这个处理这些 Javascript 案例并处理 Web 请求。

    您需要先安装它:pip install requests-html

    然后,您只需这样做:

    from requests_html import HTMLSession
    
    session = HTMLSession()
    request = session.get('https://www.sports-reference.com/cbb/boxscores/2020-01-14-19-clemson.html')
    request.html.render() # Here is where you render the table
    
    table = request.html.xpath('//table[@id="line-score"]')
    

    我建议您在查找元素时使用xpath。这是获取您正在寻找的元素的更好方法。如果你不了解 xpaths,这里是Xpath tutorial by W3Schools

    您可以获取requests-htmlhere的文档。

    【讨论】:

      【解决方案3】:

      是的,表格是通过JS添加的,但是数据已经在源代码中了。可以通过以下方式获取

      from simplified_scrapy.request import req 
      from simplified_scrapy.simplified_doc import SimplifiedDoc
      html = req.get('https://www.sports-reference.com/cbb/boxscores/2020-01-14-19-clemson.html')
      doc = SimplifiedDoc(html)
      table = doc.getElement('table',attr='id',value='line-score')
      trs = table.trs.notContains('thead',attr='class').notContains('colspan') # Filter out the head
      for tr in trs:
        tds = tr.children
        print ([td.text for td in tds])
      
      table = doc.getElement('table',attr='id',value='four-factors')
      trs = table.trs.notContains('thead',attr='class').notContains('colspan') # Filter out the head
      for tr in trs:
        tds = tr.children
        print ([td.text for td in tds])
      

      结果:

      ['Duke', '33', '39', '72']
      ['Clemson', '40', '39', '79']
      ['Duke', '73.5', '.574', '19.3', '13.8', '.185', '98.6']
      ['Clemson', '73.5', '.642', '19.3', '20.7', '.208', '108.2']
      

      可以获取SimplifiedDochere的例子

      【讨论】:

        【解决方案4】:

        您也可以通过渲染获取表格。以下代码使用 pyppeter 库。

        from simplified_html.request_render import RequestRender
        req = RequestRender({ 'executablePath': '/Applications/chrome.app/Contents/MacOS/Google Chrome'})
        def callback(html,url,data):
          from simplified_scrapy.simplified_doc import SimplifiedDoc 
          doc = SimplifiedDoc(html)
          table = doc.getElementByID('line-score')
          trs = table.trs.notContains('thead',attr='class').notContains('colspan') # Filter out the head
          for tr in trs:
            tds = tr.children
            print ([td.text for td in tds])
        req.get('https://www.sports-reference.com/cbb/boxscores/2020-01-14-19-clemson.html',callback)
        

        结果:

        ['Duke', '33', '39', '72']
        ['Clemson', '40', '39', '79']
        

        【讨论】:

          猜你喜欢
          • 2020-06-06
          • 2013-07-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-10-09
          相关资源
          最近更新 更多