【梨视频下载案例】

【一】前提:代理池搭建

【1】引入

  • 代理池是一种用于获取可用代理服务器的工具,可以帮助用户在发送请求时隐藏真实IP地址并提高访问稳定性。
  • 开源的代理池核心原理:https://github.com/jhao104/proxy_pool
    • 1 使用爬虫技术,爬取网上免费的代理
    • 2 爬完回来做验证,如果能用,存到redis中
  • 启动调度程序,爬代理,验证,存到redis中
    • python proxyPool.py schedule

步骤1:选择合适的开源软件

  • 首先,我们需要选择一款适合搭建代理池的开源软件。
  • 目前市面上有很多可供选择的软件,比如Scrapy、ProxyPool等。
  • 根据自己的需求和技术能力,选择一款稳定可靠的软件进行搭建。

步骤2:安装依赖和配置环境

  • 根据所选软件的官方文档,安装相关依赖并配置环境。
  • 通常情况下,您需要安装Python以及相应的库和模块。

步骤3:编写代理池程序

根据软件的要求,编写代理池程序。程序主要包括以下几个部分:

  • 代理获取:从免费代理网站或付费代理提供商获取代理IP,并进行有效性验证。
  • 代理存储:将有效的代理IP存储在数据库或其他存储介质中,以供后续使用。
  • 代理检测与维护:定时检测已存储的代理IP的有效性,并根据需要进行维护,如删除无效的代理IP。

步骤4:运行代理池程序

  • 确认程序编写完成后,通过命令行或脚本运行代理池程序。
  • 程序会自动获取、存储和维护代理IP。

步骤5:从代理池中随机取出代理发起请求

  • 在需要使用代理的场景下,可以从代理池中随机选择一个可用的代理IP,并将其添加到请求头中。
  • 示例代码如下:
import random
import requests

def get_random_proxy():
    # 从数据库或其他存储介质中获取代理池中的代理IP列表
    proxy_list = ['ip1:port1', 'ip2:port2', 'ip3:port3', ...]
    
    # 随机选择一个代理IP
    random_proxy = random.choice(proxy_list)
    
    return random_proxy

def send_request(url):
    # 获取随机代理IP
    proxy = get_random_proxy()
    
    # 设置代理参数
    proxies = {
        'http': 'http://' + proxy,
        'https': 'https://' + proxy
    }
    
    try:
        # 发起请求
        response = requests.get(url, proxies=proxies, timeout=10)
        
        # 处理响应数据
        # ...
        
    except Exception as e:
        # 请求异常处理
        # ...

# 示例调用
url = "http://example.com"
send_request(url)
  • 通过以上步骤,您就可以搭建一个代理池,并从中随机选择代理IP发送请求。
  • 记得定期更新和维护代理池,以确保代理IP的有效性和可用性。

【2】拉取第三方镜像

  • pycharm
    • Git
    • Clone
    • Git from version control

https://github.com/jhao104/proxy_pool

【3】搭建虚拟环境

mkvirtualenv -p python39 proxypool

【4】安装依赖

pip install -r requirements.txt

【5】更新配置

# setting.py 为项目配置文件

# 配置API服务

HOST = "0.0.0.0"               # IP
PORT = 5000                    # 监听端口


# 配置数据库
# Redis数据库
DB_CONN = 'redis://127.0.0.1:8888/2'


# 配置 ProxyFetcher

PROXY_FETCHER = [
    "freeProxy01",      # 这里是启用的代理抓取方法名,所有fetch方法位于fetcher/proxyFetcher.py
    "freeProxy02",
    # ....
]

# 代理验证目标网站
HTTP_URL = "http://httpbin.org"

HTTPS_URL = "https://www.qq.com"

【6】启动项目

  • 如果已经具备运行条件, 可用通过proxyPool.py启动。
  • 程序分为: schedule 调度程序 和 server Api服务

(1)启动调度程序

  • 启动调度程序,爬代理,验证,存到redis中
python proxyPool.py schedule

(2)启动webApi服务

  • 使用flask启动服务,对外开放了几个接口,向某个接口发请求,就能随机获取一个代理
python proxyPool.py server

【7】使用

(1)Api

api method Description params
/ GET api介绍 None
/get GET 随机获取一个代理 可选参数: ?type=https 过滤支持https的代理
/pop GET 获取并删除一个代理 可选参数: ?type=https 过滤支持https的代理
/all GET 获取所有代理 可选参数: ?type=https 过滤支持https的代理
/count GET 查看代理数量 None
/delete GET 删除代理 ?proxy=host:ip

【二】主代码

# -*-coding: Utf-8 -*-
# @File : 03练习爬取视频网站 .py
# author: Chimengmeng
# blog_url : https://www.cnblogs.com/dream-ze/
# Time:2023/8/18
import multiprocessing
import os
import re
import threading
import time
from concurrent.futures import ThreadPoolExecutor, wait
from fake_useragent import UserAgent

import requests


