BeautifulSoup找到元素但不是文本

时间:2018-02-22 13:44:02

标签: python beautifulsoup

我正在尝试使用BeautifulSoup提取MLB游戏的游戏统计数据。到目前为止它一直运作良好,但我只是注意到我无法使用通常的方式检索有关游戏开始时间的信息:

soup.findAll(“span”,{“class”:“time game-time”})

这有什么奇怪之处在于它找到了确切的元素,并允许我打印它,它表明汤已经找到了元素的所有内容,除了文本。不幸的是,文本部分是我所需要的。

图片:

enter image description here enter image description here

有问题的网址: http://www.espn.com/mlb/game?gameId=370925110

有没有办法绕过这个问题而不必使用像Selenium这样的网络驱动程序?

代码:

with urllib.request.urlopen(link) as url:
    page = url.read()
soup = BeautifulSoup(page, "html.parser")
clock = soup.findAll("span", {"class": "time game-time"})
print(clock[0])

2 个答案:

答案 0 :(得分:3)

虽然通常你不得不做一些逆向工程,但这里不会消耗任何外部API来填补游戏时间。

可以在页面源的脚本标记中找到游戏的时间戳作为变量。

Plain Beautifulsoup足以获得时间戳:

js = str(soup.findAll("script", {"type": "text/javascript"}))
s = 'espn.gamepackage.timestamp = "'
idx = js.find(s) + len(s)
ts = ""
while js[idx] != '"':
    ts += js[idx]
    idx += 1
print(ts)
# 2017-09-25T17:05Z

时间戳以UTC表示,如尾随Z所示。 要转换为其他时区,您可以使用python-dateutil

from datetime import datetime
from dateutil import tz

ts = datetime.strptime(ts, "%Y-%m-%dT%H:%MZ")
ts = ts.replace(tzinfo=tz.gettz('UTC'))
target_tz = ts.astimezone(tz.gettz('Europe/Berlin'))
print(target_tz)

(见Python - Convert UTC datetime string to local datetime

答案 1 :(得分:2)

这是因为此特定span标记由javascript填充。

如果您想亲眼看到它,请在浏览器上打开URL并查看页面的代码来源以找到此范围,您将看到:

<span class="time game-time" data-dateformat="time1" data-showtimezone="true"></span>

(或curl 'http://www.espn.com/mlb/game?gameId=370925110' | grep 'time game-time',无论如何)

所以你必须在这里找到解决方案:

  1. 使用selenium
  2. 在网站上进行一些逆向工程,以了解它是如何工作的,以及如何重现这种行为(通常:查找调用哪个API以及如何调用API,然后自己调用API而不是获取HTML页面)。