一个简单的监控网页变化的方法

最近遇上一个小的实际需求:一个页面上有些许表格,我们需要监控这个页面,当表格的内容有变化的时候,及时通知我们。需求比较小,要求是用尽量简单的方式来实现。另外,这个页面是要求登陆态的。

想了想,大约没有什么现成的解决方案,那么打算自己写代码来实现。

自然的想起脚本语言来,首先尝试了 python,在 python 2 自带的 urllib2 的帮助下,抓取页面这个步骤还是比较简单的,几行代码就可以完成功能

url = "http://..."
headers = {"Cookie" : "..."}
request = urllib2.Request(url, None, headers)
response = urllib2.urlopen(request)
html = response.read()

但是在解析 html 的时候出现了问题。

简单搜索一下,发现 python 用来解析 html 的,有自带的 HTMLParser,以及第三方库,beautiful soup,第三方库下载之后简单的尝试安装了一下,没有安装成功,快速的放弃了,转而查看 HTMLParser 的文档,这个东西其实也还是蛮强大的,但是写起来比较复杂,需要用一种状态驱动的方式去写接口,样例的代码可以看到这里,http://cloudaice.com/yong-pyth…

from HTMLParser import HTMLParser
import urllib
import sys
class parselinks(HTMLParser):
def __init__(self):
self.data=[]
self.href=0
self.linkname=”
HTMLParser.__init__(self)
def handle_starttag(self,tag,attrs):
if tag ==’a’:
for name,value in attrs:
if name == ‘href’:
self.href=1
def handle_data(self,data):
if self.href:
self.linkname+=data
def handle_endtag(self,tag):
if tag==’a’:
self.linkname=”.join(self.linkname.split())
self.linkname=self.linkname.strip()
if self.linkname:
self.data.append(self.linkname)
self.linkname=”
self.href=0
def getresult(self):
for value in self.data:
print value
if __name__==”__main__”:
IParser = parselinks()
IParser.feed(urllib.urlopen(“http://www.python.org/index.html”).read())
IParser.getresult()
IParser.close()

这样虽然也可以完成任务,但是还是略繁琐了。

而问题并没有到此结束,接下来遇到的问题是,当发现变化的时候,怎么通知到我们呢。假设我们都在电脑前坐着,但是需要干其他事情,而这个 python 脚本是基于终端的,那么,我们就只能把终端窗口一直开着,然后在发现变化的时候,打出一串长长长的字符串。。。真是一个挫办法。。

不管怎么说,这个方式大约是实现了。

然后试试 php,php 不愧是为网页量身的脚本语言,抓取页面,解析页面,都是很方便的,来看这段代码

// Create a stream
$opts = array(
  'http'=>array(
    'method'=>"GET",
    'header'=>"Cookie:...\r\n"
  )
);

$context = stream_context_create($opts);

// Open the file using the HTTP headers set above
$file = file_get_contents('http://...', false, $context);

可以看到 php 抓取页面并不比 python 引以为豪的 urllib2 复杂,然后再来看解析页面

$table = strstr($file, "<tbody>");
$table = substr($table, 0, strpos($table, "</tbody>"));
$tr_arr = explode("<tr>", $table);

foreach($tr_arr as &$tr) {
    $tr = trim(strip_tags($tr));
    //var_dump($tr);
}

//var_dump($tr_arr);

if (strstr($tr_arr[1], "...") == false) {
    echo 1;
} else {
    echo 0;
}

在 strip_tags 这个神奇函数的帮助下,我们可以十分轻松的把页面的内容抽取出来,然后稍微字符串查找一下,就 ok 了。

但是这个依然遇到的问题就是怎么提示,由于 python 是常驻脚本,还可以死循环跑,然后终端打出,但是 php 被设计为一个短暂脚本,那么,看来就要上 js 了。

说道这里,就想起来之前 gmail 上面出现过的桌面通知,这可是个好东西,搜了一下,找到这个文章,http://www.cnblogs.com/cloudle…,按照里面的方法,敲进去,但是发现弹不出来啊,再一阵搜,找到这里,http://stackoverflow.com/quest…,人说了,要在回调里面调这个函数,那么可以得到代码如下

<script src="http://codeorigin.jquery.com/jquery-1.10.2.min.js"></script>

<button id="btn">request notify permission</button>

<script>
    function notify() {
        if (window.webkitNotifications.checkPermission() == 0) {
            window.webkitNotifications.createNotification('image.png', '标题', '内容').show();
        } else {
            window.webkitNotifications.requestPermission(notify);
        }
    }
    $(function(){
        $("#btn").click(function(){
            notify();
        });
        setInterval(function(){            
            $.get("mo.php", function(data){
            if (data != 0) {
                notify();
            } else {
                console.log(new Date());
            }
       });
       }, 10000);    
    });
</script>

至此需求基本完成

5 thoughts on “一个简单的监控网页变化的方法

  1. Python 分析网页应该用 requests + lxml,前者下载内容,后者有 HTML Parser 并且支持 XPath 语法。

    标准库的 urllib 系的 API 设计实在反人类,Beautiful Soup 的 CSS 选择器其实远不如 XPath 灵活和易于修改。

    • 一个人两个电脑,一个用来查资料上网逛 bbs,另外一个用来写代码的机器是不能连外网的,于是 py 的那些什么在线自动安装的包管理就悲剧了,下载了安装包拖到另外一台机器发现装起来麻烦,还跑不起来,时间又赶,自然就换上 php 自带的内置函数了。。

      • Python 也可以像 Java 的 jar 包一样,把库下载下来用的~

        真用 PHP 也应该有 xml 解析库吧?手动拆字符串,万一别人网页变了,改代码多痛苦~

        • 原来有类 jar 的包。。我看看。。我上次装的 py 库是 msi 的封装形式。。当时还想着怎么这么奇葩。。

Leave a Reply to ZRJ Cancel reply

Your email address will not be published. Required fields are marked *