数据采集第1次作业

数据采集第一次作业博客

一、作业①

1.1 实验:爬取 2020 软科中国大学排名

目标网址:http://www.shanghairanking.cn/rankings/bcur/2020
分析网页结构:
屏幕截图 2026-10-12 200758
思路:用 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()

运行结果:
屏幕截图 2026-10-10 092210

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

分析网页:
屏幕截图 2026-10-12 200640

思路:用 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">&yen;([\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()

运行结果:

image

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
分析网页:
屏幕截图 2026-10-12 200603

思路:

  1. 用 requests.get() 拿到页面 HTML;
  2. 用 BeautifulSoup 的 find\_all("img") 遍历所有 <img> 标签;
  3. 过滤出后缀是 .jpg / .jpeg / .png 的图片;
  4. 用 urljoin() 把相对路径拼成绝对 URL,用 set() 去重;
  5. 逐张 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()

运行结果:
image

image

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 文件夹。
通过这道题,我进一步加深了对于爬取图片、视频这类数据的理解。

posted @ 2026-10-15 22:44  WQWa  阅读(2)  评论(0)    收藏  举报