Mac 下 Python+Selenium 自动上传西瓜视频
背景
研究下 Python+Selenium 自动化测试框架,简单实现 Mac 下自动化批量上传视频西瓜视频并发布,分享给需要的同学(未做过多的异常处理)。
脚本实现
首先通过手工手机号登录,保存西瓜视频网站的 cookie 文件
之后加载 cookie 内容,使用脚本批量上传视频,保存到草稿(也可自动发布,为了二次编辑,如修改封面)
最后通过遍历视频草稿列表,来进行草稿视频发布,PS: 同一天上传或发布视频太多时,会被西瓜视频限流。
安装依赖
# 安装依赖保存网站 cookie# 安装 chromedriver
$ brew install chromedriver
脚本内容
#!/usr/bin/python
# -*- coding: utf-8 -*-
import time
import json
import os
import shutil
import sysfrom selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver import ActionChains
from pykeyboard import PyKeyboard
from pymouse import PyMouse
import pyperclipclass XiGua:"""Mac 西瓜视频自动上传视频及发布草稿"""def __init__(self):"""初始化,打开浏览器"""self.driver = webdriver.Chrome()def save_cookies(self, cookies_file_name):"""保存 cookiescookies_file_name: cookies 文件名称"""# 预留 20 秒,来进行手工登录time.sleep(20)# 登录成功后,保存 cookies 文件with open(cookies_file_name, 'w') as cookies_file:cookies_file.write(json.dumps(self.driver.get_cookies()))def load_cookies(self, cookies_file_name):"""加载 cookiecookies_file_name: cookies 文件名称"""# 加载 cookies 文件with open(cookies_file_name, 'r') as cookies_file:cookies_list = json.load(cookies_file)for cookie in cookies_list:if 'expiry' in cookie:del cookie['expiry']self.driver.add_cookie(cookie)# 加载 cookie 后,刷新页面生效self.driver.refresh()def is_exist_element_by_xpath(self, xpath):"""判断元素是否存在"""flag = Truetry:self.driver.find_element_by_xpath(xpath)return flagexcept Exception as e:flag = Falseprint("xpath: [%s] 的元素不存在,错误:%s" % xpath, e)return flagdef upload_video(self, video_file_path):"""上传视频video_file_path: 上传视频路径"""# 打开上传视频页面self.driver.get("https://studio.ixigua.com/upload?from=post_article")# 点击上传self.driver.find_element_by_class_name("byte-upload-trigger-drag").click()time.sleep(5)# 选择视频文件k = PyKeyboard()m = PyMouse()# 打开k.press_keys(['Command', 'Shift', 'G'])x_dim, y_dim = m.screen_size()k.press_keys(['Shift'])m.click(x_dim // 2, y_dim // 2, 1)# 复制视频文件路径pyperclip.copy(video_file_path)# 粘贴k.press_keys(['Command', 'V'])time.sleep(2)k.press_key('Return')time.sleep(2)k.press_key('Return')time.sleep(2)# 设置转载选项self.driver.find_element_by_xpath('//*[@id="js-video-list-content"]/div/div[2]/div[4]/div[2]/div/div/label[2]/span/span').click()time.sleep(1)# 同步到抖音# self.driver.find_element_by_class_name("byte-checkbox-mask").click()# 循环判断视频上传成功,不成功等待10秒后,再次判断,直到成功while '上传成功' not in self.driver.find_element_by_xpath('//*[@id="js-video-list-content"]/div/div[1]/div[1]/div[2]/div[2]').text:print("循环等待视频上传成功,等待10秒")time.sleep(10)# 设置视频封面self.driver.find_element_by_class_name("m-xigua-upload").click()print('点击-上传封面')time.sleep(5)try:reload = self.driver.find_element_by_xpath('/html/body/div[3]/div/div[2]/div/div[1]/div/div/div/div[2]')# 视频封面解析失败处理,循环刷新if reload != '':print('视频封面解析失败处理,开始循环刷新')while XiGua.is_exist_element_by_xpath(self,'/html/body/div[3]/div/div[2]/div/div[1]/div/div/div/div[2]'):# 点击循环self.driver.find_element_by_xpath('/html/body/div[3]/div/div[2]/div/div[1]/div/div/div/div[2]').click()print('刷新失败后,等待5秒,再次刷新')time.sleep(5)# 选择第一个图片img = self.driver.find_element_by_xpath('/html/body/div[3]/div/div[2]/div/div[1]/div/div/div[1]/img')img.click()except Exception as e:print('封面解析正常,无需刷新')pass# 下一步cover_next_element = WebDriverWait(self.driver, 30).until(lambda x: x.find_element_by_xpath('/html/body/div[3]/div/div[2]/div/div[2]/div'))cover_next_element.click()print('点击-封面下一步')try:# 完成裁剪cover_crop_element = WebDriverWait(self.driver, 30).until(lambda x: x.find_element_by_xpath('//*[@id="tc-ie-base-content"]/div[2]/div[2]/div[2]/div/div[2]/div/div/div[2]'))if cover_crop_element != '':cover_crop_element.click()print('点击-封面完成裁剪')else:print('封面无需裁剪')except Exception as e:print('裁剪封面出现异常:%s' % e)passtime.sleep(5)# 确定self.driver.find_element_by_xpath('//*[@id="tc-ie-base-content"]/div[2]/div[2]/div[3]/div[3]/button[2]').click()print('点击-封面确定')time.sleep(1)# 再次确定self.driver.find_element_by_xpath('/html/body/div[4]/div/div[2]/div/div[2]/button[2]').click()print('点击-封面再次确定')time.sleep(5)# 存草稿draft_element = WebDriverWait(self.driver, 30).until(lambda x: x.find_element_by_xpath('//*[@id="js-submit-draft-0"]/button'))action = ActionChains(self.driver)print('点击-保存草稿')# 移动滚动条到底部js = "window.scrollTo(0,document.body.scrollHeight)"self.driver.execute_script(js)# 移动到 存草稿 按钮点击action.move_to_element(draft_element).click().perform()def close(self):"""关闭浏览器"""self.driver.close()def batch_upload(self, videos_dir_path):"""批量上传视频videos_dir_path: 上传视频存储路径"""files = os.listdir(videos_dir_path)# 降序排序上传,草稿发布时,视频序号则为顺序files.sort(reverse=True)# 批量上传视频for file in files:if os.path.splitext(file)[1] == '.mp4':full_file_path = os.path.join(videos_dir_path, os.path.splitext(file)[0])print("==开始上传视频:%s" % full_file_path)self.upload_video(full_file_path)src = os.path.join(videos_dir_path, file)dst = os.path.join(videos_dir_path, 'bak', file)# 发布完成后,移到到备份目录shutil.move(src, dst)def videos_release(self):"""草稿视频发布"""self.driver.get("https://studio.ixigua.com/content")time.sleep(2)# 点击草稿导航draft_navigation_element = WebDriverWait(self.driver, 30).until(lambda x: x.find_element_by_xpath('//*[@id="app"]/div/section/div/div[1]/ul/li[3]'))draft_navigation_element.click()print('点击-草稿导航')time.sleep(2)# 草稿列表draft_elements = self.driver.find_elements_by_class_name('content-card__title ')# 草稿列表为空,则退出if len(draft_elements) == 0:print("草稿列表为空")XiGua.close(self)sys.exit()# 循环发布草稿,每次都发布第一个for i in range(1, 99999):# 草稿列表为空,退出if draft_elements == '':print('草稿发布完成,总共:%s' % str(i))XiGua.close(self)sys.exit()print('当前发布数量 %s, 发布视频: %s' % (str(i), draft_elements[0].text))# 发布草稿第一个视频draft_elements[0].click()time.sleep(3)# 立即发布element2 = WebDriverWait(self.driver, 30).until(lambda x: x.find_element_by_xpath('//button[contains(text(), "发布")]'))element2.click()print('点击-视频发布')# 判断是否发布失败,如标题超长try:# 错误处理if XiGua.is_exist_element_by_xpath(self, '/html/body/div[3]/div/div/div/span'):print('发布出现错误,退出,请检查错误,如标题超长等')sys.exit()except Exception as e:print('草稿发布异常:%s' % e)pass# 处理封面分辨率低提示try:# 封面分辨率低cover_cancel_element = self.driver.find_element_by_xpath('//div[contains(text(), "取消")]')print('封面分辨率低处理,直接取消')# 错误处理if cover_cancel_element != '':print('取消封面分辨率低')cover_cancel_element.click()# 立即发布cover_publish_element = WebDriverWait(self.driver, 30).until(lambda x: x.find_element_by_xpath('//button[contains(text(), "发布")]'))cover_publish_element.click()except Exception as e:print('封面分辨率低出现异常:%s' % e)pass# 点击草稿draft_publish_element = WebDriverWait(self.driver, 30).until(lambda x: x.find_element_by_xpath('//*[@id="app"]/div/section/div/div[1]/ul/li[3]'))draft_publish_element.click()time.sleep(2)print('重新获取草稿列表')draft_elements = self.driver.find_elements_by_class_name('content-card__title ')print(draft_elements)def xigua_videos_release(self, base_url, cookies_file_path):"""西瓜视频发布草稿base_url: 西瓜视频网站cookies_file_path: 西瓜视频 cookies 文件路径"""self.driver.get(base_url)# 加载 cookiesXiGua.load_cookies(self, cookies_file_path)# 草稿发布视频XiGua.videos_release(self)# 关闭浏览器XiGua.close(self)def xigua_batch_upload(self, base_url, cookies_file_path, videos_dir_path):"""西瓜视频批量发布视频base_url: 西瓜视频网站cookies_file_path: 西瓜视频 cookies 文件路径videos_dir_path: 上传视频存储路径"""self.driver.get(base_url)XiGua.load_cookies(self, cookies_file_path)XiGua.batch_upload(self, videos_dir_path)XiGua.close(self)def xigua_save_cookies(self, base_url, cookies_file_path):"""保存网站 cookiebase_url: 网站地址cookies_file_path: 网站 cookies 文件路径"""self.driver.get(base_url)# 保存 cookiesXiGua.save_cookies(self, cookies_file_path)XiGua.close(self)if __name__ == '__main__':xi_gua = XiGua()# 西瓜视频base_url = 'https://www.ixigua.com/'xigua_cookies = '/tmp/xigua_update_video/xigua_cookies.txt'videos_dir_path = '/tmp/rm'## 1. 保存 cookie# xi_gua.xigua_save_cookies(base_url, 'xigua_cookies.txt')## 2. 批量上传xi_gua.xigua_batch_upload(base_url, xigua_cookies, videos_dir_path)## 3. 批量发布草稿# xi_gua.xigua_videos_release(base_url, xigua_cookies)
行动吧,在路上总比一直观望的要好,未来的你肯定会感 谢现在拼搏的自己!如果想学习提升找不到资料,没人答疑解惑时,请及时加入扣群: 320231853,里面有各种软件测试+开发资料和技术可以一起交流学习哦。
最后感谢每一个认真阅读我文章的人,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:
这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴上万个测试工程师们走过最艰难的路程,希望也能帮助到你!

