数据采集第一次作业
学号:102402135
姓名:王伟浩
课程:数据采集与融合技术
作业链接:第一次作业
作业①:
undefined 要求:用requests和BeautifulSoup库方法定向爬取给定网址的数据,屏幕打印爬取的大学排名信息。
一.实验
1. 代码设计思路
本程序使用 requests 获取目标网页,再利用 BeautifulSoup 解析 HTML,通过 CSS 选择器定位大学排名表格,提取排名、学校名称、省市、学校类型和总分,最后按照表格形式输出结果。
2. 可能遇到的问题
爬取过程中主要需要注意网页编码和 HTML 结构问题。中文网页如果编码设置不正确可能出现乱码,同时网页结构发生变化也可能导致选择器无法正确获取数据,因此程序对网页编码和数据列数进行了处理。
3.关键代码分析
response = requests.get(
url,
headers=headers
)
(1)发送网页请求: 使用 requests.get() 向目标网址发送 GET 请求,并设置 User-Agent 请求头模拟浏览器访问。获取网页后设置 UTF-8 编码,保证中文内容能够正常解析。
soup = BeautifulSoup(
response.text,
"html.parser"
)
(2)解析网页内容: 使用 BeautifulSoup 对获取到的 HTML 源代码进行解析,并指定 html.parser 作为解析器,为后续查找网页中的排名数据做准备。
rows = soup.select(
"tbody tr"
)
(3)定位排名表格: 使用 CSS 选择器 tbody tr 定位大学排名表格中的数据行,每个 tr 对应一条大学排名信息。
for row in rows:
cols = row.find_all("td")
if len(cols) >= 5:
rank = cols[0].text.strip()
name = cols[1].text.strip()
province = cols[2].text.strip()
category = cols[3].text.strip()
score = cols[4].text.strip()
(4)遍历并提取大学信息: 遍历所有排名数据行,通过 find_all("td") 获取当前行中的各个单元格,再按照网页中的字段顺序提取排名、学校名称、省市、学校类型和总分。strip() 用于清除文本前后的空格和换行。
print(
"{:<8}{:<15}{:<10}{:<10}{:<10}"
.format(
rank,
name,
province,
category,
score
)
)
(5)格式化输出结果: 使用 format() 设置各字段的显示宽度,将提取到的大学信息按照统一格式输出到终端,方便查看最终的爬取结果。
完整代码:
import requests from bs4 import BeautifulSoup目标网址
url = "http://www.shanghairanking.cn/rankings/bcur/2020"
设置请求头,模拟浏览器访问
headers = {
"User-Agent": "Mozilla/5.0"
}def get_university_rank():
# 发送请求
response = requests.get(
url,
headers=headers
)设置网页编码
response.encoding = "utf-8"
创建 BeautifulSoup 对象
soup = BeautifulSoup(
response.text,
"html.parser"
)查找排名表格中的所有行
rows = soup.select("tbody tr")
输出表头
print("=" * 75)
print(
"{:<8}{:<18}{:<12}{:<12}{:<10}".format(
"排名",
"学校名称",
"省市",
"学校类型",
"总分"
)
)
print("=" * 75)遍历学校信息
for row in rows:
cols = row.find_all("td")if len(cols) >= 5:
获取排名
rank = cols[0].get_text(
" ",
strip=True
)获取学校中文名称
找到学校名称所在的标签
name_tag = cols[1].find(
"span",
class_="name-cn"
)if name_tag:
name = name_tag.get_text(
strip=True
)
else:
# 如果网页结构发生变化,
# 则只取第一个文本内容
name = cols[1].get_text(
" ",
strip=True
).split(" ")[0]获取省市信息
province_text = cols[2].get_text(
" ",
strip=True
)删除办学标签
province = province_text
for tag in [
"双一流",
"985",
"211"
]:
province = province.replace(
tag,
""
)province = province.strip()
获取学校类型
category = cols[3].get_text(
" ",
strip=True
)获取总分
score = cols[4].get_text(
" ",
strip=True
)输出学校信息
print(
"{:<8}{:<18}{:<12}{:<12}{:<10}".format(
rank,
name,
province,
category,
score
)
)if name == "main":
get_university_rank()
运行结果:

