背景
研究下 Python+Selenium 自動化測試框架,簡單實現 Mac 下自動化批量上傳視頻西瓜視頻並發布,分享給需要的同學(未做過多的異常處理)。
腳本實現
- 首先通過手工手機號登錄,保存西瓜視頻網站的 cookie 文件
- 之后加載 cookie 內容,使用腳本批量上傳視頻,保存到草稿(也可自動發布,為了二次編輯,如修改封面)
- 最后通過遍歷視頻草稿列表,來進行草稿視頻發布
PS: 同一天上傳或發布視頻太多時,會被西瓜視頻限流。
安裝依賴
# 安裝依賴
$ pip install selenium PyUserInput pyperclip
# 安裝 chromedriver
$ brew install chromedriver
腳本內容
#!/usr/bin/python
# -*- coding: utf-8 -*-
import time
import json
import os
import shutil
import sys
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver import ActionChains
from pykeyboard import PyKeyboard
from pymouse import PyMouse
import pyperclip
class XiGua:
"""
Mac 西瓜視頻自動上傳視頻及發布草稿
"""
def __init__(self):
"""
初始化,打開瀏覽器
"""
self.driver = webdriver.Chrome()
def save_cookies(self, cookies_file_name):
"""
保存 cookies
cookies_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):
"""
加載 cookie
cookies_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 = True
try:
self.driver.find_element_by_xpath(xpath)
return flag
except Exception as e:
flag = False
print("xpath: [%s] 的元素不存在,錯誤:%s" % xpath, e)
return flag
def 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)
pass
time.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)
# 加載 cookies
XiGua.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):
"""
保存網站 cookie
base_url: 網站地址
cookies_file_path: 網站 cookies 文件路徑
"""
self.driver.get(base_url)
# 保存 cookies
XiGua.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)
微信公眾號:daodaotest