Monthly Archives: May 2010

紧急赶制的Python抓取爬虫

前天一个朋友有紧急的要求:抓取一个工具书网站的上所有工具书信息,包括书名、作者、出版社、售价等等。还好原来做个一个python的爬虫程序,拿到这里修改修改还能运行,不过出现了几个问题:

1. 服务器拒绝。如果大量爬虫进程同时开始向服务器发出http请求,稍微有些安全意识的网站都会把你放到黑名单中,拒绝访问。比较好的方法就是使用互联网上免费的http proxy。

import urllib2

proxy = "61.219.107.164:8080"
url = "www.liyanyan.net"
proxy_support = urllib2.ProxyHandler({'http':proxy})
opener = urllib2.build_opener(proxy_support, urllib2.HTTPHandler)
urllib2.install_opener(opener)

print 'from proxy :'+proxy
html = urllib2.urlopen(url).read()

这样就能通过代理获取网页了。

2. 异常处理。原来的爬虫一旦遇到异常就会退出,添加异常后更具有健壮性,但是需要对python异常进行分类了解,针对不同的异常进行处理。

3. html内容分析。使用正则表达式太麻烦,不如使用SGMLParser这样现有的类更加方便。

4.多线程支持。在使用数十个proxy的情况下,如果不使用多线程的话就太浪费了,下面有个简单的使用thread和Queue配合的多线程ping

from threading import Thread
import subprocess
from Queue import Queue

num_threads = 4
queue = Queue()

ips = ["61.219.107.164", "92.50.163.114", "128.195.54.163", "129.107.35.132"]

def pinger(i,q):
	"""pings test"""
	while True:
		ip = q.get()
		print "Thread %s: Pinging %s" % (i,ip)
		ret = subprocess.call("ping -c 1 %s" % ip,
							shell=True,
							stdout=open('/dev/null','w'),
							stderr=subprocess.STDOUT)
		if ret == 0:
			print '%s is alive' % ip
		else:
			print '%s is not alive' % ip
		q.task_done()

for i in range(num_threads):
	worker = Thread(target=pinger , args= (i,queue))
	worker.setDaemon(True)
	worker.start()
for ip in ips:
	queue.put(ip)

queue.join()

javascript里的条件判断

