python---根据日期排序下载like数大于一定量的Iwara视频 (2023.3.29)

1.提示:
使用需要安装bs4库,selenium库,fake_useragent库,pyautogui库,cv2库,undetected_chromedriver库,版本没什么要求,
同时需要安装相同版本的Chrome浏览器和驱动器,注意驱动器和浏览器不一样哦,
哦对了,还要自备梯子,不过某喵天天在Iwara打广告,你们应该不会看不到吧?
后面如果有时间的话我会做个使用教学视频发在b站的,顺便讲讲思路,应该会有时间吧?大概?

2.严肃警告

  1. 本程序仅可用作个人爱好,商业用途严禁!
  2. 请自觉遵守君子协定robots.txt
  3. 不要给Iwara过大的压力,每天以及同一时段的访问量请控制在一定程度内!
  4. 推荐在中国北京时间早上9:00到下午15:00点进行爬取,避开访问高峰期,不仅是为了大家都有的看,同时也是因为高峰期网站不稳定,爬取成功率可能较低(Iwara经常会崩溃大家也都知道,自然啥也爬不到…)

3.具体功能描述:
Iwara没有根据最新日期筛选like数大于一定量的视频的功能,每次都需要一页一页手翻来找近期大佬们的精品,太痛苦了,作为一个程序员我能忍?直接写个爬虫!

  • login函数 作用就是登录,登录后可以极大程度的提高爬取的成功率,大概80%,不登录就要看网站心情了,注册个账号超级简单,一个邮箱即可(当然我已经在代码里提供了一个测试账号,别给我玩封号了就行),用的pyautogui来规避反爬,代价是需要三张图来确定点击的位置,放在和代码同一文件夹下即可。(get_multi_page 和 multi_dynamic_download 会调用login函数)

  • get_single_page函数 爬取指定页面的所有视频信息,并存储在列表中,最后返回
    格式类似于:[[title, view, like, href], [title, view, like, href], [title, view, like, href]…]

  • get_multi_page函数 根据日期爬取从第 x 页到第 y 页的所有 like 数大于指定值的视频信息,储存在列表中,返回的格式和 get_single_page函数 一致。

其实到此为止就够用了,毕竟得到了视频的网页地址,直接手动进去下载就ok,但还是懒得动手,怎么办捏,写个自动下载吧~

  • single_dynamic_download函数 根据给出的网址下载视频。
    (如果单独使用这个记得把 time.sleep(10000)启用一下)

  • multi_dynamic_download函数 根据 get_single_page或者get_multi_page 爬取到的视频信息列表来进行下载。

4.使用方法:
一般来说都是 get_multi_page 和 multi_dynamic_download 配合使用就行,就是最后那几行代码,基本就是调一下like数和起始页码和结束页码就行,其他的东西不懂最好别动。

5.代码如下:


from bs4 import BeautifulSoup
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
import time
import pyautogui
import cv2
import undetected_chromedriver as uc
from undetected_chromedriver import By

# 0.创建browser/driver, 设置基础反反爬
def selenium_start():
    option = uc.ChromeOptions()
    option.headless = False
    option.add_argument('--disable-infobars')
    option.add_argument('--start-maximized')
    option.add_argument('--disable-extensions')
    option.add_argument('--disable-popup-blocking') # 允许chrome浏览器网页自动跳转
    option.add_argument("--enable-javascript") # 启用javascript渲染

    browser = uc.Chrome(options=option)
    # browser = uc.Chrome(executable_path='C:/Program Files (x86)/Google/Chrome/Application/chromedriver.exe', options=option)
    return browser


# 1.点击按钮
def click_button(browser, xpath, content):  # (网页源,需要点击的xpath信息,程序运行提示信息)
    button = browser.find_element(By.XPATH, xpath)
    browser.execute_script("arguments[0].click();", button)
    print(content)
    time.sleep(1)


# 2.输入按钮
def input_button(browser, xpath, input_content, content):  # (网页源,输入框的xpath信息,输入信息,程序运行提示信息)
    input_account = browser.find_element(By.XPATH, xpath)
    input_account.send_keys(input_content)
    print(content)
    time.sleep(1)


