数据采集第1次作业
数据采集第一次作业博客
一、作业①
1.1 实验:爬取 2020 软科中国大学排名
目标网址:http://www.shanghairanking.cn/rankings/bcur/2020
分析网页结构:

思路:用 requests.get() 请求页面 → 用 BeautifulSoup 解析 HTML → 通过 soup.select("tbody tr") 选中表格每一行 → 再从每一行里用 select() 抠出排名、学校名称、省市、类型、总分。
代码:
import requests
from bs4 import BeautifulSoup
# 目标网址
url = "http://www.shanghairanking.cn/rankings/bcur/2020"
# 请求头
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"
}
def get_schools():
"""请求软科 2020 排名页面,返回每一行学校对应的 BeautifulSoup 节点列表。"""
# 1. 发起 GET 请求
response = requests.get(url, headers=headers)
# 2. 按 utf-8 解码 HTML
html = response.content.decode("utf-8")
# 3. 用 lxml 解析成 BeautifulSoup 对象
soup = BeautifulSoup(html, "lxml")
# 4. 选中表格 tbody 下的所有 <tr> 行
schools = soup.select("tbody tr")
return schools
def parse_school_row(row):
"""从一行 <tr> 里选出 (排名, 学校名, 省市, 类型, 总分)。"""
rank = row.select("div[class*='ranking']")[0].text.strip() # 排名
name = row.select("span[class='name-cn']")[0].text.strip() # 校名
tds = row.select("td")
city = tds[2].text.strip() # 省市
kind = tds[3].text.strip() # 学校类型
score = tds[4].text.strip() # 总分
return rank, name, city, kind, score
def main():
"""主函数,打印软科 2020 排名。"""
schools = get_schools()
# 打印表头
print(f"{'排名':<6}{'学校名称':<14}{'省市':<8}{'类型':<8}{'总分':>8}")
print("-" * 50)
# 逐行打印
for row in schools:
rank, name, city, kind, score = parse_school_row(row)
print(f"{rank:<6}{name:<14}{city:<8}{kind:<8}{score:>8}")
if __name__ == "__main__":
main()
运行结果:

1.2 作业心得
这道题用的是标准的爬虫流程:发请求 → 解码 HTML → 提取字段。
先确定爬取的url,用requests库发送get请求,返回response,再对内容进行encode解码,获取网页的html。解析html用的是bs4库,根据html页面里的结构分析要爬取的内容的位置,这道题中,用soup.select("tbody tr")可以获得各大学的信息,最后再进一步提取所需要的信息并输出。
通过这道题我理解了 BeautifulSoup 的一般过程:先选大容器,再选子节点,最后取文本。
二、作业②
2.1 "书包" 商品比价爬虫
目标网站:https://search.dangdang.com/?key=%CA%E9%B0%FC&act=input&page_index=1
分析网页:

思路:用 F12 观察每个商品块的 HTML 结构,发现商品名在 <p class="name"><a title="..."> 里,价格在 <span class="price\_n">¥xx</span> 里。用一条正则同时捕获这两个字段,避免分两次匹配导致错位。
代码:
import re
import requests
def get_page(page_index):
"""抓取当当搜索结果页的 HTML 源码"""
# 目标网址
url = "https://search.dangdang.com/?key=%CA%E9%B0%FC&act=input&page_index={page_index}"
# 请求头
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/154.0.0.0 Safari/537.36 Edg/154.0.0.0"
}
# 发起 GET 请求
response = requests.get(url, headers=headers)
# 按解码 HTML
html = response.content.decode("gbk")
return html
def parse_goods(html):
"""从 HTML 里用正则选出 (商品名, 价格) 列表。"""
pattern = re.compile(
r'<p class="name"[^>]*?>.*?<a[^>]*?title="([^"]+)"[^>]*>'
r'.*?<span class="price_n">¥([\d.]+)</span>',
re.S,)
goods = pattern.findall(html)
# 去掉商品名首尾空白
return [(name.strip(), price) for name, price in goods]
def main():
"""主函数,打印当当搜索结果页的商品名和价格。"""
print(f"{'序号':<4}{'价格':>8} 商品名")
print("-" * 60)
idx = 1
#选择要爬取页面的范围
for page in range(1, 3):
html = get_page(page)
for name, price in parse_goods(html):
print(f"{idx:<4}{price:>8} {name}")
idx += 1
if __name__ == "__main__":
main()
运行结果:

