从网站上抓取动态更新的温度传感器数据



我写了以下python代码:

from bs4 import BeautifulSoup
import urllib2
url= 'http://www.example.com'
page = urllib2.urlopen(url)
soup = BeautifulSoup(page.read(),"html.parser")
freq=soup.find('div', attrs={'id':'frequenz'})
print freq

结果是:

<div id="frequenz" style="font-size:500%; font-weight: bold; width: 100%; height: 10%; margin-top: 5px; text-align: center">tempsensor</div>

当我用web浏览器查看这个网站时,网页显示的是动态内容,而不是字符串'tempsensor'。温度值每秒自动刷新。所以网页上的东西自动将字符串'tempsensor'替换为数值。

我现在的问题是:我怎样才能让Python显示更新的数值?如何获取BeautifulSoup中自动更新到tempsensor的值?

抱歉,不能单独使用BeautifulSoup

问题是BS4不是一个完整的web浏览器。它只是一个HTML解析器。它不解析CSS,也不解析Javascript。

一个完整的浏览器至少要做四件事:

  1. 连接到web服务器,获取数据
  2. 解析HTML内容和CSS格式并呈现网页
  3. 解析Javascript内容,并运行它。
  4. 为浏览器导航、HTML表单和Javascript程序的事件API提供用户交互

还是不确定?现在看看你的代码。BS4甚至不包括第一步,获取网页,要做到这一点,你必须使用urllib2

动态站点通常包含Javascript以在浏览器上运行并定期更新内容。BS4不提供这个功能,所以你不会看到它们,而且只使用BS4永远不会看到它们。为什么?由于上面的第(3)项,下载和执行Javascript程序不会发生。这可能发生在IE, Firefox或Chrome中,这就是为什么这些工作可以显示动态内容,而仅bs4抓取不显示它。

PhantomJS和CasperJS提供了一个更机械化的浏览器,通常可以运行启用动态网站的JavaScript代码。但是CasperJS和PhantomJS是用服务器端Javascript编程的,而不是Python。

显然,有些人正在使用PyQt4内置的浏览器来执行这些类型的动态屏幕扫描任务,隔离部分DOM,并将其发送到BS4进行解析。这可能允许使用Python解决方案。

在注释中,@Cyphase暗示你想要的确切数据可能在不同的URL上可用,在这种情况下,它可能被urllib2/BS4获取和解析。这可以通过仔细检查站点上运行的Javascript来确定,特别是可以查找调度更新的setTimeoutsetInterval,或者查找用于从后端获取数据的ajax或jQuery的.load函数。用于更新动态内容的javascript将通常只从同一网站的后端url获取数据。如果他们使用jQuery $('#frequenz')引用div,通过在JS中搜索这个,你可能会发现更新div的代码。没有jQuery, JS更新可能会使用document.getElementById('frequenz')

你少了一小段代码:

from bs4 import BeautifulSoup
import urllib2
url= 'http://www.example.com'
page = urllib2.urlopen(url)
soup = BeautifulSoup(page.read(), 'html.parser')
freq = soup.find('div', attrs={'id':'frequenz'})
print freq.string  # Added .string

应该这样做:

freq.text.strip()

>>> html = '<div id="frequenz" style="font-size:500%; font-weight: bold; width: 100%; height: 10%; margin-top: 5px; text-align: center">tempsensor</div>'
>>> soup = BeautifulSoup(html)
>>> soup.text.strip()
u'tempsensor'