说到协程,协程不是进程或线程,其执行过程更类似于子例程,或者说不带返回值的函数调用。

协程在执行过程中遇到阻塞时转而执行别的子程序,阻塞结束后再返回来接着执行。

在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

 

 效果图

基于协程的爬虫