# 3.打开新标签页,将操作权限转移至新标签页
def open_new_web_page(browser, https):
    # 1.打开新标签页
    browser.execute_script(f"window.open('{https}');")
    # 2.将操作权限转移到新标签页
    browser.switch_to.window(browser.window_handles[-1])
    return browser


# 4.传入图片名称搜索图片点击,或传入xy直接点击坐标
def mouse_click(img_name=None, click_button='left', click_times=1, x=None, y=None):
    if x and y:
        print(f'正在点击{x, y}')
        pyautogui.click(x, y, clicks=click_times, button=click_button, duration=0.2, interval=0.2)
    else:
        while True:
            try:
                image_position = pyautogui.locateCenterOnScreen(img_name, confidence=0.8)
                x = image_position.x
                y = image_position.y
                print(f'正在点击{img_name}')
                pyautogui.click(x, y, clicks=click_times, button=click_button, duration=0.2, interval=0.2)
                break
            except:
                print(f'未识别到{img_name},0.5秒后重试')
                time.sleep(0.2)


# 5.登录(奶奶滴,不让我用selenium爬是吧,直接上pyautogui!哼)
def login(browser, account="kallstrommadeleinenfbf9266@gmail.com", password="1234"):  # (网页源,账号,密码)
    # 打开网页
    browser = open_new_web_page(browser, "https://www.iwara.tv/login")
    time.sleep(3)

    # # 1.输入账号
    mouse_click("1.png")
    pyautogui.write(account)

    # # 2.输入密码
    mouse_click("2.png")
    pyautogui.write(password)

    # # 3.点击提交登录
    mouse_click("3.png")

    wait_for_lording(browser, "username")   # 等待登录成功,防止还没登陆上去就切换到下一页了
    return browser


# 6.等待特定元素加载
def wait_for_lording(browser, element, sec=120):     # browser, "videoTeaser__content", 10
    try:
        WebDriverWait(browser, sec).until(EC.visibility_of_element_located((By.CLASS_NAME, element)))
        return True
    except:
        print("等待超时,未找到指定元素")
        return False


# 7.拿到单页中的所有视频信息
def get_single_page(browser, https):     # (网页源,网址)
    # 打开新网页
    browser = open_new_web_page(browser, https)

    video_info = []
    # 添加显式等待
    if wait_for_lording(browser, "videoTeaser__content"):
        # 获取到网页html
        html = browser.page_source  # print(html)

        # # bs4解析
        soup = BeautifulSoup(html, "html.parser")

        # 拿到每种数据的集合
        titles = soup.find_all('div', class_='videoTeaser__content')
        likes = soup.find_all("div", class_="likes")
        views = soup.find_all("div", class_="views")

        # 处理数据并保存到video_info中, data_struct = [title, like, view, href]
        for i in range(len(titles)):
            title = titles[i].find('a').get('title')
            like = likes[i].find("div", class_="text text--white text--tiny text--bold").text
            view = views[i].find("div", class_="text text--white text--tiny text--bold").text
            href = "https://ecchi.iwara.tv" + titles[i].find('a').get('href')
            video_info.append([title, like, view, href])

    # 判断获取页面信息是否成功
    if len(video_info):
        print(video_info)
    else:
        print(f"本次获取失败,具体信息:{https}")
    return video_info


# 8.拿到多页视频信息, 根据date筛选like数大于给定value的
def get_multi_page(start_page, end_page, value, account, password):      # (起始页,终止页,like数, 账号,密码)
    browser = selenium_start()
    browser = login(browser, account, password)
    more_than_num = []
    for i in range(start_page, end_page+1):
        try:
            for j in get_single_page(browser, f"https://www.iwara.tv/videos?sort=date&rating=ecchi&page={i}"):
                if j[1][-1] in ["k", "m", "K", "M"] or int(j[1]) >= value:
                    more_than_num.append(j)
        except Exception as e:
            print(f"{e}")                                               # 有bug,但其他地方正常运行,待排查,2023-9-6 3:55
            print(f"get page {i} failed, pls try this page later")
        time.sleep(3)

    print(f"符合要求的视频共有{len(more_than_num)}个,video_list={more_than_num}")
    return more_than_num