二.心得体会
通过本次实验,我熟悉了使用 requests 获取网页以及使用 BeautifulSoup 解析网页的基本方法。通过实际爬取大学排名数据,我了解到网络爬虫不仅需要发送网页请求,还需要根据网页的 HTML 结构准确定位和提取目标数据。
作业②:
undefined 要求:用requests和re库方法设计某个商城(自已选择)商品比价定向爬虫,爬取该商城,以关键词“书包”搜索页面的数据,爬取商品名称和价格。此实验使用当当网
一.实验
1. 代码设计思路
本程序选择当当网作为爬取对象,使用 requests 库获取“书包”关键词的商品搜索页面,再利用 re 库通过正则表达式提取商品名称和价格信息。程序对爬取到的商品进行去重,并将结果在屏幕上按照序号、价格和商品名的形式输出,同时保存到文本文件中。
2. 可能遇到的问题
爬取过程中主要需要注意网页编码、商品 HTML 结构以及商品重复问题。由于网页内容包含中文,因此需要正确设置网页编码;同时通过正则表达式匹配商品名称和价格时,需要根据网页实际结构设计匹配规则,最后对商品名称进行去重,避免重复数据影响结果。
3.关键代码分析
# (1)设置关键词和爬取数量
KEYWORD = "书包"
MAX_COUNT = 60
http = urllib3.PoolManager()
headers = {
"User-Agent": (
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/155.0.0.0 Safari/537.36"
),
"Referer": "https://www.dangdang.com/"
}
(1)设置爬取参数: 设置搜索关键词为“书包”,最多获取 60 条商品信息,同时设置请求头模拟浏览器访问,减少网页拒绝请求的情况。
# (2)生成搜索页面地址并获取网页
keyword = quote(KEYWORD)
url = (
"https://search.dangdang.com/"
"?key=" + keyword +
"&act=input"
"&page_index=" + str(page)
)
response = http.request(
"GET",
url,
headers=headers,
timeout=10.0
)
(2)获取搜索页面: 使用 quote() 对中文关键词进行 URL 编码,然后根据关键词和页码生成当当网搜索页面地址,通过 GET 请求获取网页内容。
# (3)设置网页编码并获取 HTML 内容
if response.status != 200:
return ""
html = response.data.decode(
"gbk",
errors="ignore"
)
return html
(3)处理网页内容: 判断服务器返回的状态码是否为 200,确认网页正常获取后,将网页内容按照 GBK 编码进行解码,得到可以进行正则表达式匹配的 HTML 文本。
# (4)使用正则表达式定位商品
li_pattern = re.compile(
r'<li\s+ddt-pit="[^"]+"\s+class="[^"]*"\s+id="[^"]*"\s*>'
r'(.*?)'
r'</li>',
re.S
)
items = li_pattern.findall(html)
(4)定位商品信息: 使用正则表达式查找网页中的商品 li 标签,将每一个商品的 HTML 内容提取出来,为后续获取商品名称和价格做准备。
# (5)提取商品价格和名称
price_match = re.search(
r'<span\s+class="price_n"\s*>\s*'
r'¥?\s*([\d.]+)'
r'\s*</span>',
item,
re.S
)
name_match = re.search(
r'<p\s+class="name"\s+name="title"[^>]*>'
r'\s*<a[^>]*>'
r'(.*?)'
r'</a>',
item,
re.S
)
(5)提取商品信息: 分别通过正则表达式匹配商品价格和商品名称,其中价格从 price_n 标签中提取,商品名称从商品名称对应的 a 标签中提取。
# (6)清理商品名称并保存数据
name = re.sub(
r'<[^>]+>',
'',
name
)
name = re.sub(
r'\s+',
' ',
name
)
name = name.strip()
products.append(
{
"name": name,
"price": price
}
)
(6)处理并保存商品数据: 去除商品名称中的 HTML 标签以及多余的空格和换行,然后将商品名称和价格保存到列表中,方便后续统一输出。
# (7)去除重复商品
for product in products:
duplicate = False
for old_product in all_products:
if old_product["name"] == product["name"]:
duplicate = True
break
if not duplicate:
all_products.append(product)
(7)商品去重: 遍历已经获取的商品信息,通过比较商品名称判断当前商品是否已经存在,只有不存在重复商品时才将其加入最终结果列表。
# (8)输出商品名称和价格
for i, product in enumerate(all_products, 1):
print(
"{:<5} {:<55} {:>12}".format(
i,
product["name"],
"¥" + product["price"]
)
)
(8)格式化输出: 使用 enumerate() 为商品添加序号,再利用 format() 将序号、商品名称和价格按照固定格式输出到屏幕,形成清晰的商品信息表格。
完整代码:
import requests
import re
from urllib.parse import quote============================================================
当当网“书包”商品比价定向爬虫
使用:requests + re
最多爬取:60项
============================================================
KEYWORD = "书包"
MAX_COUNT = 60headers = {
"User-Agent": (
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/155.0.0.0 Safari/537.36"
),
"Referer": "https://www.dangdang.com/"
}def get_page(page):
"""
获取当当网搜索结果页面
"""keyword = quote(KEYWORD)
url = (
"https://search.dangdang.com/"
"?key=" + keyword +
"&act=input"
"&page_index=" + str(page)
)try:
# 使用 requests 发送 GET 请求
response = requests.get(
url,
headers=headers,
timeout=10
)print("正在访问:", url)
print("状态码:", response.status_code)
print("网页长度:", len(response.content))if response.status_code != 200:
return ""当当网页使用 GBK 编码
html = response.content.decode(
"gbk",
errors="ignore"
)return html
except Exception as e:
print("访问页面失败:", e)
return ""def parse_products(html):
"""
使用正则表达式提取商品名称和价格
"""products = []
========================================================
第一步:找到商品列表
========================================================
li_pattern = re.compile(
r'<li\s+ddt-pit="["]+"\s+class="["]"\s+id="[^"]"\s>'
r'(.?)'
r'',
re.S
)items = li_pattern.findall(html)
for item in items:
----------------------------------------------------
提取商品价格
----------------------------------------------------
price_match = re.search(
r'<span\s+class="price_n"\s>\s'
r'¥?\s([\d.]+)'
r'\s',
item,
re.S
)if not price_match:
continueprice = price_match.group(1).strip()
----------------------------------------------------
提取商品名称
----------------------------------------------------
name_match = re.search(
r'<p\s+class="name"\s+name="title"[^>]>'
r'\s<a[^>]>'
r'(.?)'
r'',
item,
re.S
)if not name_match:
continuename = name_match.group(1)
删除 HTML 标签
name = re.sub(
r'<[^>]+>',
'',
name
)清理多余空格和换行
name = re.sub(
r'\s+',
' ',
name
)name = name.strip()
if name:
products.append(
{
"name": name,
"price": price
}
)return products
============================================================
主程序
============================================================
print("=" * 80)
print(" 当当网“书包”商品比价定向爬虫")
print("=" * 80)print("关键词:", KEYWORD)
print("最多爬取:", MAX_COUNT, "项")
print()all_products = []
最多检查10页
for page in range(1, 11):
达到60项后停止
if len(all_products) >= MAX_COUNT:
breakprint("-" * 80)
print("正在爬取第", page, "页")html = get_page(page)
if not html:
print("网页获取失败")
continueproducts = parse_products(html)
print("本页解析到:", len(products), "项")
if len(products) == 0:
print("本页没有解析到商品,停止爬取。")
break--------------------------------------------------------
添加商品,并进行去重
--------------------------------------------------------
for product in products:
duplicate = False
for old_product in all_products:
if old_product["name"] == product["name"]:
duplicate = True
breakif not duplicate:
all_products.append(product)if len(all_products) >= MAX_COUNT:
break============================================================
输出结果
============================================================
print()
print("=" * 90)
print(" 爬取结果")
print("=" * 90)按照作业要求输出:
序号、价格、商品名
print(
"{:<8} {:<15} {}".format(
"序号",
"价格",
"商品名"
)
)print("-" * 90)
for i, product in enumerate(all_products, 1):
name = product["name"]
终端显示时限制商品名称长度
if len(name) > 55:
name = name[:55] + "..."print(
"{:<8} {:<15} {}".format(
i,
product["price"],
name
)
)print("-" * 90)
print(
"实际爬取商品数量:",
len(all_products)
)print("=" * 90)
============================================================
保存结果
============================================================
with open(
"dangdang_shubao.txt",
"w",
encoding="utf-8"
) as f:f.write("当当网“书包”商品爬取结果\n")
f.write("=" * 80 + "\n")for i, product in enumerate(all_products, 1):
f.write(
"{}. {} ¥{}\n".format(
i,
product["name"],
product["price"]
)
)print()
print("结果已经保存到:dangdang_shubao.txt")

