前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Scrapy实战2:爬虫深度&&广度优先算法

Scrapy实战2:爬虫深度&&广度优先算法

作者头像
龙哥
发布2020-02-12 11:14:47
1.2K0
发布2020-02-12 11:14:47
举报
文章被收录于专栏:Python绿色通道

一、前言

以后尽量每天更新一篇,也是自己的一个学习打卡!加油!今天给大家分享的是,Python里深度/广度优先算法介绍及实现。

二、深度、广度优先算法简介

1.深度优先搜索(DepthFirstSearch)

深度优先搜索的主要特征就是,假设一个顶点有不少相邻顶点,当我们搜索到该顶点,我们对于它的相邻顶点并不是现在就对所有都进行搜索,而是对一个顶点继续往后搜索,直到某个顶点,他周围的相邻顶点都已经被访问过了,这时他就可以返回,对它来的那个顶点的其余顶点进行搜索。 深度优先搜索的实现可以利用递归很简单地实现。

2.广度优先搜索(BreadthFirstSearch)

广度优先搜索相对于深度优先搜索侧重点不一样,深度优先好比是一个人走迷宫,一次只能选定一条路走下去,而广度优先搜索好比是一次能够有任意多个人,一次就走到和一个顶点相连的所有未访问过的顶点,然后再从这些顶点出发,继续这个过程。

具体实现的时候我们使用先进先出队列来实现这个过程:

  1. 首先将起点加入队列,然后将其出队,把和起点相连的顶点加入队列,
  2. 将队首元素v出队并标记他
  3. 将和v相连的未标记的元素加入队列,然后继续执行步骤2直到队列为空

广度优先搜索的一个重要作用就是它能够找出最短路径,这个很好理解,因为广度优先搜索相当于每次从一个起点开始向所有可能的方向走一步,那么第一次到达目的地的这个路径一定是最短的,而到达了之后由于这个点已经被访问过而不会再被访问,这个路径就不会被更改了。

三、看代码,边学边敲边记深度优先、广度优先算法

1.遍历二叉树图形

遍历二叉树图形

2.深度优先、广度优先遍历模型
代码语言:javascript
复制
'''
date : 2018.7.29
author : 极简XksA
goal : 深度/广度优先算法
'''

# 深度优先: 根左右 遍历
# 广度优先: 层次遍历,一层一层遍历

# 深度优先: 根左右 遍历 (递归实现)
def depth_tree(tree_node):
    if tree_node is not None:
        print(tree_node._data)
        if tree_node._left is not None:
            return depth_tree(tree_node._left)  # 递归遍历
        if tree_node._right is not None:
            return depth_tree(tree_node._right)  # 递归遍历

# 广度优先: 层次遍历,一层一层遍历(队列实现)
def level_queue(root):
    if root is None:
        return
    my_queue = []
    node = root
    my_queue.append(node)  # 根结点入队列
    while my_queue:
        node = my_queue.pop() # 出队列
        print(node.elem)   # 访问结点
        if node.lchild is not None:
            my_queue.append(node.lchild)    # 入队列
        if node.rchild is not None:
            my_queue.append(node.rchild)    # 入队列
3.数据结构设计、遍历代码

方法一:列表法

代码语言:javascript
复制
# 树的数据结构设计
# 1.列表法
# 简述:列表里包含三个元素:根结点、左结点、右结点
my_Tree = [
    'D', # 根结点
    ['B',
     ['F',[],[]],
     ['G',['E',[],[]],[]]
     ],  # 左子树
    ['C',
     [],
     ['A',['H',[],[]],[]]
     ]   # 右子树
]

# 列表操作函数
# pop() 函数用于移除列表中的一个元素(默认最后一个元素),并且返回该元素的值。
# insert() 函数用于将指定对象插入列表的指定位置,没有返回值。

# 深度优先: 根左右 遍历 (递归实现)
def depth_tree(tree_node):
    if tree_node:
        print(tree_node[])
        # 访问左子树
        if tree_node[]:
            depth_tree(tree_node[])  # 递归遍历
        # 访问右子树
        if tree_node[]:
            depth_tree(tree_node[])  # 递归遍历        
depth_tree(my_Tree)
# result:
#            D B F G E C A H

# 广度优先: 层次遍历,一层一层遍历(队列实现)
def level_queue(root):
    if not root:
        return
    my_queue = []
    node = root
    my_queue.append(node)  # 根结点入队列
    while my_queue:
        node = my_queue.pop() # 出队列
        print(node[])   # 访问结点
        if node[]:
            my_queue.append(node[])    # 入队列
        if node[]:
            my_queue.append(node[])    # 入队列       
level_queue(my_Tree)
# result :
#           D B C F G A E H

方法二:构造类节点法

代码语言:javascript
复制
#2.构造类
# Tree类,类变量root 为根结点,为str类型
# 类变量right/left 为左右节点,为Tree型,默认为空
class Tree:
    root = ''
    right = None
    left = None
    # 初始化类
    def __init__(self,node):
        self.root = node

    def set_root(self,node):
        self.root = node

    def get_root(self):
        return self.root

# 初始化树
# 设置所有根结点
a = Tree('A')
b = Tree('B')
c = Tree('C')
d = Tree('D')
e = Tree('E')
f = Tree('F')
g = Tree('G')
h = Tree('H')
# 设置节点之间联系,生成树
a.left = h
b.left = f
b.right = g
c.right = a
d.left = b
d.right = c
g.left = e

# 深度优先: 根左右 遍历 (递归实现)
def depth_tree(tree_node):
    if tree_node is not None:
        print(tree_node.root)
        if tree_node.left is not None:
            depth_tree(tree_node.left)  # 递归遍历
        if tree_node.right is not None:
            depth_tree(tree_node.right)  # 递归遍历
depth_tree(d)  # 传入根节点
# result:
#            D B F G E C A H

# 广度优先: 层次遍历,一层一层遍历(队列实现)
def level_queue(root):
    if root is None:
        return
    my_queue = []
    node = root
    my_queue.append(node)  # 根结点入队列
    while my_queue:
        node = my_queue.pop() # 出队列
        print(node.root)   # 访问结点
        if node.left is not None:
            my_queue.append(node.left)    # 入队列
        if node.right is not None:
            my_queue.append(node.right)    # 入队列
level_queue(d)
# result :
#           D B C F G A E H

四、后言

可能大家会好奇,深度优先算法、广度优先算法对爬虫有什么用,不用好奇,慢慢后面就会懂得了。提前透露:几乎所有网站都有首页、XXX、XXX、XXX…在每个分页下,又有很多分页,这样所有url之间的联系实际上就可以比喻成一棵树,当我们想要系统爬取时,为了不重复爬取,对这颗树的遍历就尤为重要了,这里说到的深度优先、广度优先为最常用的遍历算法。

【完】

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-01-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Python绿色通道 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、前言
  • 二、深度、广度优先算法简介
    • 1.深度优先搜索(DepthFirstSearch)
      • 2.广度优先搜索(BreadthFirstSearch)
      • 三、看代码,边学边敲边记深度优先、广度优先算法
      • 四、后言
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档