news 2026/9/11 1:15:25

头歌实践教学平台:数据科学与大数据技术导论(二十一2)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
头歌实践教学平台:数据科学与大数据技术导论(二十一2)

二十一、数据采集实战

第2关:网站爬取策略

任务描述
本关任务:编写一个爬虫实现深度优先爬虫。

相关知识
主要介绍两种爬虫爬取策略:1. 深度优先爬虫; 2. 广度优先爬虫。

深度优先爬虫(一路到底)
在一个网页中,当一个超链被选择后,被链接的网页将执行深度优先搜索,即在搜索其余的超链结果之前必须先完整地搜索单独的一条链。深度优先搜索沿着网页上的超链走到不能再深入为止,然后返回到某一个网页,再继续选择该网页中的其他超链。当不再有其他超链可选择时,说明搜索已经结束。

示例:

爬取顺序为:1->2->4->8->5->3->6->7

广度优先爬虫(逐层爬取)
广度优先爬虫过程就是从一系列的种子节点开始,把这些网页中的“子节点” 提取出来,放入队列中依次进行抓取,被处理过的链接需要放入一张表中。每次新处理一个链接之前,需要查看这个链接是否已经存在于表中。如果存在,证明链接已经处理过, 跳过,不做处理,否则进行下一步处理。

示例:

爬取顺序为:1->2->3->4->5->6->7->8

编程要求
请仔细阅读右侧代码,结合相关知识,在 Begin-End 区域内进行代码补充,编写一个爬虫实现深度优先爬虫,爬取的网站为 www.baidu.com。

测试说明
平台会对你编写的代码进行测试:

下方预期输出随着网页的更新,中间的数据会有一定的变化。

预期输出:

Add the seeds url ['http://www.baidu.com'] to the unvisited url list
Pop out one url "http://www.baidu.com" from unvisited url list
Get 10 new links
Visited url count: 1
Visited deepth: 1
10 unvisited links:
Pop out one url "http://news.baidu.com" from unvisited url list
Get 52 new links
Visited url count: 2
Visited deepth: 2
Pop out one url "http://www.hao123.com" from unvisited url list
Get 311 new links
Visited url count: 3
Visited deepth: 2
Pop out one url "http://map.baidu.com" from unvisited url list
Get 0 new links
Visited url count: 4
Visited deepth: 2
Pop out one url "http://v.baidu.com" from unvisited url list
Get 566 new links
Visited url count: 5
Visited deepth: 2
Pop out one url "http://tieba.baidu.com" from unvisited url list
Get 21 new links
Visited url count: 6
Visited deepth: 2
Pop out one url "http://www.baidu.com/bdorz/login.gif?login&tpl=mn&u=http%3A%2F%2Fwww.baidu.com%2f%3fbdorz_come%3d1" from unvisited url list
Get 1 new links
Visited url count: 7
Visited deepth: 2
Pop out one url "http://home.baidu.com" from unvisited url list
Get 27 new links
Visited url count: 8
Visited deepth: 2
Pop out one url "http://ir.baidu.com" from unvisited url list
Get 22 new links
Visited url count: 9
Visited deepth: 2
Pop out one url "http://www.baidu.com/duty/" from unvisited url list
Get 1 new links
Visited url count: 10
Visited deepth: 2
Pop out one url "http://jianyi.baidu.com/" from unvisited url list
Get 4 new links
Visited url count: 11
Visited deepth: 2
2 unvisited links:
Pop out one url "http://baozhang.baidu.com/guarantee/" from unvisited url list
Get 0 new links
Visited url count: 12
Visited deepth: 3
Pop out one url "http://ir.baidu.com/phoenix.zhtml?c=188488&p=irol-irhome" from unvisited url list
Get 22 new links
Visited url count: 13
Visited deepth: 3
22 unvisited links:
注意:右侧预期输出为部分输出。

开始你的任务吧,祝你成功!

from bs4 import BeautifulSoup

import requests

import re

#自定义队列类

class linkQuence:

def __init__(self):

# 已访问的url集合

self.visted = []

# 待访问的url集合

self.unVisited = []

# 获取访问过的url队列

def getVisitedUrl(self):

return self.visted

# 获取未访问的url队列

def getUnvisitedUrl(self):

return self.unVisited

# 添加到访问过得url队列中

def addVisitedUrl(self, url):

self.visted.append(url)

# 移除访问过得url

def removeVisitedUrl(self, url):

self.visted.remove(url)

# 未访问过得url出队列 深度优先 pop() 后进先出,栈

def unVisitedUrlDeQuence(self):

try:

return self.unVisited.pop()

except:

return None

# 保证每个url只被访问一次

def addUnvisitedUrl(self, url):

if url != "" and url not in self.visted and url not in self.unVisited:

self.unVisited.insert(0, url)

# 获得已访问的url数目

def getVisitedUrlCount(self):

return len(self.visted)

# 获得未访问的url数目

def getUnvistedUrlCount(self):

return len(self.unVisited)

# 判断未访问的url队列是否为空

def unVisitedUrlsEnmpy(self):

return len(self.unVisited) == 0

class MyCrawler:

def __init__(self, seeds):

# 初始化当前抓取的深度

self.current_deepth = 1

# 使用种子初始化url队列

self.linkQuence = linkQuence()

if isinstance(seeds, str):