相关文章:
Mac 下 Python+Selenium 自动上传西瓜视频
背景 研究下 PythonSelenium 自动化测试框架,简单实现 Mac 下自动化批量上传视频西瓜视频并发布,分享给需要的同学(未做过多的异常处理)。 脚本实现 首先通过手工手机号登录,保存西瓜视频网站的 cookie 文件 之后加载…...
六:ReentrantLock —— 可重入锁
目录 1、ReentrantLock 入门2、ReentrantLock 源码解析2.1、构造方法:默认为非公平锁2.2、三大内部类2.2、lock():加锁【不可中断锁】2.2.1、acquire() 方法 —— AQS【模板方法】2.2.2.1 tryAcquire() 方法 —— AQS,由子类去实现2.2.2.2. a…...
一种驱动器的功能安全架构介绍
下图提供了驱动器实现安全功能的架构 具有如下特点: 1.通用基于总线或者非总线的架构。可以实现ethercat的FSOE,profinet的profisafe,或者伺服本体安全DIO现实安全功能。 2.基于1oo2D架构,安全等级可以达到sil3。 3.高可用性。单…...
紫光展锐T610平台_4G安卓核心板方案定制开发
紫光展锐T610核心板配备Android 11操作系统,采用12nm制程工艺。该处理器CPU由2颗基于Cortex-A75架构的大核心和6颗基于Cortex-A55架构的小核心组成,最高主频为1.8GHz。GPU采用的是614.4MHz的Mali G52,可以流畅播放2400*1080分辨率视频&#x…...
C++11 设计模式4. 抽象工厂(Abstract Factory)模式
问题的提出 从前面我们已经使用了工厂方法模式 解决了一些问题。 现在 策划又提出了新的需求:对于各个怪物,在不同的场景下,怪物的面板数值会发生变化, //怪物分类:亡灵类,元素类,机械类 …...
第8周 Python面向对象编程刷题
单击题目,直接跳转到页面刷题,一周后公布答案。加入QQ群701657573,随时答疑交流。 218:类对象属性219:坐标对象相加220:计算周长221:学生分数总和222:车辆类中创建引擎类对象223&am…...
【学习心得】神经网络知识中的符号解释②
我在上篇文章中初步介绍了一些神经网络中的符号,只有统一符号及其对应的含义才能使我自己在后续的深度学习中有着一脉相承的体系。如果对我之前的文章感兴趣可以点击链接看看哦: 【学习心得】神经网络知识中的符号解释①http://t.csdnimg.cn/f6PeJ 一、…...
Igh related:Small Bug And Notes Record.
Write at the top My computer got some silly problem with the typing software that my Chinese IM does’t work again. So I’ll try to record the things happened in English. If any error,DM me plz. BUGs BUG1 Undefined symbol Identifier “CLOCK_MONOTONIC”…...
【QT入门】Qt自定义控件与样式设计之qss介绍(Qt style sheet)
往期回顾: 【QT入门】 无边框窗口设计之实现圆角窗口-CSDN博客【QT入门】 无边框窗口设计综合运用之自定义标题栏带圆角阴影的窗口-CSDN博客 【QT入门】 无边框窗口设计之综合运用,实现WPS的tab页面-CSDN博客 【QT入门】Qt自定义控件与样式设计之qss介绍…...
[ LeetCode ] 题刷刷(Python)-第49题:字母异位词分组
题目描述 给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。 字母异位词是由重新排列源单词的所有字母得到的一个新单词。 即将含有相同字符但排列顺序不同的字符串放入同一个组中。 示例 示例 1: 输入: strs ["eat", &qu…...
冒泡排序算法实现步骤
算法实现的过程: 1. 定义问题: - 算法是用来解决某一特定计算问题的方法步骤。例如,对于排序问题,我们需要一个算法对一组无序的整数进行排序。 2. 设计算法: - 冒泡排序是一种基础的排序算法。它的设计思路是…...
js实现webp转png/jpg
网上保存的图片是webp类型的,但是我把它嵌入flac格式的音频里后导致网页中无法播放 wps要会员,真麻烦。 完整代码: <!DOCTYPE html> <html lang"zh-CN"> <head> <meta charset"UTF-8">…...
DVWA -File Upload-通关教程-完结
DVWA -File Upload-通关教程-完结 文章目录 DVWA -File Upload-通关教程-完结页面功能LowMediumHighImpossible 页面功能 此页面的功能为选择某个图片文件点击Upload按钮上传,上传成功后得知文件上传路径为DVWA\hackable\uploads。 Low 源码审计 这段 PHP 代码…...
中介者模式:简化对象间通信的协调者
在面向对象的软件开发中,中介者模式是一种重要的行为型设计模式,用于降低多个对象间通信的复杂性。通过提供一个中心化的对象来处理不同组件之间的交互,中介者模式使得组件间不必显式引用彼此,从而使其松散耦合、更易于维护。本文…...
【Python系列】pydantic版本问题
💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...
深度学习-多尺度训练的介绍与应用
一、引言 在当今快速发展的人工智能领域,多尺度训练已经成为了一种至关重要的技术,特别是在处理具有复杂结构和不同尺度特征的数据时。这种技术在许多应用中发挥着关键作用,例如图像识别、自然语言处理和视频分析等。 多尺度训练的定义 多尺…...
详解单文件组件
当你创建 Vue 单文件组件时,通常会包含三个部分:<template>、<script> 和 <style>。这三个部分分别用于定义组件的模板、逻辑和样式。让我更详细地解释一下它们的作用和用法: <template> <template> 标签用于…...
MLeaksFinder报错
1.报错:FBClassStrongLayout.mm 文件:layoutCache[currentClass] ivars; 解决:替换为layoutCache[(id)currentClass] ivars; 2.编译正常但运行时出现crash indirect_symbol_bindings[i] cur->rebinding FBRetainCycleDetector iOS15 …...
【心路历程】初次参加蓝桥杯实况
送给大家一句话: 寂静的光辉平铺的一刻,地上的每一个坎坷都被映照得灿烂。 – 史铁生 《我与地坛》 初次参加蓝桥杯有感 一点小小的震撼难评的做题过程A题 艺术与篮球问题描述解题 B 题 五子棋问题描述解题 C题 训练士兵问题描述解题 D题 团建解题 E题 …...
微信小程序全屏开屏广告
效果图 代码 <template><view><!-- 自定义头部 --><u-navbar title" " :bgColor"bgColor"><view class"u-nav-slot" slot"left"><view class"leftCon"><view class"countDown…...
Python爬虫实战:研究MechanicalSoup库相关技术
一、MechanicalSoup 库概述 1.1 库简介 MechanicalSoup 是一个 Python 库,专为自动化交互网站而设计。它结合了 requests 的 HTTP 请求能力和 BeautifulSoup 的 HTML 解析能力,提供了直观的 API,让我们可以像人类用户一样浏览网页、填写表单和提交请求。 1.2 主要功能特点…...
conda相比python好处
Conda 作为 Python 的环境和包管理工具,相比原生 Python 生态(如 pip 虚拟环境)有许多独特优势,尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处: 一、一站式环境管理:…...
Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...
【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密
在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...
将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?
Otsu 是一种自动阈值化方法,用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理,能够自动确定一个阈值,将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...
浅谈不同二分算法的查找情况
二分算法原理比较简单,但是实际的算法模板却有很多,这一切都源于二分查找问题中的复杂情况和二分算法的边界处理,以下是博主对一些二分算法查找的情况分析。 需要说明的是,以下二分算法都是基于有序序列为升序有序的情况…...
算法笔记2
1.字符串拼接最好用StringBuilder,不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...
[免费]微信小程序问卷调查系统(SpringBoot后端+Vue管理端)【论文+源码+SQL脚本】
大家好,我是java1234_小锋老师,看到一个不错的微信小程序问卷调查系统(SpringBoot后端Vue管理端)【论文源码SQL脚本】,分享下哈。 项目视频演示 【免费】微信小程序问卷调查系统(SpringBoot后端Vue管理端) Java毕业设计_哔哩哔哩_bilibili 项…...
[大语言模型]在个人电脑上部署ollama 并进行管理,最后配置AI程序开发助手.
ollama官网: 下载 https://ollama.com/ 安装 查看可以使用的模型 https://ollama.com/search 例如 https://ollama.com/library/deepseek-r1/tags # deepseek-r1:7bollama pull deepseek-r1:7b改token数量为409622 16384 ollama命令说明 ollama serve #:…...
android13 app的触摸问题定位分析流程
一、知识点 一般来说,触摸问题都是app层面出问题,我们可以在ViewRootImpl.java添加log的方式定位;如果是touchableRegion的计算问题,就会相对比较麻烦了,需要通过adb shell dumpsys input > input.log指令,且通过打印堆栈的方式,逐步定位问题,并找到修改方案。 问题…...

