python scrapy框架详解_Python之Scrapy框架源码解析

from twisted.internet import reactor #事件循环(终止条件,所有的socket都已经移除)

from twisted.web.client import getPage #socket对象(如果下载完成,自动从时间循环中移除...)

from twisted.internet import defer #defer.Deferred 特殊的socket对象 (不会发请求,手动移除)

#自定义一个Request 类

classRequest(object):def __init__(self, url, callback):"""初始化接受url和callback回调函数

:param url: 请求的url

:param callback: 获取内容后的callback"""self.url=url

self.callback=callback#响应对象

classHttpResponse(object):def __init__(self, content, request):"""初始化相应内容

:param content: 下载 下来的响应的content

:param request: response对应的request"""

#响应的内容

self.content =content#响应的请求

self.request =request#response对应的request

self.url =request.url#将内容转换为文本

self.text = str(content, encoding='utf-8')classChoutiSpider(object):"""初始化顶一个小蜘蛛"""name= 'chouti'

#蜘蛛一开始的执行方法

defstart_requests(self):

start_url= ['http://www.baidu.com', 'http://www.bing.com', ]for url instart_url:yieldRequest(url, self.parse)#收到response后的解析函数

defparse(self, response):print(response) #response是下载的页面

yield Request('http://www.cnblogs.com', callback=self.parse)importqueue#这里是调度器

Q =queue.Queue()#定义了一个引擎类

classEngine(object):def __init__(self):#引擎关闭

self._close =None#最大的请求数

self.max = 5

#正在爬的请求

self.crawlling =[]#拿着相应的回调函数

defget_response_callback(self, content, request):""":param content: 响应的content

:param request: 响应对应的request

:return:"""

#一旦执行回调函数,就可以从调度中拿走这个请求

self.crawlling.remove(request)#将内容封装成 一个 HttpResponse对象

rep =HttpResponse(content, request)#调用请求时的回调函数,将封装的HttpResponse传递进去

result =request.callback(rep)importtypes#查看回调函数是否继续返回迭代器对象

ifisinstance(result, types.GeneratorType):#将回调函数 新的请求放到调度器

for req inresult:

Q.put(req)#从调度器取请求,执行,下载,并控制最大并发数

def_next_request(self):"""去取request对象,并发送请求

最大并发数限制

:return:"""

print(self.crawlling, Q.qsize())#如果调度器的长度为0,而且处于正在爬取的数目也为 0 ,那么就说明该关闭了

if Q.qsize() == 0 and len(self.crawlling) ==0:#直接调用 defer.Deferred().callback(None)就会关闭defer

self._close.callback(None)return

#如果正在爬取的数目超过了最大的并发限制,直接返回

if len(self.crawlling) >=self.max:return

#如果没有达到并发限制,就执行以下内容

while len(self.crawlling)

req = Q.get(block=False)#把拿到的请求放到 正在爬取的列表中

self.crawlling.append(req)#获取相应的页面

d = getPage(req.url.encode('utf-8'))#页面下载完成,get_response_callback,调用用户spider中定义的parse方法,并且将新请求添加到调度器

d.addCallback(self.get_response_callback, req)#未达到最大并发数,可以再去调度器中获取Request

#继续给d添加回调函数,这个回调函数可以是匿名函数

d.addCallback(lambda_: reactor.callLater(0, self._next_request))exceptException as e:print(e)return@defer.inlineCallbacksdefcrawl(self, spider):#将start_requests包含的生成器,初始Request对象添加到调度器

start_requests =iter(spider.start_requests())whileTrue:try:#拿到每个request,放到调度器中

request =next(start_requests)

Q.put( request)exceptStopIteration as e:break

#去调度器中取request,并发送请求

#self._next_request()

reactor.callLater(0, self._next_request)#初始化self._close

self._close =defer.Deferred()yieldself._close#初始化一个抽屉爬虫

spider =ChoutiSpider()

_active=set()#实例化一个引擎对象

engine =Engine()#引擎对象 调用 crawl方法,运行指定的spider

d =engine.crawl(spider)#将crawl方法放到set中

_active.add(d)#实例化一个DeferredList,将_active 内容放进去,返回一个defer.Deferred()对象,若defer.Deferred()被关闭,dd就为空

dd =defer.DeferredList(_active)#一旦dd里面为空,就调用reactor.stop()方法

dd.addBoth(lambdaa: reactor.stop())#让它run起来

reactor.run()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值