2.2 作业心得
这道题用的流程是:发请求 → 解码 HTML → 用正则提取字段。
先确定当当网的搜索 url,把关键词 "书包" 按 GBK 编码拼到 url 里,用 requests.get 请求,返回 response。解析部分是用正则。商品名在 <a title="..."> 里,价格在 <span class="price_n">¥数字</span> 里。用正则表达式把商品名和价格两个组抓出来,最后把抓到的 (商品名,价格) 元组循环打印,加上序号即可。
通过这道题我理解了 "抓包 + 分析 HTML 结构 + 写正则"的流程,加深了对re正则的理解
三、作业③
3.1 爬取一个给定网页网页的所有JPEG、JPG或PNG格式图片文件
目标网页:https://news.fzu.edu.cn/yxfd.htm
分析网页:

思路:
- 用
requests.get()拿到页面 HTML; - 用
BeautifulSoup的find\_all("img")遍历所有<img>标签; - 过滤出后缀是
.jpg / .jpeg / .png的图片; - 用
urljoin()把相对路径拼成绝对 URL,用set()去重; - 逐张
requests.get()拿到二进制内容,用"wb"模式写进本地./images/文件夹。
import os
from urllib.parse import urljoin
import requests
from bs4 import BeautifulSoup
# 目标网页
url = "https://news.fzu.edu.cn/yxfd.htm"
# 请求头
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/154.0.0.0 Safari/537.36 Edg/154.0.0.0"
}
# 图片保存目录
SAVE_DIR = "./images"
def get_page(url):
"""请求网页并返回 BeautifulSoup 对象。"""
response = requests.get(url, headers=headers)
html = response.content.decode("utf-8")
return html
def collect_image_urls(html, base_url):
"""从页面里收集所有 jpg/jpeg/png 图片的绝对 URL,自动去重。"""
# 只下载这三种后缀的图片
IMG_EXT = (".jpg", ".jpeg", ".png")
soup = BeautifulSoup(html, "lxml")
urls = []
#去重,避免重复下载
seen = set()
for img in soup.find_all("img"):
src = img.get("src", "")
if not src:
continue
# 去掉 ?e=.png 这种 query 再判断后缀
lower = src.lower().split("?")[0]
if not lower.endswith(IMG_EXT):
continue
abs_url = urljoin(base_url, src)
if abs_url in seen:
continue
seen.add(abs_url)
urls.append(abs_url)
return urls
def main():
"""主流程:建目录 抓页面 收集图片 URL 逐张下载。"""
# 1. 建保存目录
os.makedirs(SAVE_DIR, exist_ok=True)
# 2. 抓列表页
html = get_page(url)
# 3. 收集所有图片 URL
image_urls = collect_image_urls(html, url)
# 4. 逐张下载
for img_url in image_urls:
# 发起 GET 请求
response = requests.get(img_url, headers=headers)
# 保存图片
with open(SAVE_DIR+"/"+img_url.split("?")[0].split("/")[-1], "wb") as f:
f.write(response.content)
print(f"已保存 {img_url.split("?")[0].split("/")[-1]}")
if __name__ == "__main__":
main()
运行结果:


3.2 作业心得
这道题的流程是:发请求拿 HTML → 解析出所有 img 标签 → 过滤后缀 → 拼绝对路径 → 逐张下载二进制写文件。
先确定目标 url,用 requests.get 请求并 decode 成字符串,再交给 BeautifulSoup 解析。解析部分用 soup.find_all("img")遍历页面上所有图片标签,对每个 src 用 endswith((".jpg",".jpeg",".png")) 过滤出题目要求的三种格式。这里要注意 src 可能带 ?e=.png 这种 query,要先 split("?")[0] 再判断后缀。因为页面里的 src 是相对路径(比如 images/logo.png),不能直接请求,要用 urljoin(base_url, src) 拼成完整 URL。最后逐张 requests.get 图片 url,拿到 response.content,用 open(path, "wb") 二进制模式写进本地 images 文件夹。
通过这道题,我进一步加深了对于爬取图片、视频这类数据的理解。

浙公网安备 33010602011771号