最近遇上一个小的实际需求:一个页面上有些许表格,我们需要监控这个页面,当表格的内容有变化的时候,及时通知我们。需求比较小,要求是用尽量简单的方式来实现。另外,这个页面是要求登陆态的。
想了想,大约没有什么现成的解决方案,那么打算自己写代码来实现。
自然的想起脚本语言来,首先尝试了 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>
至此需求基本完成
这个可以有啊
登录的录写错了<–_<–
Python 分析网页应该用 requests + lxml,前者下载内容,后者有 HTML Parser 并且支持 XPath 语法。
标准库的 urllib 系的 API 设计实在反人类,Beautiful Soup 的 CSS 选择器其实远不如 XPath 灵活和易于修改。
一个人两个电脑,一个用来查资料上网逛 bbs,另外一个用来写代码的机器是不能连外网的,于是 py 的那些什么在线自动安装的包管理就悲剧了,下载了安装包拖到另外一台机器发现装起来麻烦,还跑不起来,时间又赶,自然就换上 php 自带的内置函数了。。
Python 也可以像 Java 的 jar 包一样,把库下载下来用的~
真用 PHP 也应该有 xml 解析库吧?手动拆字符串,万一别人网页变了,改代码多痛苦~
原来有类 jar 的包。。我看看。。我上次装的 py 库是 msi 的封装形式。。当时还想着怎么这么奇葩。。