异步Python爬虫:实战某视频网站凡人修仙传 (附完整代码) ✨

异步Python爬虫:实战某视频网站凡人修仙传 (附完整代码) 🚀✨

在这篇充满魔法的教程中,我们将一起探索如何使用Python的异步编程特性,以闪电般的速度从网络上爬取并下载资源。想象一下,我们将如何轻松地从网站上捕获视频文件,并将它们异步下载到我们的宝库中。准备好了吗?让我们开始这场冒险吧!🧙‍♂️🔮

开始之前 📚🔧

在我们跳入代码的海洋之前,请确保你的Python环境中已经安装了以下神奇的工具:

  • aiohttp:闪电般发送HTTP请求的法杖。
  • aiofiles:异步操作文件的魔法书。
  • lxml:解析HTML的神秘卷轴。
  • asyncio:控制时间流速的时光轮。

如果在安装aiotqdm(一个展示进度的魔镜)时遇到难题,不用担心!我们可以选择其他方式来观察进度,或者干脆让这部分保持神秘。🔍💡

爬虫逻辑解析 🕵️‍♂️📖

我们的冒险之旅包含几个关键步骤:

  1. 获取列表页数据:首先,我们会向目标网站发出信号,请求列表页的内容。
  2. 解析列表页数据:在列表页的海洋中寻找通往详情页的航标。
  3. 获取详情页数据:通过异步飞毯访问每个详情页,获取它们的秘密。
  4. 解析详情页数据:在详情页中找到隐藏的视频文件URL。
  5. 异步下载视频文件:像空中的燕子一样,轻盈快速地下载每个视频文件,并将它们安全带回家。

代码实现 🧑‍💻📝

我们的代码像一本古老的魔法书,里面记载了召唤异步爬虫的咒语:

# 异步获取详情页数据
async def parse_detail_data(session, url):
    # 在这里,我们将揭开详情页的秘密...

# 异步下载视频文件
async def download_ts_file(session, ts_url, ts_sequence, buffer_dict):
    # 使用异步飞毯,将视频文件一片片地带回家...

# 主函数
async def main(url):
    # 用你的法杖触碰这段代码,启动整个魔法仪式...

完整代码

"""
http://www.gxychina.com/
http://www.gxychina.com/chi/69.html 凡人修仙传列表
http://www.gxychina.com/na/69-1-85.html 凡人修仙传第一章 1-85
ERROR: Could not find a version that satisfies the requirement aiotqdm (from versions: none)
ERROR: No matching distribution found for aiotqdm 找不到满足aiotqdm要求的版本(来自版本:none)错误:未找到aioqdm的匹配分发

"""
import aiofiles
import aiohttp
import asyncio
import requests
from lxml import etree
import os
import time
import pprint
import re
from tqdm import tqdm

# 域名
prefix_url = "http://www.gxychina.com"

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36"
}


# 获取列表页数据
def get_list_data(url):
    requests_get = requests.get(url=url, headers=headers)
    requests_get.encoding = "UTF-8"
    return requests_get.text


# 解析数据
def parse_list_data(html):
    etree_html = etree.HTML(html)
    playUrls = etree_html.xpath("//ul[@class='myui-content__list sort-list clearfix']/li/a/@href")
    return playUrls


# 获取剧名
def get_name(html):
    etree_html = etree.HTML(html)
    name = etree_html.xpath("//h1[@class='title text-fff']/text()")
    return name


# 获取标题名
def getTitles(html):
    etree_html = etree.HTML(html)
    Titles = etree_html.xpath("//ul[@class='myui-content__list sort-list clearfix']/li/a/@title")
    return Titles


# 获取详情页
async def parse_detail_data(session, url):
    async with session.get(url) as response:
        response.encoding = "UTF-8"
        text = await response.text()
        # 获页面中的m3u8地址
        search = re.search(';var now="(.*?)";var', text)
        return search


