数据采集第一次作业

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()

屏幕截图 2026-10-21 182418

心得体会

在这次实验中,我体会到了网页解析中“定位”的重要性。软科排名页面的数据存放在 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()

图片1

图片2

心得体会:选择当当网是因为它的搜索页是服务端直接渲染的,商品信息都在 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()

屏幕截图 2026-10-21 183913

屏幕截图 2026-10-21 183859

心得体会:这道题的关键在于筛选图片格式和处理相对路径。urljoin 能把页面中的相对链接拼成绝对链接,避免下载时出错。另外,保存图片要用 wb 二进制模式,否则文件会损坏。部分网站使用懒加载,图片真实地址可能放在 data-src 属性里,代码里做了兼容处理,可以提升下载成功率。

posted @ 2026-10-21 18:41  干的湿垃圾  阅读(9)  评论(0)    收藏  举报