淺談深度優先和廣度優先(scrapy-redis)
首先先談談深度優先和廣度優先的定義
深度優先搜尋演算法(英語:Depth-First-Search,DFS)是一種用於遍歷或搜尋樹或圖的演算法。沿著樹的深度遍歷樹的節點,儘可能深的搜尋樹的分支。當節點v的所在邊都己被探尋過,搜尋將回溯到發現節點v的那條邊的起始節點。這一過程一直進行到已發現從源節點可達的所有節點為止。如果還存在未被發現的節點,則選擇其中一個作為源節點並重復以上過程,整個程序反覆進行直到所有節點都被訪問為止。屬於盲目搜尋。
深度優先搜尋 | ||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
節點進行深度優先搜尋的順序 | ||||||||||||||
概況 |
||||||||||||||
|
廣度優先搜尋演算法(英語:Breadth-First-Search,縮寫為BFS),又譯作寬度優先搜尋,或橫向優先搜尋,是一種圖形搜尋演算法。簡單的說,BFS是從根節點開始,沿著樹的寬度遍歷樹的節點。如果所有節點均被訪問,則演算法中止。廣度優先搜尋的實現一般採用open-closed表。
廣度優先搜尋 | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
節點進行廣度優先搜尋的順序 |
||||||||||||
概況 | ||||||||||||
|
通俗的講:
深度優先:一個一個節點往下找,不找兄弟節點,每一個深度一個節點,先進去的後出來
廣度優先:橫向取值,一個節點有關聯其他的節點,一同被取出來,一個深度多個節點,先進去的先出來
在settings裡面的配置:
from scrapy_redis.queue import PriorityQueue,FifoQueue,LifoQueue
先進先出:廣度優先
SCHEDULER_QUEUE_CLASS='scrapy_redis.queue.FifoQueue'
後進先出:深度優先
SCHEDULER_QUEUE_CLASS='scrapy_redis.queue.LifoQueue'
優先順序佇列:
SCHEDULER_QUEUE_CLASS='scrapy_redis.queue.PriorityQueue'
優先順序佇列裡面也有深度優先和廣度優先:
requets.priority=1 廣度優先
requets.priority=1 深度優先
實現原理:
from scrapy_redis import queue
prio=1
depth = response.meta['depth'] + 1
requets.priority-=depth*self.prio
每一次迴圈,depth加1
同一個深度可以找到很多url(兄弟節點)
如果是1的話,廣度優先
廣度優先:
depth 優先順序
1 -1
1 -1
1 -1
2 -2
從深度為1的開始往下找,優先順序也越大
重點:深度越小,優先順序越小
def push(self, request):
"""Push a request"""
data = self._encode_request(request)
score = -request.priority##取反,注意
......
優先順序佇列:
放進佇列裡面:
反一下
1 1
1 1
1 1
2 2
......
print('這裡優先順序是',score)
print(request.meta.get('depth'))
# We don't use zadd method as the order of arguments change depending on
# whether the class is Redis or StrictRedis, and the option of using
# kwargs only accepts strings, not bytes.
self.server.execute_command('ZADD', self.key, score, data)
#按照分值來看
def pop(self, timeout=0):
"""
Pop a request
timeout not support in this queue class
"""
# use atomic range/remove using multi/exec
##開啟事物
pipe = self.server.pipeline()
pipe.multi()
##取第一個值出來,拿出一個刪除一個
pipe.zrange(self.key, 0, 0).zremrangebyrank(self.key, 0, 0)
results, count = pipe.execute()
if results:
return self._decode_request(results[0])
最終pop是按照這個優先順序來取值的,優先順序越小的越先被取出來,優先順序從小多大取值
總結:就是深度越小,優先順序越小,越先被取出來>>廣度優先(先進先出,橫向取值)
深度優先:
先進後出:一個一個節點的往下面執行
深度越大,優先順序越小,越先被pop出來
深度優先類似,就不多說了
....................