500lines之crawler学习(三)
回到最初的话题,为什么我们通过:
python -q crawl.py xkcd.com
上面命令在控制台运行,啥结果都没有,是因为在第一篇博客(crawler学习(一))中,分析过-q会让日志级别变低(level=0),设置代码(crawl.py中)如下:
levels = [logging.ERROR, logging.WARN, logging.INFO, logging.DEBUG]
logging.basicConfig(level=levels[min(args.level, len(levels)-1)])
所以我们要查看日志信息,就不要加-q命令(或者加-v)提高日志显示级别。我们再运行:
python crawl.py xkcd.com
结果如下:
控制台总算出现了两条日志信息,然后就卡住了,什么结果也没有。这显然不是我们想要的结果。但是我们通过日志,还是能得出重要的信息,那就是打印第二行的日志以后,我们的程序在某个地方卡住了。所以先找到第二条日志打印的地方:
(图一)
在crawling.py中,我们找到第二条打印日志的地方,通过每行打印的方式,再结合(crawler学习(一))中urljoin函数的用法,我们初步判断应该是urljoin函数的地方出了错。
但是什么错,为什么没在控制台显示出来呢?还是在crawling.py中:
可以看出,代码采用的是try...finally结构,没有捕获异常,更不要说抛出来了。所以我们需要加点代码:
运行结果如下:
(图二)
可以看出,我们的代码起了效果,获得了抛出的异常信息。虽然这个信息有点用,但是我仍然不能确定是什么原因导致的这个错误,所以我把上面(图一)中urls所有值都打印出来,然后与url(https://xkcd.com/)进行urljoin操作,结果都正确,没出现异常。经过仔细观察上面的(图二),发现response.url并不是“https://xkcd.com/”,而是:
URL('https://xkcd.com/')
不错,这个玩意居然是一个URL对象,一个字符串与一个URL对象比较,当然会出错啦。那怎么将URL变成字符串呢?
我们只知道它是一个URL对象,并不知道URL对象里面有些什么方法?通过aiohttp文档,我找到了以下网页:
https://yarl.readthedocs.io/en/stable/api.html#yarl.URL
列出重点:
>>> url = URL('http://εμπορικόσήμα.eu/путь/這裡') >>> str(url) 'http://xn--jxagkqfkduily1i.eu/%D0%BF%D1%83%D1%82%D1%8C/%E9%80%99%E8%A3%A1' >>> url.human_repr() 'http://εμπορικόσήμα.eu/путь/這裡'
可以看出可以通过str()函数对URL编码成一个字符串,或者通过human_repr()函数返回字符串形式。由于xkcd.com都是些英文网页,所以我直接采用了str()形式:
for url in urls:
normalized = urllib.parse.urljoin(str(response.url), url)
defragmented, frag = urllib.parse.urldefrag(normalized)
if self.url_allowed(defragmented):
links.add(defragmented)
再运行程序,控制台会出现发送请求后得到的各种日志信息!
然而,即便如此,此crawler项目也还有许多问题需要解决。此文算是迈出重要一步!!!