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,里面有各种软件测试+开发资料和技术可以一起交流学习哦。

最后感谢每一个认真阅读我文章的人,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:

这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴上万个测试工程师们走过最艰难的路程,希望也能帮助到你!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/814144.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HTML的文档说明

1.告诉浏览器当前网页的版本 2.写法&#xff1a; &#xff01;以前的写法&#xff1a;要依据网页的HTML的版本去确定&#xff0c;紫萼发油很多很多。 具体的写法可以参考&#xff1a;W3C官网的文档说明 &#xff01;新写法&#xff1a;W3C都推荐用h5的写法 <DOCTYPE ht…

C语言CRC通用模块代码

我这几天看了下CRC具体校验原理&#xff0c;我看网上都没有一个通用的CRC库&#xff0c;都是一个函数写一种校验方式的那种&#xff0c;以下代码是随手写的一个通用的CRC软件模块&#xff0c; 支持最小单位字节的输入&#xff0c;有问题大家一起讨论。移植时需要修改的点可能是…

【蓝桥杯】第十五届蓝桥杯大赛软件赛省赛(Java研究生组)个人解题思路及代码分享

文章目录 试题A&#xff1a;劲舞团试题B&#xff1a;召唤数字精灵试题C&#xff1a;封闭图形的个数试题D&#xff1a;商品库存管理试题E&#xff1a;砍柴试题F&#xff1a;回文字符串试题G&#xff1a;最大异或节点试题H&#xff1a;植物生命力 试题A&#xff1a;劲舞团 【问题…

napi系列学习高阶篇——通过IDE集成C/C++三方库并开发napi接口

简介 应用在调用系统固件集成的C/C三方库时&#xff0c;可能会由于系统固件集成端与IDE的NDK中libc版本不一致导致调用失败&#xff0c;而且系统固件集成的C/C三方库对于应用的调式也很不友好&#xff0c;需要多方编译调试&#xff0c;很不方便。因此本文将通过在IDE上适配ope…

mp3怎样才能转换成wav格式?音频互相转换的方法

一&#xff0c;什么是WAV WAV&#xff0c;全称为波形音频文件&#xff08;Waveform Audio File Format&#xff09;&#xff0c;是一种由微软公司和IBM公司联合开发的音频文件格式。自1991年问世以来&#xff0c;WAV格式因其无损的音频质量和广泛的兼容性&#xff0c;成为了多…

【opencv】示例-morphology2.cpp 形态学操作:膨胀、腐蚀、开运算、闭运算

element_shape MORPH_ELLIPSE; element_shape MORPH_RECT element_shape MORPH_CROSS; // 包含必要的OpenCV头文件 #include "opencv2/imgproc.hpp" // 图像处理 #include "opencv2/imgcodecs.hpp" // 图像编码解码 #include "opencv2/highgui.hpp…

Zynq学习笔记--AXI 总线概述

目录 1. AXI总线概述 1.1 主要特点 1.2 通道功能 1.3 信号概览 2. AXI Interconnect 2.1 信号说明 2.2 内部结构 3. PS-PL AXI Interface 3.1 AXI FPD/LFP/ACP 3.2 Address Editor 3.3 地址空间 3.4 AXI-DDR 4. 通过ILA观察AXI信号 4.1 AXI 读通道 1. AXI总线概述…

Linux高级IO——多路转接之poll

本章代码Gitee地址&#xff1a;PollServer 文章目录 1. poll2. poll_server 1. poll poll的作用和select一模一样&#xff0c;只负责等待 poll在select的基础之上解决了select的两个硬伤&#xff1a; select等待的fd有上限select输入输出参数较多 #include <poll.h> …

【软件设计师知识点】八、数据库技术基础

文章目录 数据库基本术语关系型数据库基本术语数据库模型三级模式二级映射数据的独立性数据模型常用数据模型E-R 图(概念设计)数据库操作完整性规则关系代数运算集合运算符关系运算符数据库语言 SQL数据定义语言(DDL)

uniapp开发小程序手写板、签名、签字

可以使用这个插件进行操作 手写板-签名签字-lime-signature - DCloud 插件市场 但是目前这个插件没有vue3 setup Composition API的写法。所以对于此文档提供的可以直接使用,需要使用Composition API方式实现的,可以继续看。 因为Composition API方式,更加的简单、灵活,…

