a525 发表于 2024-5-12 13:52

python爬虫,【好舅舅系列】二

本帖最后由 a525 于 2024-5-12 13:57 编辑

针对上一篇【五一放假篇】,完善了一下代码。喜欢的可以学习学习,仅个人使用,请勿用作商业用途,尊重版权(www.shijuan1.com)。
另外,五一奔波一千多公里,刚回家就给大外甥安排了几张试卷,看得出他是不情愿的,五月五号两张数学一张英语,做的直哭{:1_925:}怪我没跟他说不用一下子做完..... 可怜天下舅舅心,农村孩子不努力,以后连去工地搬砖,厂里面打螺丝都没人要....

再次,感谢第一试卷网免费的试卷!!!

优化内容:
1.增加菜单
2.自动切换分页
3.线程延迟
4.其他优化
需要安装的包:

pip install rarfile
pip install requests
pip install beautifulSoup4


上代码:
import concurrent.futures
import importlib
import os
import subprocess
import sys
import threading
import time
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 get_page_list(page_url):
    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.text
      suffix = tds.text
      level = tds.text
      category = tds.text
      child_url = domain + tds.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)

    # 返回下一页的url
    pages = root_html.find("div", class_="dede_pages").find("ul").find_all("li")
    stop = False
    for i in pages:
      if stop:
            return i.find("a").get("href")
      cls: list = i.get("class")
      if cls and "thisclass" in cls:
            stop = True
    return None


# 环境检测
def pip_install():
    print("正在检测安装依赖...")
    paks = ["rarfile", "requests", "beautifulsoup4"]
    name = ""
    try:
      for pak in paks:
            name = pak
            importlib.import_module(name)
    except ImportError:
      print(f"依赖未安装[{name}],开始安装 ========> pip install {name}")
      subprocess.check_call(["pip", "install", name])

    winrar: bool = os.path.exists("C:\\Windows\\UnRAR.exe")
    if not winrar:
      print("请安装winrar解压缩软件,并将UnRAR.exe复制到【C:\\Windows】目录.")
      sys.exit()
    print("依赖安装完成")


maps: dict = {}
menus: dict = {}


def request_menus():
    home = requests.get(domain, headers=dic)
    home.encoding = "gb2312"
    home_html = BeautifulSoup(home.text, "html.parser")
    uls = home_html.find("div", class_="linkbox").find_all("ul")
    num = 1
    for ul in uls:
      lis = ul.find_all("li")
      key = lis.find("font").text
      objs = []
      for i in range(1, len(lis)):
            a = lis.find("a").get("href")
            font = lis.find("a").text
            obj = {
                "num": num,
                "a": a,
                "font": font
            }
            maps = a
            objs.append(obj)
            num = num + 1
      menus = objs


def print_menus():
    print("数据来源:第一试卷网(www.shijuan1.com) 商务合作:shijuan2011@163.com 仅支持个人研究和学习,商用请联系官方授权.\n")
    for key, value in menus.items():
      text = ''
      for obj in value:
            text += f'({obj.get("num")}){obj.get("font")} '
      print(f'{key} : {text}')


def select_menus() -> str:
    if not menus:
      request_menus()

    print_menus()
    sc = input("请输入序号开始下载:\n")
    while not maps.get(sc):
      sc = input("输入错误,请重新输入:\n")

    return maps.get(sc)


if __name__ == '__main__':
    print("声明:本代码仅供学习研究使用,请勿用于商业用途,否则后果自负!")
    print("声明:本代码仅供学习研究使用,请勿用于商业用途,否则后果自负!")
    print("声明:本代码仅供学习研究使用,请勿用于商业用途,否则后果自负!")
    pip_install()
    domain = "https://www.shijuan1.com/"
    dic = {
      "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:68.0) Gecko/20100101 Firefox/68.0"
    }
    print("声明:本代码仅供学习研究使用,请勿用于商业用途,否则后果自负!")
    # 创建线程池
    pool = ThreadPoolExecutor(5)
    task_list = []
    # 打印菜单,等待输入
    url: str = select_menus()

    # 开始下载
    next_page = url + get_page_list(url)
    # 等待所有任务完成
    concurrent.futures.wait(task_list, return_when='ALL_COMPLETED')

    while next_page:
      print(f'开始下载下一页:{next_page}, 请稍等...')
      time.sleep(60)
      next_page = url + get_page_list(next_page)

    pool.shutdown()
    print("所有任务完成,共下载{}个文件", len(task_list))

    # 打印菜单
    select_menus()


效果图:







免责声明:
以上代码仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。


青春莫相随 发表于 2024-5-12 14:44

本帖最后由 青春莫相随 于 2024-5-12 14:46 编辑

五一的我已经下载使用了,试试这次的。没整自解压,下载后删除不需要的后自行解压也是可以的,这次要安装winrar软件了。我来试试效果。感谢楼主{:1_893:}

kingflyingwxg 发表于 2024-7-10 10:20

不错 不错

hhxx1983 发表于 2024-7-10 10:03

真好,谢谢楼主的奉献,真是好舅舅?孩子当时想咬你的心都有

stldhl 发表于 2024-6-23 20:00

学习学习

xuguoguo 发表于 2024-6-21 23:10

效果非常好,楼主是个神仙,你的大外甥一定会非常感谢你:lol

kingok2006 发表于 2024-6-21 18:55

这么不能用啊

hef0504 发表于 2024-6-19 10:30

好东西谢谢 !也是学习的机会

jackpots0 发表于 2024-6-10 15:41

谢谢分享!!

ytkkk 发表于 2024-6-7 10:20

楼主太牛了

那年281 发表于 2024-6-6 12:00

强烈建议出程序,伸手党跪谢
页: [1] 2 3 4 5 6
查看完整版本: python爬虫,【好舅舅系列】二