102302156 李子贤 数据采集第一次作业

作业1
用requests和BeautifulSoup库方法定向爬取给定网址(http://www.shanghairanking.cn/rankings/bcur/2020 )的数据,屏幕打印爬取的大学排名信息。

(1)代码和运行结果

点击查看代码
import urllib.request
from bs4 import BeautifulSoup

# 获取目标网页的HTML内容
def get_html(url):
    try:
        req = urllib.request.Request(url)
        response = urllib.request.urlopen(req)
        html = response.read().decode('utf-8')
        return html
    except Exception as e:
        print(f"获取网页失败:{e}")
        return None

# 解析HTML,提取大学排名数据
def parse_html(html):
    if html is None:
        return []
    # 初始化解析器并获取表格行数据
    soup = BeautifulSoup(html, 'html.parser')
    rows = soup.select('tr')  # 选择所有表格行
    rank_data = []

    for row in rows:
        # 提取排名
        rank_elem = row.select_one('div.ranking')
        if not rank_elem:
            continue
        rank_text = rank_elem.text.strip().replace(' ', '')
        if not rank_text.isdigit():
            continue

        # 提取学校名称
        name_elem = row.select_one('div.univname')
        if not name_elem:
            continue
        name = name_elem.text.strip().split('\n')[0].strip()

        # 提取省市、学校类型、总分(从表格单元格中获取)
        tds = row.select('td')
        if len(tds) < 5:
            continue
        province = tds[2].text.strip()
        school_type = tds[3].text.strip()
        score = tds[4].text.strip()

        # 收集数据
        rank_data.append([rank_text, name, province, school_type, score])
    return rank_data

# 格式化打印排名数据
def print_rank(data):
    if not data:
        print("没有获取到有效排名数据")
        return
    # 打印表头
    print(f"{'排名':<6}{'学校名称':<20}{'省市':<8}{'学校类型':<10}{'总分'}")
    for item in data:
        print(f"{item[0]:<6}{item[1]:<20}{item[2]:<8}{item[3]:<10}{item[4]}")

def main():
    url = "http://www.shanghairanking.cn/rankings/bcur/2020"
    html = get_html(url)
    if html:
        print("网页获取成功,开始解析...\n")
        rank_data = parse_html(html)
        print_rank(rank_data)
    else:
        print("网页获取失败,无法继续")

if __name__ == "__main__":
    main()

image

(2)心得体会

屏幕截图 2025-10-25 141624

从上图可以看出,我们需要提取的信息包含在表格的tbody中,我们只需要先提取每一个tr行

屏幕截图 2025-10-25 142123

再分别对每一个tr行提取相对应的td标签中的内容,即可得到我们想要的结果。
因此,我们得出爬取一个网页中的信息,必须要先知道我们所要爬取的内容的html结构,对症下药才可以得到我们想要的信息。

作业2
用requests和re库方法设计某个商城(自已选择)商品比价定向爬虫,爬取该商城,以关键词“书包”搜索页面的数据,爬取商品名称和价格。

(1)代码和运行结果

点击查看代码
import urllib3
import re

def crawl_dangdang_books(keyword, max_items=30):
    http = urllib3.PoolManager()
    # 设置请求头,模拟浏览器访问
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36"
    }

    all_names = []
    all_prices = []
    url = f"https://search.dangdang.com/?key={keyword}&page=1"

    try:
        # 发送GET请求,设置超时和重试机制
        response = http.request(
            'GET',
            url,
            headers=headers,
            timeout=10,
            retries=urllib3.Retry(3, backoff_factor=0.5)
        )
        # 解码网页内容
        html = response.data.decode('gbk', errors='ignore')

        # 提取商品名称:匹配含class="pic"的a标签中的title属性
        name_pattern = re.compile(r'<a\s+.*?class="pic".*?title="(.*?)".*?>',re.DOTALL | re.VERBOSE )
        names = name_pattern.findall(html)
        valid_names = [n for n in names if n.strip()]
        all_names.extend(valid_names[:max_items])

        # 提取价格:匹配class="price_n"的span标签中的数值(去除¥符号)
        price_pattern = re.compile(r'<span class="price_n">&yen;(.*?)</span>')
        prices = price_pattern.findall(html)
        valid_prices = [p for p in prices if p.strip()]
        all_prices.extend(valid_prices[:max_items])

        # 打印当前页数据提取统计
        print(f"第1页:名称{len(valid_names)}个,价格{len(valid_prices)}个,有效匹配{min(len(valid_names), len(valid_prices))}个")

    except Exception as e:
        print(f"爬取失败:{str(e)}")

    # 组合名称和价格为元组列表返回
    products = list(zip(all_names, all_prices))
    return products