self.linkQuence.addUnvisitedUrl(seeds)

if isinstance(seeds, list):

for i in seeds:

self.linkQuence.addUnvisitedUrl(i)

print("Add the seeds url %s to the unvisited url list" % str(self.linkQuence.unVisited))

# 抓取过程主函数

def crawling(self, seeds, crawl_deepth):

# ********** Begin **********#

# 循环条件:抓取深度不超过crawl_deepth

while self.current_deepth <= crawl_deepth:

# 循环条件:待抓取的链接不空

while not self.linkQuence.unVisitedUrlsEnmpy():

# 队头url出队列 深度优先 pop

url = self.linkQuence.unVisitedUrlDeQuence()

print('Pop out one url "%s" from unvisited url list' % url)

# 获取超链接

new_links = self.getHyperLinks(url)

print(f"Get {len(new_links)} new links")

# 将url放入已访问的url中

self.linkQuence.addVisitedUrl(url)

print(f"Visited url count: {self.linkQuence.getVisitedUrlCount()}")

print(f"Visited deepth: {self.current_deepth}")

if self.linkQuence.getUnvistedUrlCount() > 0:

print(f"{self.linkQuence.getUnvistedUrlCount()} unvisited links:")

# 未访问的url入列

for link in new_links:

self.linkQuence.addUnvisitedUrl(link)

self.current_deepth += 1

# ********** End **********#

# 获取源码中得超链接

def getHyperLinks(self, url):

# ********** Begin **********#

links = []

source = self.getPageSource(url)

if source is None:

return links

soup = BeautifulSoup(source, "html.parser")

a_list = soup.find_all("a", href=True)

for a in a_list:

href = a['href']

# 简单处理http开头链接

if href.startswith("http"):

links.append(href)

return links

# ********** End **********#

# 获取网页源码

def getPageSource(self, url):

# ********** Begin **********#

headers = {

"User‑Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/100.0.0.0 Safari/537.36"

}

try:

resp = requests.get(url, headers=headers, timeout=3)

resp.encoding = resp.apparent_encoding

return resp.text

except Exception:

return None

# ********** End **********#

def main(seeds, crawl_deepth):

craw = MyCrawler(seeds)

craw.crawling(seeds, crawl_deepth)

if __name__ == '__main__':

main("http://www.baidu.com", 3)

有任何问题都可以随时关注私信!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/2 11:15:16

Byte Latent Transformer:字节熵动态切Patch,彻底告别分词器

【面试高频】扔掉分词器&#xff01;Byte Latent Transformer 用字节熵动态切 Patch 全解析如果你最近在准备大模型方向的面试&#xff0c;一定遇到过类似问题&#xff1a;“为什么大模型不直接用字符或字节训练&#xff1f;”、“BPE 词表会不会成为瓶颈&#xff1f;”、“如果…

作者头像 李华
网站建设 2026/9/2 21:52:57

AI时代网络安全:大模型应用的安全架构与落地实践

OpenAI、微软、谷歌等 116 家企业联合签署公开信&#xff0c;呼吁高度重视 AI 时代网络安全——这条消息在技术社区里并不只是新闻&#xff0c;它背后是一个工程判断&#xff1a;当大模型从演示工具进入生产系统&#xff0c;网络安全的边界、责任和风险模型都在发生变化。这封信…

作者头像 李华
网站建设 2026/9/11 1:15:18

Gemini 3 Pro 生成法线贴图:从原理到 Blender/Unity 接入指南

如果你做 3D 美术、技术美术&#xff08;TA&#xff09;或者游戏开发&#xff0c;这几天应该看到过这样一个说法&#xff1a;Gemini 3 Pro 可以生成 normal maps&#xff08;法线贴图&#xff09;。这件事值得单独拿出来聊&#xff0c;因为它和“画一张好看的图”完全不同。法线…

作者头像 李华
网站建设 2026/9/3 1:56:21

技术面试八股文:从背题到知识体系的进阶指南

“八股文”这个词&#xff0c;在程序员圈子里的热度&#xff0c;这几年一直居高不下。从“Java八股文”、“C八股文”到“嵌入式八股文”、“软件测试八股文”&#xff0c;再到“Kafka八股文为什么能支撑百万并发”&#xff0c;几乎每个技术方向都有自己的“面试题库”。很多人…

作者头像 李华
网站建设 2026/9/3 6:53:46

边缘语言模型记忆增强:SSM状态注入与结构化记忆实践

最近在边缘设备上调语言模型推理时&#xff0c;遇到一个很实际的问题&#xff1a;设备内存有限&#xff0c;模型不能像云端那样无限扩展上下文窗口。用户问过的问题&#xff0c;换个会话模型就忘了&#xff0c;每次都要把历史记录重新拼进 prompt&#xff0c;推理延迟成倍上涨。…

作者头像 李华
网站建设 2026/9/3 13:32:42

STM32WL设备在ChirpStack上失联:AU915信道掩码解析bug排查全过程

刚拿到客户工单的时候&#xff0c;我以为是又遇到了“自建ChirpStack不兼容STM32WL”的玄学问题。设备是STM32WL55JC&#xff0c;LoRaWAN MW 2.5.0 / MAC 1.0.4&#xff0c;工作在AU915频段&#xff0c;在TTN上验了两周一点事没有&#xff1b;搬到客户自建的ChirpStack上&#…

作者头像 李华