JavaScript 是一种可以在浏览器中运行的脚本语言,是一种弱语言(相对于C,C#,JAVA而言),只要是计算机语言就会使用到条件判断式,而JavaScript作为一种“弱”语言,它的条件判断常常令人困惑不解,特别是有其它强语言编程经历的人来说,更是不可理喻!高手和无惑的人别取笑,我自己也曾经有一段时间郁闷过。先写一个例子吧:

var s = “meizz”;
if (s && s==true)
{
alert(“Is true”);
}

咱先不管上面的代码运行的结果正确与否,我给变量 s 赋的是字符型,而在后面的 if 条件判断式里是直接把变量 s 作为一个判断表达式写出的,若是在强语言里对字符型的变量要么是判断它的类型是否是字符型或者是判断这个变量的值是否等于某字符串,但在 javascript 里就是没有用类型判断(typeof)也没有值判断(==)而就是这么孤伶伶地在那里,就可以作为一个条件判断表达式。当然这种单独作为条件表达式不只是字符型变量,也可以是数字型变量,也可以是一个对象,也可以是一个函数或者方法等等。这就正是这种语法令人费解的地方。

我测试统计了一下:在 JavaScript 里,不为空 “” 的字符串、不为 0 的数字、不为 null 的对象、不为 undefined 的对象属性、布尔型 true,单独作为判断式里的一个表达式时 JavaScript 通通认定为真(true),反之则为假(false)

原因为是JS脚本没有强变量类型,你前一句赋值 var s = “meizz”; 后一句你甚至马上可以写成 s = function(){}; ,中间没有任何的类型转换,而这些写法在强语言里是不可思议的,甚至是大逆不道的(根本就不支持这种语法),但在JS脚本里却是那么的自然。原因就是没有强制变量类型, 变量类型是动态的,也就是说变量本身是没有类型的,变量的值是有类型的。呵呵,这里扯到其它模块去了,嗯,关于变量类型我另外再写文章讨论吧。

说到这里,就不难理解 if (s && …..这句的判断式了,同样的道理,我甚至可以 function s(){} 然后再用 if (s && …. 或者 var s = document.getElementById(“ObjectId”);  if (s && …. 这样语法在JS脚本里都是没错的,至于判断的结果可以参考上面的那段统计结果。

现在再来讨论上面的那几句代码的运行结果,多个条件判断式的结果合成运行只有“与”和“或”,到于“非”因为它是一元运行符,只针对单个值,比如 if (!s) … 至于条件式不只一个的时候条件式的结果只有与和或的运行。与(&&),或(||)。上面的那句条件式:if (s && s==true) 就是两个条件式的合成判断。至于与运算(只要一个值为false则值为false)或运算(只要一个值为true则值为true)这些运算细节我就不多说了,教科书比我的笔头强多了。现在来分析这个判断式:这是一个“与”运算。第一个判断式 s ,因为它的字符型值不为 “” ,在JS当然认为它等同于 true,第二个判断式是 s==true,显然这个不相等,值为 false,因为是“与”运算,当然整个条件判断式的结果是 false,所以不会运行 alert()。

第三,我这里说说几个很特殊的条件判断。在没有任何声明(var)和赋值的情况下,直接拿一个变量来判断JS会抛出一个变量未定义的错误出来。比如:

if (ss) alert(“条件判断结果为 true!”);

运行这句代码就会出错。因为这个变量 ss 从未被声明赋值过,这种情况不等同于上述的 null “” undefined。这种情况一般会发生在什么地方呢?一是自己写代码不小心未声明,二就是对网页里没有的控件进行操作直接用ID来操作的时候,比如 if (InputId.value!=””) … ,若是网页里根本就没有 id=”InputId” 的文本框或者在执行这句脚本操作的时候这个文本框还没有被浏览器加载,那也就抛出变量未定义的错误。

结果的办法是:第一种情况用 typeof 判断。if (typeof(ss)==”undefined”) alert(“变量未定义”);  ,第二种情况则不要直接使用ID来引用对象而使用标准的对象引用。例:

var e = document.getElementById(“InputId”);  //IE里以前是用 document.all.InputId
if (e && e.value!=””) ;//……

这样就不会出这种错误了。

那么就上面这句代码有人会说一定要这样写呢,为什么不直接

if(document.getElementById(“InputId”).value != “”) ;//….

这样的代码不是更精练吗?城然代码是精简了,但错误也来了。只要网页里没有这个对象或者这个对象在脚本执行的时候还未被加载到,就会报错。原来是 document.getElementById(“InputId”) 返回了 null 值,而 null 显然是没有 value 属性的,而我那句代码也用到了 e.value 来取属性但就没有报错,原因在于C系列的语言在多个条件式里的另一外属性:多个条件判断式组合判断时,先看第一个条件式,若已经符合条件时,就不会再去判断第二个判断式;也就是在第一个条件判断式未达到标准时再会去判断第二个判断式,依此类推直至最后。if (e && e.value!=””) 是两个判断式的组合判断,这是一个“与”运算,只要一个判断式为 false 则整个值都为 false。第一个判断式 e 由于不存在或者未加载到返回了 null,而在JS里 null 就等同于 false ,这样不用后面的判断也可得到整个组合判断的结果是 false 了,所以系统就不会再去判断后面的那句 e.value 了。这点与B系列语言不同,尤其要注意。在B语言中 if e and e.value!=”” then 这样的语句是先把所有的判断式都运算一遍后最后再做组合的“与”运算。所以这句代码在JS里是正确的,若放在VBS里就不一定正确了。

查看本文来源

是选择高清播放器还是选择HTPC

新家的装修已经开始了,五一已经买了46寸的夏普LCD,心里一直打算怎么来折腾这台大尺寸的电视。

首先,需要能够在电视上播放1080p或者720p的电影,要不46寸的屏幕岂不是浪费了。本来自己是准备装一台HTPC的,为了方便下载高清电影,但是发现最新的高清播放器已经能够很好的解决“播放”和“下载”的问题了。上淘宝搜索到了这个高清播放器-天敏DMP550

在播放方面,除了VC-1编码格式的高清之外,H.264编码的一般都能正确播放,目前网上大部分avi或者mkv格式都是H.264编码的。并且采用的AML8626H芯片还能支持网络下载,甚至能够支持USB无线网卡!如果这样的话,HTPC存在的意识实在是不大了,原因如下:

1. 价格因素。高清播放器在500左右,HTPC即使采用低端的平台也得2k左右。

2.用电因素。高清播放器待机功耗6瓦左右,播放高清视频功耗也就是8瓦左右;而HTPC再怎么节能也要80瓦了,还只是平时待机状态而已,下载的时候估计耗电更大。

3.占地面积。高清更加小巧,HTPC占地面积更大,并且如果想用好的HTPC机箱需要更多的money。

4.存放空间。这款高清播放器也能使用2.5寸的SATA硬盘,储存电影的能力不比HTPC差多少。

不过HTPC可以加上电视卡和接受卫星信号的1020卡,这要比高清播放器功能更加强大。非常想在新装修的家里面能够看到国家地理频道,要不就加一个DM500吧,也就是300块钱左右,就能很完美的替代HTPC了。

PS:又找到了一款英菲克i9高清播放器,价格比天敏DMP550稍微便宜了一点,不过从英菲克的论坛上来看固件的更新速度很快。