过年啦,千万别让外甥闲着!我用Cursor爬了100份卷子:“你还敢打游戏?

文摘   2025-01-23 13:08   广东  

过年回家,是合家欢聚的热闹时刻。可我的外甥,放假依然在家“葛优躺”

不是打游戏就是看动漫,什么学习?通通抛到九霄云外。

看得我这个沉迷AI编程的舅舅,脑袋都快冒烟了!你说将来谁给我端碗饭呀?没辙,我只能使出杀手锏——自己写个小爬虫,抓一堆卷子回来让他“开卷有益”!

话不多说,一切为了年后的“少儿不宜”——我外甥的快乐寒假,现在马上进入正题!

一、脑洞大开:我要写个小爬虫

我先跟我的得力 AI 伙伴——Cursor 商量了一下需求:

1.我需要一个爬虫脚本,从某个试卷网站批量下载试卷。

2.下载的文件还是 .rar 压缩包,解压后只需要其中的 .doc 文件。

3.最好支持多线程下载,以便能在我家网速还行的时候迅速搞定。

4.最后自动把 .rar 删了,省得占地方。

5.没啥特别复杂的容错需求,但也要跑得稳。

Cursor 秒回我一个“稳得一匹”的多线程爬虫思路,而且还贴心地给了下载、解压、删除一条龙服务的示例。完美,我先在本地跑起来看看!

二、搬砖现场:我的爬虫代码 Cursor 给出的思路非常清晰,我又稍微改动了一下(主要是加了点自己的注释和打印语句,毕竟我得知道下载到哪了),然后就得到了下面这段终极解决方案:

import concurrent.futures
import os
import threading
from concurrent.futures import ThreadPoolExecutor

import rarfile
import requests
from bs4 import BeautifulSoup


def download(url, category, level, name):
    path = category + "/" + level + "/" + name + ".rar"
    dir_name = os.path.dirname(path)
    os.makedirs(dir_name, exist_ok=True)
    res = requests.get(domain + url, headers=dic)
    with open(path, "wb") as f:
        f.write(res.content)
        f.flush()
        print(f'线程:{threading.current_thread().name} 下载完成:{path}')
    # 解压
    extract_rar(path, category + "/" + level)
    # 自动删除rar
    os.remove(path)


def extract_rar(file_path, extract_path):
    with rarfile.RarFile(file_path) as rf:
        for member in rf.infolist():
            if not member.filename.endswith('.doc'):
                continue
            rf.extract(member.filename, extract_path)


def getPageList(page_index):
    page_url = f"a/sjyw4/list_109_{page_index}.html"
    root = requests.get(domain + page_url, headers=dic)
    root.encoding = "gb2312"
    root_html = BeautifulSoup(root.text, "html.parser")
    tr_list = root_html.find("div", class_="listbox").find("table").find_all("tr")
    for index, tr in enumerate(tr_list):
        if index == 0 or (tr.text.find(".doc") == -1):
            continue
        tds = tr.find_all("td")
        name = tds[0].text
        suffix = tds[1].text
        level = tds[2].text
        category = tds[3].text
        child_url = domain + tds[0].find("a").get("href")
        child_html = BeautifulSoup(requests.get(child_url, headers=dic).text, "html.parser")
        a = child_html.find("div", class_="content").find_next("a")
        down_url = a.get("href")
        print(f'开始下载:{category}-{level}-{name}{suffix} url: {domain}{down_url}')
        task = pool.submit(download, down_url, category, level, name)
        task_list.append(task)


if __name__ == '__main__':
    domain = "https://www.shijuan1.com/"
    dic = {
        "User-Agent""Mozilla/5.0 (Windows NT 10.0; WOW64; rv:68.0) Gecko/20100101 Firefox/68.0"
    }
    # 创建线程池
    pool = ThreadPoolExecutor(5)
    task_list = []

    # 遍历10页,下载
    for page in range(1, 10):
        getPageList(page)

    # 等待所有任务完成
    concurrent.futures.wait(task_list, return_when='ALL_COMPLETED')
    pool.shutdown()
    print("所有任务完成,共下载{}个文件", len(task_list))
    

代码亮点

1.多线程下载:

ThreadPoolExecutor(5) 预设了 5 个线程,让下载像子弹一样飞快。

2.RAR 解压 + 清理:

写完一个 extract_rar() 就把 .rar 解压,再把多余的压缩包删干净。

3.批量爬:

for page in range(1, 10): 我这里选了 1~9 页,总共要批量下载。

三、与 Cursor 的斗智斗勇:代码优化过程

我最初是打算写一堆 requests 请求再手动解压,但 Cursor 一语点醒梦中人:“请用多线程与自动解压!”

  • 我之前用 Python 自带的 zipfile,结果发现我下到的是 .rar 格式文件,Cursor 贴心地提醒说:“你可以用 pip install rarfile 嘛。”

  • 然后又顺带安利我 ThreadPoolExecutor,让整个下载效率直接飞起。

整个过程可谓火花四溅,Cursor 不仅安抚了我的懒癌,还帮我排查了编码问题,比如网站的 root.encoding = "gb2312",非常中国特色。要是没这行,怕是中文会变成火星文吧!

四、实践出真知:再买个打印机!

搞定代码后,我立刻:

1.买了一台打印机 2.下载了100套试卷 3.打印装订好

准备在大年初一的时候,亲手交给我亲爱的外甥。毕竟谁说程序员就不会关心教育下一代呢?只是我们的方式...可能比较特别😏

五、总结

  • 编程真的离不开AI助手了。Cursor不仅帮我生成代码,还能智能优化、提供建议

  • 多线程果然是提升效率的利器,下载速度提升了好几倍

  • 最重要的是 - 我终于有"教育资源"了

过年嘛,干活和快乐都要两手抓!希望大家看到这里,能体会到我这位苦口婆心的舅舅的良苦用心……

好了,撒花!祝大家新年快乐!记得早点写好爬虫,让你家孩子也能随时开卷!

PS: 各位读者朋友如果也想要这个代码,可以在评论区留言。不过我建议谨慎使用,毕竟...过年还是要让孩子们适当放松的嘛!


顶尖架构师栈
大厂架构师,专注科技资讯,AI前沿信息,日常分享技术干货,程序员副业,职场三两事。
 最新文章