最近几天一直在写网络爬虫,用的是python,图的是方便省事,不过中间确实遇到过几次让人头疼的问题,现记录如下:
一.建立网络链接的问题
使用的是python提供的urllib2模块,用urllib2.urlopen()函数建立链接,该函数抛错率高,还可能不响应,因此要设定timeout,并使用try except else来容错。
二.从链接中读取数据的问题
使用urlopen获得response后,调用respons.read()读取网页数据,这也是程序假死的罪魁祸首之一,更无奈的是该函数不接受timeout参数,导致线程直接卡死在这儿,并且python不像ruby一样直接支持函数的timeout写法,因此这个问题很棘手,目前尚未解决。
今天看来可能不是read函数出问题,还是出在print上面。一个解决方法是主程序将需要爬的url列表分成若干份,每次创建多线程去读取其中一份并将数据记录下来,如此依次解决掉所有的url。不算完美,但还是一个较容易实现的记录中间结果的办法。
三.多线程问题
爬数据当然要用到多线程,比如threading模块,多线程最要注意的就是死锁现象,但是在只使用了一把锁的情况下依然出现了,查了半天,发现极大可能是临界区中的print函数造成的。按理说print应该是时间片占用,到时间了该自动释放,但事实却是它造成了死锁(不算很严密的验证过),将print从临界区移除后死锁现象消失了,但是为什么会这样不太理解。
今天又出现了数次类似现象,都是线程在做pinrt操作时,没有完成,并且一直卡在那,并且还是在非临界区。难道python的print和多线程真有冲突?如果是这样只有采用写log文件的方法了。
四. 编码问题
从网页上面爬下来的内容编码常常特别混乱,即使网页上的charset写明是某种编码,如'gb2312',也往往不太可靠,用python进行String的decode操作时常常出错,尤其是要把其中部分内容放入数据库时。
一种做法是采用decode函数的 'ignore' 参数,这样可以忽略网页上的小部分乱码,避免一颗老鼠屎坏一锅汤的问题。但是很可能做完parsing以后要把结果存入DB,这时这些内容很可能乱码,即使你把内容输出到屏幕时是正常的。针对这种情况,我的一个经验是利用剪贴板,比如你把结果都写入到 result.txt 文件,然后新建一个 true_result.txt 文件,并且把 result.txt 文件里面的内容复制粘贴过来,通过这个过程,不规范的乱码被去除了,剩下干净的编码,然后存入Database。