# 9.下载单个视频
def single_dynamic_download(browser, https):        # (网页源,网址)
    # 1.打开新标签页,将操作权限转移到新标签页
    browser = open_new_web_page(browser, https)

    # 等待视频源加载
    if wait_for_lording(browser, 'vjs-big-play-button') is False:
        print("didnt find wait element")
        raise Exception

    # 2.点击下载列表,点击下载
    try:
        html = browser.page_source
        soup = BeautifulSoup(html, 'html.parser')
        for index, dropdown in enumerate(soup.find_all('div', class_='dropdown dropdown--bottomRight')):
            button = dropdown.find('button', class_='button downloadButton mr-2 button--primary button--solid', type='button')
            if button:
                click_button(browser, f'//div[contains(@class, "dropdown dropdown--bottomRight")][{index + 1}]//button[contains(@class, "button downloadButton")]', 'Clicked download list')
                click_button(browser, f'//div[contains(@class, "dropdown dropdown--bottomRight")][{index + 1}]//div[contains(@class, "dropdown__content")]//a[text()="Source"]', 'Clicked Source link')
    except:
        print(f"下载失败,视频源不存在")


# 10.下载多个视频
def multi_dynamic_download(video_list, interval, account, password):     # (这里传入的是get_multi_page函数所爬取到的信息,也就是like数大于一定量的视频信息)
    browser = selenium_start()
    browser = login(browser, account, password)
    # 循环在同一个浏览器中打开多个视频网页,调用单个下载函数进行下载
    count = 1
    for i in video_list:
        try:
            print(f"尝试下载第{count}个,名称:'{i[0]}', 网址:{i[3]}")
            single_dynamic_download(browser, i[3])
            time.sleep(interval)
        except:
            print(f"视频下载出错,具体信息:{i[3]}")
        count += 1
        print('-----')
    print("Downloading...")
    time.sleep(10000)


# 入口
if __name__ == "__main__":
    # 单页信息
    # browser = selenium_start()
    # browser = login(browser)
    # browser.get("https://www.iwara.tv/videos?sort=date&rating=all&page=1")

    # 多页信息(第一个参数是起始页码,第二个是结束页码,第三个是大于多少like数,第四个账号,第五个密码)
    video_list = get_multi_page(10, 20, 700, "kallstrommadeleinenfbf9266@gmail.com", "1234")

    # 多个下载(下载每个视频的间隔时间,账号,密码),我的下载速度是10MB左右每秒,间隔时间设置为30,根据网速调整即可
    multi_dynamic_download(video_list, 50, "kallstrommadeleinenfbf9266@gmail.com", "1234")

    # 没法识别下载完了还是还在下载,所以就多跑一会吧,后续可能会添加自动结束功能
    time.sleep(100000)

pyautogui需要的三张图如下:
或者自己截也行,就是点击账号输入框,点击密码输入框,点击提交,很简单的
1.
请添加图片描述
2.
请添加图片描述
3.
请添加图片描述

喜欢的话不妨点个赞吧?有人互动的感觉才能支撑我继续发文章呀~

版本更迭:
1.0 2023/1/20 初版,
1.1 2023/1/21 完善启用login功能,增加爬取成功率,
1.2 2023/1/21 将login落实到 get_multi_page 和 multi_dynamic_download 函数中,
1.3 2023/1/25 在 multi_dynamic_download 添加try except,防止出现一个视频下载出错导致整个程序崩溃,
1.4 2023/3/2 在 get_multi_page 添加try except,防止单个页面出现数据错误导致程序崩溃,

2.0 2023/3/20 适配iwara的新网页端,更改了抓取页面的识别代码,删除了click_continue_if_need函数,新增wait_for_lording函数(等待特定元素加载),
2.1 2023/3/29 使用undetected_chromedriver绕过新增加的Cloudflare反爬,对selenium_start函数进行了部分调整,
2.2 2023/9/14 修复一个like数识别bug,
2.3 2023/11/4 微调selenium_start中的headless参数,修复由于chrome19.0版本更新导致的启动错误,
2.4 2023/11/20 修复一个由于pyautogui更新导致的小bug
2.5 2023/11/21 修复一个由于视频页面多了个按钮导致未能正确下载的bug

  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值