# 访问ts文件url拿到文件保存
async def get_ts_data(session, url):
    async with session.get(url) as response:
        response.encoding = "UTF-8"
        ts_data = await response.text()  # 加上圆括号来调用方法
        #   文本处理 从,开始 到#E结束
        ts_urls = re.findall(',\n(.*?)\n#E', ts_data, re.S)
        return ts_urls


def create_directory(directory_path):
    try:
        # 如果目录不存在,则创建它
        if not os.path.exists(directory_path):
            os.makedirs(directory_path)
            print(f"目录 '{directory_path}' 已创建。")
    except Exception as e:
        print(f"创建目录时发生错误: {e}")



async def download_ts_file(session, ts_url, ts_sequence, buffer_dict):
    async with session.get(ts_url) as response:
        response.encoding = "UTF-8"
        ts_data = await response.content.read()
        buffer_dict[ts_sequence] = ts_data



async def download_ts_data(session, ts_urls, name, title):
    path_name = name[0].strip()
    create_directory(path_name)
    file_path = f"./{path_name}/{title}.mp4"
    print("保存路径:", file_path, "开始下载 ts 文件")

    buffer_dict = {}
    async with aiofiles.open(file_path, mode="ab") as f:
        tasks = [asyncio.create_task(download_ts_file(session, ts_url, i, buffer_dict))
                 for i, ts_url in enumerate(ts_urls)]
        await asyncio.gather(*tasks)

        # 确保按正确的顺序写入文件
        for i in range(len(ts_urls)):
            await f.write(buffer_dict[i])

        print("所有下载任务已完成")


async def download_detail_data(session, url, title, name):
    detail_data = await parse_detail_data(session, url)
    m3u8 = detail_data.group(1)
    # https://new.1080pzy.co/20211029/Oil0h7pU/index.m3u8 这是详情页返回的m3u8地址
    # https://new.1080pzy.co/20211029/Oil0h7pU/1400kb/hls/index.m3u8 通过页面上关键字查找,发现ts文件来自这个接口
    # 处理获取ts的链接
    ts_url = m3u8.replace("index.m3u8", "1400kb/hls/index.m3u8")  # 这里的1400kb是固定的,不知道是什么意思 直接替换
    ts_data = await get_ts_data(session, ts_url)
    # 下载ts文件
    await download_ts_data(session, ts_data, name, title)


async def main(url):
    # 创建统一的session
    async with aiohttp.ClientSession() as session:
        # 获取列表页数据
        list_data = get_list_data(url)
        data = parse_list_data(list_data)
        name = get_name(list_data)
        titles = getTitles(list_data)
        tasks = []
        for url, title in zip(data, titles):
            play_url = prefix_url + url
            print(play_url)
            task = asyncio.create_task(download_detail_data(session, play_url, title, name))
            tasks.append(task)
            break  # 测试只下载一集
        await asyncio.wait(tasks)


if __name__ == '__main__':
    # 计时
    start_time = time.time()
    # url
    url = "http://www.gxychina.com/chi/69.html"
    # 然后在某个异步上下文中调用 main 函数
    asyncio.run(main(url))
    end_time = time.time()
    print(f"耗时:{end_time - start_time}")  # 60.40073251724243

结语 🌟💫

通过这篇充满魔力的教程,你现在已经掌握了如何使用Python的异步编程特性来提高爬虫的效率。不过记得,伟大的力量伴随着伟大的责任,使用这些技能时,请确保你的行为符合法律法规和道德准则。

免责声明 🛡️⚖️

本教程提供的信息和代码仅供学习和研究目的使用,不得用于任何非法用途。作者不对因使用本教程内容造成的任何直接或间接损失负责。


如果你喜欢这次冒险,请给我一颗星星作为鼓励吧!🌟 你的支持是我不断探索和分享更多魔法的动力。如果你有任何疑问或想要交流更多的魔法知识,欢迎留言讨论。直到下次冒险,保持好奇,继续探索!🚀📚

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值