我们把前面讲解的上传视频到公众号的代码整体再复现一下,下面的代码大家直接运行就能实现上传视频到公众号并自动发布的功能。注意,前提是已经运行了爬取腾讯视频的代码爬取了视频。
# 导入相关模块 from selenium import webdriver import pymysql import os import requests from io import BytesIO from PIL import Image import time from selenium.webdriver.common.action_chains import ActionChains # 定义下拉滚动条的函数,后面会用到 def pullscrool(driver, mintime, maxtime): js = ''' function RandomNumBoth(Min, Max){ var Range = Max - Min; var Rand = Math.random(); var num = Min + Math.round(Rand * Range); return num;} var oldscrollpos = window.scrollY; var step = RandomNumBoth(500, 800); window.scrollBy(0, step); var newscrolpos = window.scrollY; if(oldscrollpos == newscrolpos) return false; else return true; ''' for count in range(150): driver.execute_script(js) time.sleep(random.uniform(mintime, maxtime)) # 取随机值更人性化 # 定义安全健壮的控件定位函数,后面会用到 def safe_findtag(driver, tagname, strtag, intertime=1, count=30000): nowcount = 0 while nowcount < count: time.sleep(intertime) try: result = driver.find_element_by_xpath(strtag) print("规定时间内找到:" + tagname) return result # 找到tag就返回 except: nowcount += 1 print("没找到" + tagname + str(nowcount) + "次") print("规定时间次数内没找到:" + tagname) # 定义安全健壮的鼠标点击函数,后面会用到 def safe_click(tag, info="noinfo"): while True: try: tag.click() break except: print(info) time.sleep(1) # 定义安全健壮的键盘按键函数,后面会用到 def safe_sendkeys(tag, data, info="senderror"): while True: try: tag.send_keys(data) break except: print(info) time.sleep(1) # 定义安全健壮的鼠标拖拽函数,后面会用到 def safe_moveandclick(driver, movetag, clicktag): while True: ActionChains(driver).move_to_element(safe_findtag(driver, movetag[0], movetag[1])).perform() try: safe_findtag(driver, clicktag[0], clicktag[1]).click() break except: print("重新移动鼠标") time.sleep(1) # 自动登录 wxdriver = webdriver.Chrome(executable_path="C:/driver/chromedriver.exe") wxdriver.get("https://mp.weixin.qq.com/") wxdriver.maximize_window() safe_click(safe_findtag(wxdriver, "使用帐号登录", '//a[@class="login__type__container__select-type"][text()="使用帐号登录"]'), "点击使用账号登录失败") safe_sendkeys(safe_findtag(wxdriver, "用户名", "//input[@name='account']"), "xxx@126.com", "输入用户名失败") # 用户名换成你自己的 safe_sendkeys(safe_findtag(wxdriver, "密码", "//input[@name='password']"), "xxx", "输入密码失败") # 密码换成你自己的 safe_click(safe_findtag(wxdriver, "登录", "//a[@class='btn_login']"), "点击登录失败") # 第1步:判断是否进入公众号管理页面 safe_findtag(wxdriver, "公众号", "//a[@class='weui-desktop-logo__inner']") print("进入公众号管理页面") # 第2步:点击图文消息标签 wxdriver.maximize_window() safe_click(safe_findtag(wxdriver, "图文消息", '//*[@id="app"]/div[2]/div[4]/div[2]/div/div[1]')) # 第3步:切换tab页 all_handles = wxdriver.window_handles # 获取浏览器所有tab页 for handle in all_handles: wxdriver.switch_to.window(handle) if safe_findtag(wxdriver, "请在这里输入标题", '//input[@placeholder="请在这里输入标题"]', 1, 1): break # 第4步:从数据库中读取视频信息 gxviewdb = pymysql.connect(user='birdpython', # 登录数据库的用户名(换成你自己的) passwd='laoniao', # 登录数据库的密码(换成你自己的) db='gxview', # 要操作的数据库(换成你自己的) host='88.88.88.88', # 登录数据库的IP地址(换成你自己的) charset='utf8') # 指定编码格式为utf-8,否则显示乱码 cursor = gxviewdb.cursor() sql = "select * from gxviewtable where viewused=0 and viewtype='%s' limit %d" % ("地球最牛黑科技", 8) cursor.execute(sql) viewtuple = cursor.fetchall() # 第5步:输入标题 for count, viewdata in enumerate(viewtuple): viewname = viewdata[2] viewlink = viewdata[3] viewimglink = viewdata[4] safe_sendkeys(safe_findtag(wxdriver, "请在这里输入标题", '//textarea[@placeholder="请在这里输入标题"]'), viewname, "输入标题失败") # 进入iframe iframe = safe_findtag(wxdriver, "编辑文档", '//iframe[@id="ueditor_0"]') wxdriver.switch_to.frame(iframe) safe_sendkeys(safe_findtag(wxdriver, "iframe的body", '//body'), "", "输入空格占位失败") # 第6步:插入视频链接 wxdriver.switch_to.default_content() # 点击上面的视频按钮,要从iframe里面再切换回来 safeclick(inter_time_find_tag(self.wxdriver, "视频", '//li[@id="js_editor_insertvideo"]')) safeclick(inter_time_find_tag(self.wxdriver, "视频链接", '//*[@id="vue_app"]/div[3]/div/div[1]/div/div[2]/div/div[1]/div[1]/ul/li[2]/a')) safesend_keys(inter_time_find_tag(self.wxdriver, "输入视频链接", '//input[@placeholder="支持微信公众号文章链接,视频详情页链接和腾讯视频链接"]'), viewlink, "输入视频链接失败") safeclick(inter_time_find_tag(self.wxdriver, "点击确定视频", '//*[@id="vue_app"]/div[3]/div/div[1]/div/div[2]/div/div[4]/form/div/div/div[2]/button')) safeclick(inter_time_find_tag(self.wxdriver, "点击确定视频", '//*[@id="vue_app"]/div[3]/div/div[1]/div/div[3]/div/div[2]/button')) # 下拉滚动条 pullscrool(wxdriver, 0.003, 0.1) # 第7步:插入图片 safe_moveandclick(wxdriver, ("选择封面", '//span[text()="拖拽或选择封面"]'), ("从图片库选择", '//*[@id="js_cover_null"]/ul/li[2]/a')) # 下载图片 basedir = os.path.dirname(os.path.abspath(__file__)) # 本程序文件所在目录 imgdir = os.path.join(basedir, "img") # 爬取的图片存放目录 hkj_dir = os.path.join(os.path.join(imgdir, "地球最牛黑科技"), "素材") # 素材存放目录 filepath = os.path.join(hkj_dir, viewname + '.png') headers = {"User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36"} f = BytesIO(requests.get(viewimglink, headers=headers).content) img = Image.open(f) img.resize((407, 228), Image.ANTIALIAS).save(filepath) f.close() safe_click(safe_findtag(wxdriver, "今日图片", '//strong[text()="今日图片"]'), "点击今日图片失败") while safe_findtag(wxdriver, "判断今日图片选中", '//strong[text()="今日图片"]/..').get_attribute( "class") != "weui-desktop-menu__link weui-desktop-menu__link_current weui-desktop-menu__link-self": pass # 处理本地上传图片 safe_findtag(wxdriver, "从本地上传视频图片", '//*[@id="vue_app"]/div[3]/div[1]/div/div[2]/div[1]/div/div[2]/div/div[1]/div/div/div[2]/div[2]/input').send_keys(filepath) while safe_findtag(wxdriver, "文件是否传输完成下一步按钮生效", '//button[text()="下一步"]').get_attribute( "class") != "weui-desktop-btn weui-desktop-btn_primary": pass # 下一步按钮生效,不然点击没效果 safe_click(safe_findtag(wxdriver, "文件是否传输完成下一步按钮生效", '//button[text()="下一步"]')) safe_click(safe_findtag(wxdriver, "点击视频图片完成", '//*[@id="vue_app"]/div[3]/div[1]/div/div[3]/div[2]/button')) # 第8步:保存草稿重复下一步操作 while safe_findtag(wxdriver, "完成按钮", '//button[text()="完成"]/', 1, 1): pass if count < 7: while True: tagsave = safe_findtag(wxdriver, "保存", '//button[text()="保存"]', 1, 1) or \ safe_findtag(wxdriver, "保存为草稿", '//span[text()="保存为草稿"]', 1, 1) if tagsave: break safe_click(tagsave) # 下拉左边滚动条 wxdriver.execute_script("document.getElementById('js_mp_sidemenu').scrollTop=1200") imagedocount = "other" # 功能:移动后安全点击(程序移动了,用户有时候再次移动鼠标失去焦点,导致点击失败。该函数可以判断在点击失败后,重新移动鼠标) safe_moveandclick(wxdriver, ("点击+号", '//*[@id="js_add_appmsg"]/i'), ("增加一条图文消息", '//i[@class="icon-svg-editor-appmsg"]')) else: while True: tagsave = safe_findtag(wxdriver, "保存并群发", '//button[text()="保存并群发"]', 1, 1) or \ safe_findtag(wxdriver, "群发", '//span[text()="群发"]', 1, 1) if tagsave: break safe_click(tagsave) safe_click(safe_findtag(wxdriver, "群发", '//button[text()="群发"]')) safe_click(safe_findtag(wxdriver, "继续群发", '//button[text()="继续群发"]')) # 发布视频,修改数据库 if safe_findtag(wxdriver, "是否发布", "//span[text()='首页']"): viewnameindex = 2 for data in viewtuple: sql = "UPDATE gxviewtable SET viewused = 1 WHERE viewname = '%s'" % (data[viewnameindex]) try: cursor = gxviewdb.cursor() cursor.execute(sql) # 提交到数据库执行 gxviewdb.commit() except: # 发生错误时回滚 gxviewdb.rollback() print("数据库已经修改")
同样,大家也可以把数据库处理的部分代码放在另一个文件中作为一个模块使用,另外把下拉滚动条的代码也放在令一个文件中作为一个模块使用,还有我们自定义的那些安全健壮的鼠标和键盘操作的函数放在另一个文件件中作为一个模块使用,这样代码看起更整洁。