Java编程题目 | 四个数的三三组合

大家可以关注一下专栏&#xff0c;方便大家需要的时候直接查找&#xff0c;专栏将持续更新~ 题目描述 使用数字1、2、3、4&#xff0c;编写一个Java程序&#xff0c;找出所有互不相同且每个三位数中不含有重复数字的组合&#xff0c;并输出这些组合。 解题思路 使…

记录一个腾讯云上kafka不能正常启动问题

问题描述&#xff1a;刚在新的腾讯云三台节点上安了Zookeeper和kafka&#xff0c;改好对应配置文件后&#xff0c;启动zk和kafka。 启动zk后&#xff0c;启动kafka jpsall以后 发现两个进程都启了&#xff08;这里有猫腻&#xff0c;kafka其实没起来&#xff0c;过几秒就自动掉…

在Windows中用命令行编译C项目

在Windows中可以用命令行编译C项目 官方指导文档&#xff1a; 演练&#xff1a;在命令行上编译 C 程序 | Microsoft Learn 在官方文档中可以看到&#xff0c;可以只安装VS的命令行工具集&#xff0c;如下图所示

2.0 Hadoop 运行环境

2.0 Hadoop 运行环境 分类 Hadoop 教程 由于 Hadoop 是为集群设计的软件&#xff0c;所以我们在学习它的使用时难免会遇到在多台计算机上配置 Hadoop 的情况&#xff0c;这对于学习者来说会制造诸多障碍&#xff0c;主要有两个&#xff1a; 昂贵的计算机集群。多计算机构成的…

JVM性能调优——GC日志分析

文章目录 1、概述2、生成GC日志3、Parallel垃圾收集器日志解析3.1、Minor GC3.2、FULL GC 4、G1垃圾收集器日志解析4.1、Minor GC4.2、并发收集4.3、混合收集4.4、Full GC 5、CMS垃圾收集器日志解析5.1、Minor GC5.2、Major GC5.3、浮动垃圾 6、日志解析工具6.1、GCeasy6.2、GC…

SpringBoot项目 jar包方式打包部署

SpringBoot项目 jar包方式打包部署 传统的Web应用进行打包部署&#xff0c;通常会打成war包形式&#xff0c;然后将War包部署到Tomcat等服务器中。 在Spring Boot项目在开发完成后&#xff0c;确实既支持打包成JAR文件也支持打包成WAR文件。然而&#xff0c;官方通常推荐将Sp…

【Godot4.2】CanvasItem绘图函数全解析 - 8.绘制点索引

概述 在示意图绘制过程中或者测试过程中&#xff0c;可能需要标记点的索引。 最常见的形式就是用一个圆圈作为背景&#xff0c;用阿拉伯数字作为索引。 实现的重点是动态计算背景圆的半径。原理是&#xff0c;获取字符串的矩形&#xff0c;取对角线长度的一半作为外接圆的半…

AI PC元年,华为的一张航海图、一艘渡轮和一张船票

今天&#xff0c;从学术研究者到产业投资者&#xff0c;无不认为大模型掀起了一场人工智能的完美风暴。 所谓“完美风暴”&#xff0c;指的是一项新技术的各个要素&#xff0c;以新的方式互相影响、彼此加强&#xff0c;组合在一起形成了摧枯拉朽般的力量。 而我们每个人&#…

【运维笔记】深入理解反向代理的原理及应用

一、引言 在现代网络架构中&#xff0c;反向代理是一个核心组件&#xff0c;它在提升网站性能、增加安全性和简化网络流量管理方面发挥着至关重要的作用。本文将深入探讨反向代理的原理&#xff0c;展示其在不同场景下的应用&#xff0c;并通过具体案例来说明如何实现和优化反…

【opencv】示例-phase_corr.cpp 捕获视频流并通过计算相位相关性来检测画面中的移动...

// 包含OpenCV库的头文件 #include "opencv2/core.hpp" // 包含OpenCV核心功能 #include "opencv2/videoio.hpp" // 包含视频IO功能 #include "opencv2/highgui.hpp" // 包含高级GUI功能&#xff0c;显示图像 #include "opencv2/imgproc.hp…