class Crawl_Li_Video():
    def __init__(self, n):
        self.headers = {
            "User-Agent": UserAgent().random,
        }
        self.proxy = self.test_proxy()
        self.page = n

    def get_proxy(self):
        return requests.get("http://127.0.0.1:5010/get/").json()

    def delete_proxy(self, proxy):
        requests.get("http://127.0.0.1:5010/delete/?proxy={}".format(proxy))

    def test_proxy(self):
        retry_count = 5
        proxy_get = self.get_proxy().get("proxy")
        proxy = {
            "http": proxy_get,
        }
        try:
            response = requests.get('https://www.baidu.com/', proxies=proxy)
            if response.status_code == 200:
                print("温馨提示::>> 代理测试完成!可以使用!")
                return proxy
            else:
                self.delete_proxy(proxy_get)
                print("温馨提示::>> 代理测试失败!正在重启!")
                self.test_proxy()
        except Exception as e:
            self.delete_proxy(proxy_get)
            print('程序错误:>>>', e)

    def get_now_urls(self):
        # 24
        tag_url_list = []
        for i in range(self.page):
            tag_url = f'https://www.pearvideo.com/category_loading.jsp?reqType=5&categoryId=1&start={24 * i}'
            tag_url_list.append(tag_url)
        # https://www.pearvideo.com/video_1007601

        result_urls_dict = {}
        count = 0
        for tag_url in tag_url_list:
            count += 1
            try:
                response = requests.get(url=tag_url, headers=self.headers, proxies=self.proxy)
            except Exception as e:
                self.proxy = self.test_proxy()
                print(e)
                continue
            response.encoding = 'utf8'
            page_text = response.text
            re_url = r'<a href="(.*?)" class="vervideo-lilink actplay">'
            re_title = r'<div class="vervideo-title">(.*?)</div>'
            re_url = re.compile(re_url)
            re_title = re.compile(re_title)
            # print(page_text)
            detail_url_list = re.findall(re_url, page_text)
            detail_url_title = re.findall(re_title, page_text)
            pairs = zip(detail_url_list, detail_url_title)
            result_dict = {key: value for key, value in pairs}
            result_urls_dict[(count)] = result_dict
        return self.get_download_url_list(result_urls_dict)

    def get_download_url_list(self, result_urls_dict):
        download_urls_dict = {}
        for i in range(1, len(result_urls_dict) + 1):
            detail_dict = {}
            for video_id, title in result_urls_dict.get(i).items():

                # video_1467342
                now_page_url = 'https://www.pearvideo.com/' + video_id

                self.headers['Referer'] = now_page_url
                now_page_url = f'https://www.pearvideo.com/videoStatus.jsp?contId={video_id.split("_")[-1]}'

                try:
                    response = requests.get(url=now_page_url, headers=self.headers, proxies=self.proxy)
                except Exception as e:
                    self.proxy = self.test_proxy()
                    print('请求下载链接出错:>>>', e)
                    continue
                # 当前视频地址
                # https://www.pearvideo.com/video_1463575
                # 返回视频地址
                # https://www.pearvideo.com/videoStatus.jsp?contId=1463575&mrd=0.5277998673469977
                # 返回假视频地址
                # "https://video.pearvideo.com/mp4/adshort/20181026/ 1692351221819 -13126761 _adpkg-ad_hd.mp4"
                # 返回真视频地址
                # https://video.pearvideo.com/mp4/adshort/20181026/ cont-1463575 -13126761 _adpkg-ad_hd.mp4
                response.encoding = 'utf8'
                data_dict = response.json()
                fake_url = data_dict['videoInfo']['videos']['srcUrl']
                rale_url = fake_url.replace(fake_url.split('/')[-1].split('-')[0], f'cont-{video_id.split("_")[-1]}')
                detail_dict[title] = rale_url
            download_urls_dict[i] = detail_dict
        return download_urls_dict

    def download_mp4(self, page_number, download_url_dict):
        for video_title, video_url in download_url_dict.items():
            try:
                response = requests.get(url=video_url, headers=self.headers, proxies=self.proxy)
            except Exception as e:
                self.proxy = self.test_proxy()
                print(f'请求视频 {video_url} <---> {video_title} 数据出错:>>>')
                print(f'错误原因:>>> {e}')
                print('---------------')
                continue
            file_name = os.path.join(os.path.dirname(__file__), f'第{page_number}页视频')
            if not os.path.exists(file_name):
                os.mkdir(file_name)
            file_path = os.path.join(file_name, video_title + '.mp4')
            try:
                with open(file_path, 'wb') as fp:
                    for line in response.iter_content():
                        fp.write(line)
                print(f'当前第 {page_number} 页视频 {video_title} 下载完成 !')
            except Exception as e:
                print('下载发生错误:>>>', e)
                continue

    def main_ThreadPoolExecutor(self):
        download_urls_dict = self.get_now_urls()
        pool = ThreadPoolExecutor(max_workers=5)
        task_list = []
        for page_number, download_url_dict in download_urls_dict.items():
            task = pool.submit(self.download_mp4, page_number, download_url_dict)
            task_list.append(task)
        wait(task_list)
        pool.shutdown()  # 阻塞等待

    def main_Thread(self):
        download_urls_dict = self.get_now_urls()
        task_list = []
        for page_number, download_url_dict in download_urls_dict.items():
            task = threading.Thread(target=self.download_mp4, args=(page_number, download_url_dict))
            task.start()
            task_list.append(task)
        for task in task_list:
            task.join()

    def main_multiprocessing(self):
        download_urls_dict = self.get_now_urls()
        task_list = []
        for page_number, download_url_dict in download_urls_dict.items():
            task = multiprocessing.Process(target=self.download_mp4, args=(page_number, download_url_dict))
            task.start()
            task_list.append(task)

        for task in task_list:
            task.join()


if __name__ == '__main__':
    start = time.time()
    crawl = Crawl_Li_Video(10)
    # crawl.main_ThreadPoolExecutor()
    # crawl.main_Thread()
    crawl.main_multiprocessing()
    print(f'总耗时:>>{time.time() - start} s')
posted @ 2023-08-22 09:13  Chimengmeng  阅读(25)  评论(0编辑  收藏  举报
/* */