if __name__ == "__main__":
    products = crawl_dangdang_books("书包")
    # 打印爬取结果
    if products:
        print(f"\n===== 爬取结果(共{len(products)}项) =====")
        for i, (name, price) in enumerate(products, 1):
            print(f"{i}. 名称:{name} | 价格:¥{price}")
    else:
        print("未爬取到有效商品数据")

image

(2)心得体会
我选择爬取的网站是当当网(https://search.dangdang.com/?key=书包&page=1)

image

由上图可以得到我们想要爬取的书包名称在class="pic"的a标签中的title属性,使用正确的正则表达式(r'<a\s+.?class="pic".?title="(.?)".?>')即可得到信息,在爬取时我发现如果只使用a标签下的title属性,会匹配到其他的信息,所以我们需要多添加一些约束条件,这样才可以精确的定位到我们想要的信息。

image

同理,我们查看价格的html标签,他存放在class="price_n"的span标签中,使用正确的正则表达式(r'¥(.*?)')即可得到信息。

作业3
爬取一个给定网页(https://news.fzu.edu.cn/yxfd.htm)或者自选网页的所有JPEG、JPG或PNG格式图片文件

(1)代码和运行结果

点击查看代码
import urllib.request
import re
import os

def main():
    # 目标网页 URL
    url = "https://news.fzu.edu.cn/info/1012/120223.htm"
    # 图片保存目录
    save_dir = "fzu_jpg_imgs"
    os.makedirs(save_dir, exist_ok=True)

    try:
        # 请求网页获取内容
        req = urllib.request.Request(url)
        with urllib.request.urlopen(req) as response:
            html = response.read().decode("utf-8")
    except Exception as e:
        print(f"获取网页内容失败:{e}")
        return

    # 正则匹配 <img> 标签中 src 属性为 .jpg 的链接
    img_pattern = r'<img[^>]*?src=["\'](.*?\.jpg)["\']'
    img_urls = re.findall(img_pattern, html)
    if not img_urls:
        print("未找到 .jpg 格式图片")
        return

    # 遍历图片链接并下载
    for i, img_url in enumerate(img_urls, 1):
        # 拼接完整绝对 URL
        full_img_url = urllib.parse.urljoin(url, img_url)
        # 提取图片文件名
        img_name = os.path.basename(full_img_url)
        save_path = os.path.join(save_dir, img_name)

        try:
            # 请求图片
            img_req = urllib.request.Request(full_img_url)
            with urllib.request.urlopen(img_req) as img_resp:
                with open(save_path, "wb") as f:
                    f.write(img_resp.read())
            print(f"[{i}/{len(img_urls)}] 成功下载:{img_name}")
        except Exception as e:
            print(f"[{i}/{len(img_urls)}] 下载失败 {full_img_url}:{e}")

if __name__ == "__main__":
    main()

image

image

(2)心得体会
我爬取的图片网站为(https://news.fzu.edu.cn/info/1012/120223.htm)

image

由html结构我们可以看出,图片的后缀为.jpg格式,所以我们先利用re正则表达式去匹配所有src属性为.jpg的标签,定位到我们想要的图片后,就要进行图片保存的操作
这是 “数据保存” 的核心步骤,针对每张图片做三件事:
1.处理链接:将网页中可能存在的 “相对路径” 转为可直接访问的 “绝对路径”;
2.定义路径:明确本地保存的位置和文件名,避免混乱;
3.下载保存:以二进制模式(图片是二进制文件)写入本地,同时捕获单张图片的下载异常(避免一张失败导致整体中断)。
由此可以得出下载图片的时候要注意路径等问题

posted @ 2025-10-25 15:54  helllo_x  阅读(0)  评论(0)    收藏  举报