本文共 9140 字,大约阅读时间需要 30 分钟。
研究 Python+Selenium 自动化测试框架,简单实现 Mac 下自动化批量上传视频并发布。以下是脚本实现及相关信息。
手动手机号登录:首先通过手工手机号登录,保存西瓜视频网站的 cookie 文件。
加载并使用 cookie:之后加载 cookie 内容,使用脚本批量上传视频,保存到草稿(可自动发布,方便二次编辑)。
批量发布草稿:通过遍历视频草稿列表,进行草稿视频发布。注意:同一天上传或发布视频太多时,会被西瓜视频限流。
# 安装 Chromedriverbrew install chromedriver
#!/usr/bin/python# -*- coding: utf-8 -*-import timeimport jsonimport osimport shutilimport sysfrom selenium import webdriverfrom selenium.webdriver.support.ui import WebDriverWaitfrom selenium.webdriver import ActionChainsfrom pykeyboard import PyKeyboardfrom pymouse import PyMouseimport pyperclipclass XiGua: def __init__(self): self.driver = webdriver.Chrome() def save_cookies(self, cookies_file_name): time.sleep(20) 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): 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) self.driver.refresh() def is_exist_element_by_xpath(self, xpath): try: self.driver.find_element_by_xpath(xpath) return True except Exception as e: print(f"xpath: {xpath} 的元素不存在,错误:{e}") return False def upload_video(self, 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) 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) 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): 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(f"==开始上传视频:{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(f'当前发布数量 {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(), "取消")]') 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): self.driver.get(base_url) 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): 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): self.driver.get(base_url) 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' # 保存 cookie # xi_gua.xigua_save_cookies(base_url, 'xigua_cookies.txt') # 批量上传 xi_gua.xigua_batch_upload(base_url, xigua_cookies, videos_dir_path) # 批量发布草稿 # xi_gua.xigua_videos_release(base_url, xigua_cookies)
转载地址:http://youfk.baihongyu.com/