基于协程的爬虫
基于gevent(协程),抓取站点的所有url
说到协程,协程不是进程或线程,其执行过程更类似于子例程,或者说不带返回值的函数调用。
协程在执行过程中遇到阻塞时转而执行别的子程序,阻塞结束后再返回来接着执行。
在gevent里面,上下文切换是通过yielding来完成的
代码中用到requests,xpath
如果有不懂xpath的小伙伴 --> 传送门
requests不理解的小伙伴 -->传送门
monkey.patch_all()
用来在运行时动态修改已有的代码,而不需要修改原始代码
官方文档链接 --> monkey.patch_all()
附带一篇中文gevent指南 -->传送门
不多说直接上代码
程序实现了判断域名,url去重
定义exp_url为set()结构,达到去重效果,也可以用list,dict,数据库
exp_url=set()
此处为去重部分
1 if domain in url: 2 if url in exp_url: 3 return
全部代码
1 from gevent import monkey 2 import gevent 3 import requests 4 from lxml import etree 5 6 monkey.patch_all() 7 8 domain="quanxue.cn" 9 exp_url=set() 10 defeated_url=[] 11 12 13 def requ(url): 14 jobs=[] 15 if domain in url: 16 if url in exp_url: 17 return 18 else: 19 exp_url.add(url) 20 print "GET:%s"%url 21 try: 22 req = requests.get(url) 23 data=req.content 24 select=etree.HTML(data) 25 links=select.xpath("//a/@href") 26 for link in links: 27 if 'http://' not in link: 28 link=url[:url.rindex('/')+1]+link 29 jobs.append(gevent.spawn(requ,link)) 30 else: 31 jobs.append(gevent.spawn(requ,link)) 32 gevent.joinall(jobs) 33 print len(exp_url) 34 except Exception,e: 35 print "ERROR" 36 defeated_url.append(url) 37 38 39 if __name__ == '__main__': 40 try: 41 url="http://www.quanxue.cn" 42 requ(url) 43 except: 44 print exp_url 45 print defeated_url 46 finally: 47 print defeated_url 48 print exp_url
效果图