学习Web Scraping with Python时遇到的BFS的问题?

发布于 2022-09-02 10:08:49 字数 3382 浏览 17 评论 0

请教一个问题,今天在学习Web Scraping with Python这本书时,书P128页上为了解决Six Degrees of Wikipedia,对爬下来储存在MySQL中的数据作了搜索。
数据用了两个表记录,分别是:

pages:

+---------+--------------+------+-----+-------------------+----------------+
| Field   | Type         | Null | Key | Default           | Extra          |
+---------+--------------+------+-----+-------------------+----------------+
| id      | int(11)      | NO   | PRI | NULL              | auto_increment |
| url     | varchar(255) | NO   |     | NULL              |                |
| created | timestamp    | NO   |     | CURRENT_TIMESTAMP |                |
+---------+--------------+------+-----+-------------------+----------------+

links:

+------------+-----------+------+-----+-------------------+----------------+
| Field      | Type      | Null | Key | Default           | Extra          |
+------------+-----------+------+-----+-------------------+----------------+
| id         | int(11)   | NO   | PRI | NULL              | auto_increment |
| fromPageID | int(11)   | YES  |     | NULL              |                |
| toPageID   | int(11)   | YES  |     | NULL              |                |
| created    | timestamp | NO   |     | CURRENT_TIMESTAMP |                |
+------------+-----------+------+-----+-------------------+----------------+

搜索的算法如下:

from urllib.request import urlopen
from bs4 import BeautifulSoup
import pymysql

conn = pymysql.connect(host = '127.0.0.1', user = 'root', passwd = 'pai433832',
        db = 'mysql', charset = 'utf8')
cur = conn.cursor()
cur.execute("USE wikipedia")

class SolutionFound(RuntimeError):
    def __init__(self, message):
        self.message = message

def getLinks(fromPageId):
    cur.execute("SELECT toPageId FROM links WHERE fromPageID = %s",
            (fromPageId))
    if cur.rowcount == 0:
        return None
    else:
        return [x[0] for x in cur.fetchall()]

def constructDict(currentPageId):
    links = getLinks(currentPageId)
    if links:
        return dict(zip(links, [{}] * len(links)))
    return {}

# The link tree may either be empty or contain multiple links
def searchDepth(targetPageId, currentPageId, linkTree, depth):
#    print(str(depth) + '\t' + str(currentPageId))        # debug
    if depth == 0:
        # Stop recursing and return, regardless
        return linkTree
    if not linkTree:
        linkTree = constructDict(currentPageId)
        if not linkTree:
            # No links found. Cannot continue at this node
            return {}
    if targetPageId in linkTree.keys():
        print("TARGET " + str(targetPageId) + " FOUND!")
        raise SolutionFound("PAGE: " + str(currentPageId))

    for branchKey, branchValue in linkTree.items():
        try:
            # Recurse here to continue building the tree
            linkTree[branchKey] = searchDepth(targetPageId, branchKey,
                    branchValue, depth - 1)
        except SolutionFound as e:
            print(e.message)
            raise SolutionFound("PAGE: " + str(currentPageId))
    return linkTree

try:
    searchDepth(14000, 1, {}, 4)
    print("No solution found")
except SolutionFound as e:
    print(e.message)

作者表示此处用了广度优先搜索,然而我觉得当在递归调用 searchDepth 函数时,使用的必然是深度优先,因此上述代码事实上是不是的确并非广度优先搜索而是深度优先搜索?然而对于这种情况是不是的确是广度优先搜索更好?如果原文的代码不是广度优先,那么广度优先应当如何处理呢?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

东走西顾 2022-09-09 10:08:49

代码确实是深度优先搜索(dfs)。

如果要改成广度优先搜索(bfs)的话,就用一个队列来维护待访问的url列表,每次从队列首部取url访问,然后把新提取出来的url集合添加到队列的尾部。

深度优先搜索跟广度优先搜索没有必然的优劣之分。如果目标位于层数比较小的地方,bfs可以很快找到解,如果目标所处的层次很深,bfs需要扩展很多节点,dfs反倒是有可能很快找到解。

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文