【问题标题】:BeautifulSoup parse table data that doesn't load immediatelyBeautifulSoup 解析不会立即加载的表数据
【发布时间】:2016-10-17 14:59:40
【问题描述】:

我正在尝试使用 beautifulsoup 从https://www.zacks.com/stock/research/MMM/earnings-announcements 下载收益公告数据。当我查看表格时,我感兴趣的表格 (earnings_announcements_earnings_table) 仅显示“正在加载数据……”。但是,如果我打印汤的全部内容,我确实会看到我正在寻找的信息在那里。我可以将这些数据隔离为一个“脚本”元素,但其中包含许多其他不需要的信息。如何仅选择和解析我要查找的特定数据,即“earnings_announcements_earnings_table”表的内容,如下所示:

" 变量 obj = { “earnings_announcements_earnings_table”: [ [“10/25/2016”、“9/2016”、“$2.14”、“--”、“--”、“开盘前”] ,...”

这是我目前所拥有的:

from urllib import request
from urllib import error
from bs4 import BeautifulSoup

def download_parse_earnings(symbol):

request_string = "https://www.zacks.com/stock/research/%s/earnings-announcements" % symbol
print(request_string)

try:
    web = request.urlopen(request_string)
except error.HTTPError:
    return

soup = BeautifulSoup(web.read(), 'lxml')
data = soup.find_all("script")[28].string
print(data)

【问题讨论】:

  • 具体来说,您要检索什么?

标签: python beautifulsoup


【解决方案1】:

一种方法是启动 Selenium 并利用其 Javascript 引擎。这不是很简单,我在这里提供了一个完全破解的替代解决方案,但它应该适用于您感兴趣的页面。

假设页面是自动生成的,我们观察到你想要的数据在(继续你的程序):

import json
earnings = json.loads(data.split('var obj =')[1].splitlines()[2])

这是利用 Javascript 对象是 JSON 的事实,因此我们直接从源代码中读取。结果是这样一个列表的列表:

[['10/25/2016', '9/2016', '.14', '--', '--', 'Before Open'],
 ['7/26/2016',
  '6/2016',
  '.08',
  '.08',
  '<div class=right pos_na showinline>0.00 (0.00%)</div>',
  'Before Open'],
 ['4/26/2016',
  '3/2016',
  '.92',
  '.05',
  '<div class=right pos positive pos_icon showinline up>0.13 (6.77%)</div>',
  'Before Open'],
 ['1/26/2016',
  '12/2015',
  '.62',
  '.80',
  '<div class=right pos positive pos_icon showinline up>0.18 (11.11%)</div>',
  'Before Open'],
 ['10/22/2015',
  '9/2015',
  '.01',
  '.05',
  '<div class=right pos positive pos_icon showinline up>0.04 (1.99%)</div>',
  'Before Open'],
...
]

第一个元素对应表格的第一行,即表头。您现在只需清理数据即可。

【讨论】:

    【解决方案2】:

    不使用 Selenium 但仍然使用 json 就像在第一个答案中一样,您可以使用 BS 挖掘出您需要的内容。

    >>> from bs4 import BeautifulSoup
    >>> from urllib import request
    >>> URL='https://www.zacks.com/stock/research/MMM/earnings-announcements'
    >>> HTML=request.urlopen(URL).read()
    >>> soup=BeautifulSoup(HTML)
    >>> import json
    >>> scripts=soup.findAll('script')
    >>> len(scripts)
    36
    
    >>> for script in scripts:
    ...     if script.has_attr('type') and script.attrs['type']=='text/javascript' and script.text.strip().startswith('$(document).ready(function()'):
    ...         break
    

    这样,javascript 就可以作为 script.text 使用了。您仍然需要做一些稍微聪明的事情来提取Rubik's 答案中显示的行。没有什么是不可能的。

    【讨论】:

    • 您可以传递一个正则表达式来查找可以避免遍历每个脚本标记的需要。 script = soup.find("script", text='$(document).ready(function()')
    猜你喜欢
    • 2015-07-11
    • 1970-01-01
    • 2017-10-08
    • 2017-02-01
    • 1970-01-01
    • 2021-06-04
    • 1970-01-01
    • 2017-03-31
    • 2022-09-28
    相关资源
    最近更新 更多