数据采集第一次作业
Python 爬虫基础实践作业:Requests 与解析库的应用
本次作业主要围绕 Python 网络爬虫的基础知识展开,分别使用了 requests 结合 BeautifulSoup、正则表达式 re 以及文件 I/O 操作,完成了数据抓取、数据提取和图片批量下载三个任务。以下是具体的实验过程与心得体会。
一、 作业1:定向爬取软科中国大学排名
1)实验过程
任务要求:使用 requests 和 BeautifulSoup 库方法定向爬取给定网址( https://www.shanghairanking.cn/rankings/bcur/2020 )的数据,屏幕打印爬取的大学排名信息。
实现代码:
import requests
from bs4 import BeautifulSoup
def crawl_university_ranking():
"""
爬取软科2020中国大学排名并打印。
"""
url = "https://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/124.0.0.0 Safari/537.36"
}
try:
response = requests.get(url, headers=headers, timeout=15)
response.raise_for_status()
response.encoding = response.apparent_encoding
# 使用BeautifulSoup解析HTML
soup = BeautifulSoup(response.text, "html.parser")
table = soup.find("table")
rows = table.find("tbody").find_all("tr")
print(f"{'排名':<6}{'学校名称':<12}{'省市':<8}{'学校类型':<8}{'总分':<8}")
print("-" * 55)
count = 0
for tr in rows:
tds = tr.find_all("td")
if len(tds) < 5:
continue
rank = tds[0].get_text(strip=True)
# 学校名称需定位到类名为 name-cn 的 span,避免混入英文名
name_tag = tds[1].find("span", class_="name-cn")
name = name_tag.get_text(strip=True) if name_tag else tds[1].get_text(strip=True)
province = tds[2].get_text(strip=True)
school_type = tds[3].get_text(strip=True)
score = tds[4].get_text(strip=True)
print(f"{rank:<6}{name:<12}{province:<8}{school_type:<8}{score:<8}")
count += 1
if count >= 10:
break
except Exception as e:
print(f"爬取失败: {e}")
if __name__ == "__main__":
crawl_university_ranking()

心得体会
在这次实验中,我体会到了网页解析中“定位”的重要性。软科排名页面的数据存放在 table 表格的 tbody 中,通过遍历 tr 和 td 就能提取内容。但在提取“学校名称”时我发现,直接获取 td 的文本会把英文名也一起抓下来,通过浏览器开发者工具(F12)审查元素发现,中文名被单独放在了 标签中。这让我认识到,在实际爬虫中,仅仅依赖基础标签定位往往不够,结合网页的 class 属性进行精细化定位,才能获取到干净、准确的数据。此外,设定 User-Agent 伪装成浏览器也是成功请求数据的关键一步。
二、作业2
undefined 要求:用requests和re库方法设计某个商城(自已选择)商品比价定向爬虫,爬取该商城,以关键词“书包”搜索页面的数据,爬取商品名称和价格。
实现代码:
import urllib3
import urllib.parse
import os
import threading
from bs4 import BeautifulSoup
STUDENT_ID = "072308214"
KEYWORD = "书包"
limit_images = int(STUDENT_ID[-3:])
if limit_images == 0:
limit_images = 10
page_num = int(STUDENT_ID[-1])
if page_num == 0:
page_num = 1
http = urllib3.PoolManager()
http.headers.update({
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
})
if not os.path.exists('images'):
os.makedirs('images')
def download_image(img_url, img_name, thread_id):
try:
response = http.request('GET', img_url)
with open(f"images/{img_name}.jpg", 'wb') as f:
f.write(response.data)
print(f"[线程 {thread_id}] 下载成功: {img_name}.jpg")
except Exception as e:
print(f"[线程 {thread_id}] 下载失败 {img_url}: {e}")
def main():
keyword_encode = urllib.parse.quote(KEYWORD.encode('gbk'))
url = f"http://search.dangdang.com/?key={keyword_encode}&act=input&page_index={page_num}"
print(f"正在请求第 {page_num} 页, 目标下载前 {limit_images} 张图片...")
response = http.request('GET', url)
html_content = response.data.decode('gbk', errors='ignore')
soup = BeautifulSoup(html_content, 'html.parser')
img_tags = soup.select('ul.bigimg li a img')
image_urls = []
for img in img_tags:
img_url = img.get('data-original') or img.get('src')
if img_url and img_url.startswith('//'):
img_url = 'http:' + img_url
if img_url and img_url not in image_urls:
image_urls.append(img_url)
if len(image_urls) >= limit_images:
break
print(f"页面分析完毕, 共找到 {len(image_urls)} 张符合条件的图片, 准备启动多线程下载...\n")
threads = []
max_threads = 5
for i, img_url in enumerate(image_urls):
img_name = f"{KEYWORD}_{page_num}page_{i + 1}"
t = threading.Thread(target=download_image, args=(img_url, img_name, f"T{i % max_threads + 1}"))
threads.append(t)
t.start()
if len(threads) >= max_threads:
for th in threads:
th.join()
threads = []
for t in threads:
t.join()
print("\n所有图片下载任务完成!")
if __name__ == '__main__':
main()


心得体会:选择当当网是因为它的搜索页是服务端直接渲染的,商品信息都在 HTML 源码里,适合练习正则表达式。需要注意的是,页面编码是 GBK,不手动指定 response.encoding = "gbk" 会导致中文乱码。另外,用正则提取商品名时,取 标签的 title 属性值,可以避开页面里的关键词高亮标签,避免提取到多余 HTML 标签。
三、作业3
undefined 要求:爬取一个给定网页( https://news.fzu.edu.cn/yxfd.htm )或者自选网页的所有JPEG、JPG或PNG格式图片文件
undefined 输出信息:将自选网页内的所有JPEG、JPG或PNG格式文件保存在一个文件夹中
import os
import requests
from bs4 import BeautifulSoup
from urllib.parse import urljoin
def download_images():
"""
爬取指定网页中的所有 JPEG、JPG、PNG 图片并保存到本地文件夹。
"""
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/120.0.0.0 Safari/537.36"
}
save_dir = "downloaded_images"
os.makedirs(save_dir, exist_ok=True)
try:
response = requests.get(url, headers=headers, timeout=15)
response.raise_for_status()
response.encoding = response.apparent_encoding
soup = BeautifulSoup(response.text, "html.parser")
img_tags = soup.find_all("img")
valid_exts = (".jpg", ".jpeg", ".png")
count = 0
for img in img_tags:
img_url = img.get("src") or img.get("data-src")
if not img_url:
continue
full_url = urljoin(url, img_url)
ext = os.path.splitext(full_url)[-1].lower()
if ext in valid_exts:
try:
img_data = requests.get(full_url, headers=headers, timeout=10).content
file_path = os.path.join(save_dir, f"image_{count}{ext}")
with open(file_path, "wb") as f:
f.write(img_data)
print(f"[✓] 下载成功: {full_url}")
count += 1
except Exception as e:
print(f"[✗] 下载失败: {full_url}, 原因: {e}")
print(f"共下载 {count} 张图片,保存至 {save_dir} 文件夹。")
except Exception as e:
print(f"爬取页面失败: {e}")
if __name__ == "__main__":
download_images()



浙公网安备 33010602011771号