当前位置: 首页 > news >正文

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类型的&#xff0c;但是我把它嵌入flac格式的音频里后导致网页中无法播放 wps要会员&#xff0c;真麻烦。 完整代码&#xff1a; <!DOCTYPE html> <html lang"zh-CN"> <head> <meta charset"UTF-8">…...

DVWA -File Upload-通关教程-完结

DVWA -File Upload-通关教程-完结 文章目录 DVWA -File Upload-通关教程-完结页面功能LowMediumHighImpossible 页面功能 此页面的功能为选择某个图片文件点击Upload按钮上传&#xff0c;上传成功后得知文件上传路径为DVWA\hackable\uploads。 Low 源码审计 这段 PHP 代码…...

中介者模式:简化对象间通信的协调者

在面向对象的软件开发中&#xff0c;中介者模式是一种重要的行为型设计模式&#xff0c;用于降低多个对象间通信的复杂性。通过提供一个中心化的对象来处理不同组件之间的交互&#xff0c;中介者模式使得组件间不必显式引用彼此&#xff0c;从而使其松散耦合、更易于维护。本文…...

【Python系列】pydantic版本问题

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...

深度学习-多尺度训练的介绍与应用

一、引言 在当今快速发展的人工智能领域&#xff0c;多尺度训练已经成为了一种至关重要的技术&#xff0c;特别是在处理具有复杂结构和不同尺度特征的数据时。这种技术在许多应用中发挥着关键作用&#xff0c;例如图像识别、自然语言处理和视频分析等。 多尺度训练的定义 多尺…...

详解单文件组件

当你创建 Vue 单文件组件时&#xff0c;通常会包含三个部分&#xff1a;<template>、<script> 和 <style>。这三个部分分别用于定义组件的模板、逻辑和样式。让我更详细地解释一下它们的作用和用法&#xff1a; <template> <template> 标签用于…...

MLeaksFinder报错

1.报错&#xff1a;FBClassStrongLayout.mm 文件&#xff1a;layoutCache[currentClass] ivars; 解决&#xff1a;替换为layoutCache[(id)currentClass] ivars; 2.编译正常但运行时出现crash indirect_symbol_bindings[i] cur->rebinding FBRetainCycleDetector iOS15 …...

【心路历程】初次参加蓝桥杯实况

送给大家一句话&#xff1a; 寂静的光辉平铺的一刻&#xff0c;地上的每一个坎坷都被映照得灿烂。 – 史铁生 《我与地坛》 初次参加蓝桥杯有感 一点小小的震撼难评的做题过程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…...

3.3.1_1 检错编码(奇偶校验码)

从这节课开始&#xff0c;我们会探讨数据链路层的差错控制功能&#xff0c;差错控制功能的主要目标是要发现并且解决一个帧内部的位错误&#xff0c;我们需要使用特殊的编码技术去发现帧内部的位错误&#xff0c;当我们发现位错误之后&#xff0c;通常来说有两种解决方案。第一…...

mongodb源码分析session执行handleRequest命令find过程

mongo/transport/service_state_machine.cpp已经分析startSession创建ASIOSession过程&#xff0c;并且验证connection是否超过限制ASIOSession和connection是循环接受客户端命令&#xff0c;把数据流转换成Message&#xff0c;状态转变流程是&#xff1a;State::Created 》 St…...

可靠性+灵活性:电力载波技术在楼宇自控中的核心价值

可靠性灵活性&#xff1a;电力载波技术在楼宇自控中的核心价值 在智能楼宇的自动化控制中&#xff0c;电力载波技术&#xff08;PLC&#xff09;凭借其独特的优势&#xff0c;正成为构建高效、稳定、灵活系统的核心解决方案。它利用现有电力线路传输数据&#xff0c;无需额外布…...

dedecms 织梦自定义表单留言增加ajax验证码功能

增加ajax功能模块&#xff0c;用户不点击提交按钮&#xff0c;只要输入框失去焦点&#xff0c;就会提前提示验证码是否正确。 一&#xff0c;模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...

基于Java Swing的电子通讯录设计与实现:附系统托盘功能代码详解

JAVASQL电子通讯录带系统托盘 一、系统概述 本电子通讯录系统采用Java Swing开发桌面应用&#xff0c;结合SQLite数据库实现联系人管理功能&#xff0c;并集成系统托盘功能提升用户体验。系统支持联系人的增删改查、分组管理、搜索过滤等功能&#xff0c;同时可以最小化到系统…...

Go 并发编程基础:通道(Channel)的使用

在 Go 中&#xff0c;Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式&#xff0c;用于在多个 Goroutine 之间传递数据&#xff0c;从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...

C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)

名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...

ZYNQ学习记录FPGA(一)ZYNQ简介

一、知识准备 1.一些术语,缩写和概念&#xff1a; 1&#xff09;ZYNQ全称&#xff1a;ZYNQ7000 All Pgrammable SoC 2&#xff09;SoC:system on chips(片上系统)&#xff0c;对比集成电路的SoB&#xff08;system on board&#xff09; 3&#xff09;ARM&#xff1a;处理器…...

内窥镜检查中基于提示的息肉分割|文献速递-深度学习医疗AI最新文献

Title 题目 Prompt-based polyp segmentation during endoscopy 内窥镜检查中基于提示的息肉分割 01 文献速递介绍 以下是对这段英文内容的中文翻译&#xff1a; ### 胃肠道癌症的发病率呈上升趋势&#xff0c;且有年轻化倾向&#xff08;Bray等人&#xff0c;2018&#x…...

FOPLP vs CoWoS

以下是 FOPLP&#xff08;Fan-out panel-level packaging 扇出型面板级封装&#xff09;与 CoWoS&#xff08;Chip on Wafer on Substrate&#xff09;两种先进封装技术的详细对比分析&#xff0c;涵盖技术原理、性能、成本、应用场景及市场趋势等维度&#xff1a; 一、技术原…...