1.提示:
使用需要安装bs4库,selenium库,fake_useragent库,pyautogui库,cv2库,undetected_chromedriver库,版本没什么要求,
同时需要安装相同版本的Chrome浏览器和驱动器,注意驱动器和浏览器不一样哦,
哦对了,还要自备梯子,不过某喵天天在Iwara打广告,你们应该不会看不到吧?
后面如果有时间的话我会做个使用教学视频发在b站的,顺便讲讲思路,应该会有时间吧?大概?
2.严肃警告
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.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)
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:
image_position = pyautogui.locateCenterOnScreen(img_name, confidence=0.9)
if image_position:
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
else:
print(f'未识别到{img_name},0.5秒后重试')
time.sleep(0.2)
# 5.登录(奶奶滴,不让我用selenium爬是吧,直接上pyautogui!哼)
def login(browser, account="[email protected]", 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, view, like, 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=all&page={i}"):
if j[1][-1] in ["k", "m"] or int(j[1]) >= value:
more_than_num.append(j)
except:
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)
wait_for_lording(browser, 'vjs-big-play-button') # 等待视频源加载
# 2.点击下载列表,点击下载
try:
html = browser.page_source
soup = BeautifulSoup(html, 'html.parser')
for index, dropdown in enumerate(soup.find_all('div', class_='dropdown dropdown--bottomLeft')):
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--bottomLeft")][{index + 1}]//button[contains(@class, "button downloadButton")]', 'Clicked download list')
click_button(browser, f'//div[contains(@class, "dropdown dropdown--bottomLeft")][{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)
# 循环在同一个浏览器中打开多个视频网页,调用单个下载函数进行下载
for i in video_list:
try:
single_dynamic_download(browser, i[3])
time.sleep(interval)
except:
print(f"视频下载出错,具体信息:{i[3]}")
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(1, 30, 500, "[email protected]", "1234")
# 多个下载(下载每个视频的间隔时间,账号,密码),我的下载速度是10MB左右每秒,间隔时间设置为30,根据网速调整即可
multi_dynamic_download(video_list, 50, "[email protected]", "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函数进行了部分调整,