二.心得体会
通过本次实验,我熟悉了使用 requests 获取商城网页以及使用 re 正则表达式提取网页数据的方法。通过实际爬取当当网“书包”商品信息,我进一步了解了如何根据网页结构设计正则表达式,并对爬取到的数据进行清理、去重和保存。通过本次实践,我对商品信息定向爬取的基本流程有了更加直观的认识。
作业③:
undefined 要求:爬取一个 给定网站 或者自选网页的所有JPEG、JPG或PNG格式图片文件
一.实验
1. 代码设计思路
本程序以福州大学新闻网页面作为爬取对象,使用 requests 获取网页 HTML 内容,再利用 BeautifulSoup 查找页面中的图片标签,获取图片文件地址。程序判断图片格式后发送请求下载图片,并统一保存到指定文件夹中。
2. 可能遇到的问题
爬取过程中主要需要注意图片地址可能使用相对路径,以及网页中可能存在不同格式的图片。程序需要将相对地址转换为完整 URL,并根据图片扩展名筛选 JPEG、JPG 和 PNG 格式,避免下载其他无关文件。
3.关键代码分析
# (1)获取目标网页
response = requests.get(
url,
headers=headers
)
response.encoding = response.apparent_encoding
soup = BeautifulSoup(
response.text,
"html.parser"
)
(1)获取并解析网页: 使用 requests.get() 获取目标网页内容,根据网页实际编码设置响应编码,再使用 BeautifulSoup 对 HTML 页面进行解析。
# (2)查找网页中的图片标签
images = soup.find_all("img")
(2)查找图片: 使用 find_all("img") 查找网页中的所有图片标签,从而获取页面中的图片资源。
# (3)获取图片地址
src = img.get("src")
if not src:
continue
img_url = urljoin(
url,
src
)
(3)获取图片地址: 从 img 标签中获取 src 属性。如果图片没有地址则跳过,并使用 urljoin() 将相对图片地址转换成完整的图片 URL。
# (4)筛选指定格式的图片
if not re.search(
r"\.(jpg|jpeg|png)(\?.*)?$",
img_url,
re.I
):
continue
(4)筛选图片格式: 使用正则表达式判断图片 URL 是否以 .jpg、.jpeg 或 .png 结尾,只保留符合实验要求的图片格式。
# (5)下载并保存图片
image_response = requests.get(
img_url,
headers=headers,
timeout=10
)
if image_response.status_code == 200:
with open(
save_path,
"wb"
) as f:
f.write(image_response.content)
(5)下载图片: 对筛选出的图片地址再次发送请求,获取图片二进制数据,并使用 open() 以二进制写入方式保存到指定文件夹中。
完整代码:
import os import re import requests from urllib.parse import urljoin============================================================
网页图片爬虫
功能:爬取网页中的 JPEG、JPG、PNG 图片并保存到文件夹
============================================================
目标网页
URL = "https://news.fzu.edu.cn/yxfd.htm"
图片保存目录
SAVE_DIR = "images"
设置请求头,模拟浏览器访问
HEADERS = {
"User-Agent": (
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/155.0.0.0 Safari/537.36"
)
}def get_page():
"""
获取目标网页的 HTML 源代码
"""try:
response = requests.get(
URL,
headers=HEADERS,
timeout=10
)print("正在访问:", URL)
print("状态码:", response.status_code)
print("网页长度:", len(response.content))if response.status_code != 200:
print("网页访问失败")
return ""根据网页实际编码设置
response.encoding = response.apparent_encoding
return response.text
except Exception as e:
print("网页访问失败:", e)
return ""def get_image_urls(html):
"""
使用正则表达式提取网页中的图片地址
"""查找 img 标签中的 src 属性
pattern = re.compile(
r'<img[^>]+src="'["']',
re.I
)image_urls = pattern.findall(html)
将相对地址转换为完整 URL
full_urls = []
for image_url in image_urls:
full_url = urljoin(
URL,
image_url
)只保留 JPEG、JPG、PNG 图片
if re.search(
r'.(jpg|jpeg|png)(?:?.*)?$',
full_url,
re.I
):
if full_url not in full_urls:
full_urls.append(full_url)return full_urls
def download_images(image_urls):
"""
下载图片并保存到本地 images 文件夹
"""创建保存目录
os.makedirs(
SAVE_DIR,
exist_ok=True
)success_count = 0
print()
print("=" * 70)
print("开始下载图片")
print("=" * 70)for index, image_url in enumerate(
image_urls,
1
):try:
response = requests.get(
image_url,
headers=HEADERS,
timeout=10
)if response.status_code != 200:
print(
"[失败]",
index,
image_url
)
continue从 URL 中获取文件扩展名
extension_match = re.search(
r'.(jpg|jpeg|png)(?:?.*)?$',
image_url,
re.I
)if extension_match:
extension = "." + extension_match.group(1).lower()
else:
extension = ".jpg"使用序号作为文件名,避免原文件名重复
filename = "image_{:03d}{}".format(
index,
extension
)filepath = os.path.join(
SAVE_DIR,
filename
)保存图片
with open(
filepath,
"wb"
) as f:
f.write(response.content)success_count += 1
print(
"[成功]",
index,
"->",
filename
)except Exception as e:
print(
"[失败]",
index,
"->",
e
)return success_count
def main():
"""
主程序
"""print("=" * 70)
print(" 网页图片爬取程序")
print("=" * 70)获取网页源代码
html = get_page()
if not html:
return提取图片地址
image_urls = get_image_urls(html)
print()
print("网页中找到 JPEG/JPG/PNG 图片:",
len(image_urls),
"张")if len(image_urls) == 0:
print("没有找到符合要求的图片")
return下载图片
success_count = download_images(
image_urls
)print()
print("=" * 70)
print("图片爬取完成")
print("=" * 70)
print("发现图片数量:", len(image_urls))
print("成功下载数量:", success_count)
print("保存文件夹:", SAVE_DIR)
print("=" * 70)if name == "main":
main()


二.心得体会
通过本次实验,我熟悉了网页图片资源的获取和保存方法,了解了如何从 HTML 页面中查找 img 标签并提取图片地址。在实践过程中,我也认识到网页中的图片地址不一定都是完整 URL,需要对相对路径进行处理,同时还需要根据文件扩展名筛选目标图片。最终程序能够将网页中的 JPEG、JPG 和 PNG 图片保存到指定文件夹,加深了我对网页资源爬取过程的理解。
作业总结
通过本次作业,我完成了大学排名、商城商品和网页图片三类数据的采集,进一步熟悉了 requests、BeautifulSoup 和正则表达式的使用。实验过程中也遇到了网页编码、数据定位和图片路径等问题,通过实际调试让我更加了解了网页数据采集的基本流程。
整体来看,本次作业让我掌握了从网页获取数据到解析、筛选和保存的基本方法,也提高了自己分析网页结构和解决爬虫运行问题的能力。

浙公网安备 33010602011771号