python使用tornado实现简单爬虫
本文实例为大家分享了python使用tornado实现简单爬虫的具体代码,供大家参考,具体内容如下
代码在官方文档的示例代码中有,但是作为一个tornado新手来说阅读起来还是有点困难的,于是我在代码中添加了注释,方便理解,代码如下:
#coding=utf-8 #!/usr/bin/envpython importtime fromdatetimeimporttimedelta try: fromHTMLParserimportHTMLParser fromurlparseimporturljoin,urldefrag exceptImportError: fromhtml.parserimportHTMLParser fromurllib.parseimporturljoin,urldefrag fromtornadoimporthttpclient,gen,ioloop,queues #设置要爬取的网址 base_url='http://www.baidu.com' #设置worker数量 concurrency=10 #此代码会获取base_url下的所有其他url @gen.coroutine defget_links_from_url(url): try: #通过异步向url发起请求 response=yieldhttpclient.AsyncHTTPClient().fetch(url) print('fetched%s'%url) #响应如果是字节类型进行解码 html=response.bodyifisinstance(response.body,str)\ elseresponse.body.decode(errors='ignore') #构建url列表 urls=[urljoin(url,remove_fragment(new_url)) fornew_urlinget_links(html)] exceptExceptionase: print('Exception:%s%s'%(e,url)) #报错返回空列表 raisegen.Return([]) #返回url列表 raisegen.Return(urls) defremove_fragment(url): #去除锚点 pure_url,frag=urldefrag(url) returnpure_url defget_links(html): #从html页面里提取url classURLSeeker(HTMLParser): def__init__(self): HTMLParser.__init__(self) self.urls=[] defhandle_starttag(self,tag,attrs): href=dict(attrs).get('href') ifhrefandtag=='a': self.urls.append(href) url_seeker=URLSeeker() url_seeker.feed(html) returnurl_seeker.urls @gen.coroutine defmain(): #创建队列 q=queues.Queue() #记录开始时间戳 start=time.time() #构建两个集合 fetching,fetched=set(),set() @gen.coroutine deffetch_url(): #从队列中取出数据 current_url=yieldq.get() try: #如果取出的数据在队列中已经存在返回 ifcurrent_urlinfetching: return print('fetching%s'%current_url) #如果不存在添加到集合当中 fetching.add(current_url) #从新放入的链接中继续获取链接 urls=yieldget_links_from_url(current_url) #将已经请求玩的url放入第二个集合 fetched.add(current_url) fornew_urlinurls: #OnlyfollowlinksbeneaththebaseURL #如果链接是以传入的url开始则放入队列 ifnew_url.startswith(base_url): yieldq.put(new_url) finally: #队列内数据减一 q.task_done() @gen.coroutine defworker(): whileTrue: #保证程序持续运行 yieldfetch_url() #将第一个url放入队列 q.put(base_url) #Startworkers,thenwaitfortheworkqueuetobeempty. for_inrange(concurrency): #启动对应数量的worker worker() #等待队列数据处理完成 yieldq.join(timeout=timedelta(seconds=300)) #如果两个集合不相等抛出异常 assertfetching==fetched #打印执行时间 print('Donein%dseconds,fetched%sURLs.'%( time.time()-start,len(fetched))) if__name__=='__main__': io_loop=ioloop.IOLoop.current() io_loop.run_sync(main)
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。