我们已经完成了爬取腾讯视频,做了视频时长和去重的操作,并且把每个腾讯视频项里面的信息(视频名称,视频链接,视频图片,视频时长)存储到了数据库。接下来我们就开始自动赚钱项目的第二步:把这些视频信息传导微信公众号上。
我们要把爬取的视频信息上传到公众号,在这之前,首先你要有一个公众号账户,公众号分为两种:一种是企业注册的服务号,一种是个人注册的订阅号。
在这里我我们使用个人订阅号即可,只要你是中华人民共和国公民就可以免费注册个人订阅号,目前微信官方只允许一个身份证注册一个订阅号,后面我们开始带大家一步步注册个人公众号。
第1步
首先,我们打开微信公众平台官网:https://mp.weixin.qq.com/ ,右上角点击“立即注册”。
第2步
选择自己的公众号类型,如果你是个人选“订阅号”即可,如果是企业请选择“服务号”。在此,我们选择“订阅号”即可。
第3步
填写邮箱,登录您的邮箱,查看激活邮件,填写邮箱验证码激活,然后自己设置一个微信公众号后台登录的密码,最后点击我同意并遵守,然后点击注册即可。
第4步
填完信息之后,点击注册,跳转到下面这个页面,默认是中国大陆,我们只需要直接点击确定按钮即可。
第5步
进入本页面有三个选项,在此我们选择订阅号,点击-》选择并继续,点击之后会弹出一个温馨提示窗口,我们直接点击确定即可。
第6步
这个页面信息登记页面,对于主题类型,我们点击个人按钮,网页下面会出现主体信息登记栏目,我们按要求填写完之后,点击继续按钮。
第7步
这个页面是最后一个页面,填写帐号信息,包括公众号名称、功能介绍,选择运营地区,然后点击完成按钮,就会弹出一个注册成功的对话框,我们就完成了个人公众号(订阅号)的注册。
首先我们打开微信公众号登录界面,网站为:https://mp.weixin.qq.com/,微信公众号默认的登录方式是扫码登录,在此我们要选择使用账号登录的方式,我们需要模拟鼠标点击使用账号登录按钮。
点击后会进入账号登录方式页面,然后对登录用户名框和登录密码框进行定位分析,以下是对登录用户名框控件的分析。
然后,我们再对登录密码框进行定位分析。
当我们把用户名和密码输入进去后,我们还需要点击登录按钮,才能完成微信公众号的登录操作,所以我们还需要对登录按钮进行定位。
通过对使用账号登录按钮,登录用户名框,登录密码框,登录按钮的定位,我们即可以使用selenium提供的定位函数来找到这些控件,然后我们用selenium提供的鼠标操作和键盘操作来完成我们的自动登录。
from selenium import webdriver wxdriver = webdriver.Chrome(executable_path="C:/driver/chromedriver.exe") wxdriver.get("https://mp.weixin.qq.com/") wxdriver.maximize_window() loginway = wxdriver.find_element_by_xpath("//a[@class='login__type__container__select-type']") usernametag = wxdriver.find_element_by_xpath("//input[@name='account']") userpassword = wxdriver.find_element_by_xpath("//input[@name='password']") loginbt = wxdriver.find_element_by_xpath("//a[@class='btn_login']") loginway.click() # 点击使用账号登录按钮 usernametag.send_keys("myname") # 输入登录用户名 userpassword.send_keys("mypassword") # 输入登录密码 loginbt.click() # 点击登录
当我们调用selenium提供的控件定位,鼠标点击,鼠标拖动,键盘输入等操作时,有可能因为浏览器反应慢,或者我们动了鼠标和键盘,导致selenium的这些行为失效。为了防止以上行为,我们对selenium提供的以上行为做了一次封装,让其更有健壮性。
安全健壮的控件定位封装。
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)
从现在开始,后面我们在使用控件定位,鼠标点击,鼠标拖动,键盘输入等操作时,就使用我们封装好的安全健壮的这些函数,从此再也不怕找不到控件,点不到,拖不动,输入失效的问题了。下面是我们改写后的自动登录代码。
from selenium import webdriver from component_tools.findtag_tool import safe_findtag, safe_click, safe_sendkeys, safe_moveandclick 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步:判断是否进入公众号管理页面
我们的程序要等待用户扫码成功之后,才能进行信公众号的管理页面的代码逻辑,问题是,我们如何知道已经扫码成功并进入微信公众号管理页面了呢?我们的策略是:先用程序去判断管理页面里面存在而扫码页面里面没有的某个标签是否能够找的到,如果找到了就说明我们已经进入管理页面了,否则说明用户没有进入管理页面。比如我们可以判断公众号这个标签。
我们发现管理页面里面存在公众号这个标签,而扫码页面里面没有这个标签,当然你也可以判断其它符合这个性质的标签。
# 第1步:判断是否进入公众号管理页面 safe_findtag(wxdriver, "公众号", "//a[@class='weui-desktop-logo__inner']") print("进入公众号管理页面")
我们的 safe_findtag 函数会一直去查找这个公众号这个标签,直到找到才会进入下一行代码。
第2步:点击图文消息标签
我们进入管理页面之后,先点击图文消息标签,进入素材上传页面,然后我们就可以一步步把爬下来的腾讯视频信息传上去了。
注意,我们在点击图文消息标签之前,要让浏览器最大化,以防止后续有些标签没有暴露出来,导致无法点击等操作。浏览器最大化后,我们就可以点击图文消息标签了。
# 第2步:点击图文消息标签 wxdriver.maximize_window() safe_click(safe_findtag(wxdriver, "图文消息", '//*[@id="app"]/div[2]/div[4]/div[2]/div/div[1]'))
如果大家懒得去分析定位某个标签,可以使用 chrome 浏览器自动的 xpath 定位功能,如下图。
第3步:切换tab页
我们发现点击图文消息后,浏览器多出一个新的 tab 页,此时,我们需要让程序的焦点也切换到这个新的 tab 页内。方案是:我们首先查询浏览器内所有的 tab 页,当找到某个 tab 页内有请在这里输入标题标签为止(其它 tab 页没这个标签),我们就能确定已经找到素材上传页面了。
代码很简单,我们先获取浏览器内所有的 tab 页,然后写个循环对每个 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步:从数据库中读取视频信息
目前为止,我们已经进入素材上传页面了,我们的素材都已经存储在数据库中了,所以,我们首先要把数据库中存储的视频信息读取到程序中。
import pymysql gxviewdb = pymysql.connect(user='birdpython', # 登录数据库的用户名(换成你自己的) passwd='laoniao', # 登录数据库的密码(换成你自己的) db='gxview', # 要操作的数据库(换成你自己的) host='88.88.88.88', # 登录数据库的IP地址(换成你自己的) charset='utf8') # 指定编码格式为utf-8,否则显示乱码
在这里有一点大家要注意,我们读取的视频信息一定要限制还没有使用的,也就是没有上传过公众号的新的视频,而且我们只需要读取 8 条即可,上面代码是把读取的新的视频信息存储到了 viewtuple 变量中。这些视频信息包括视频名称,视频链接,图片链接等。
第5步:输入标题
我们已经把视频信息读取到程序中了,现在我们就可以使用这些信息了,首先我们先把视频名称自动输入到标题编辑框中,所以按照惯例,我们先定位该编辑框。
我们已经把 8 条数据都存储到了 viewtuple 变量中了,每条数据里面都包含了我们在公众号后台需要上传的有视频名称,视频链接,视频图片这 3 条信息。记住:我们的公众号要上传 8 次,每次都要上传3条信息,所有我们写个循环,重复 8 次即可,在循环体内我们首先上传视频名称。
for count, viewdata in enumerate(viewtuple): viewname = viewdata[2] viewlink = viewdata[3] viewimglink = viewdata[4] safe_sendkeys(safe_findtag(wxdriver, "请在这里输入标题", '//textarea[@placeholder="请在这里输入标题"]'), viewname, "输入标题失败")
第6步:插入视频链接
我们在插入视频链接之前,首先要切换到从这里开始写正文标签处,该标签是在一个 iframe 框架中,所以我们要把焦点切入到这个 iframe 中。
iframe = safe_findtag(wxdriver, "编辑文档", '//iframe[@id="ueditor_0"]') wxdriver.switch_to.frame(iframe) safe_sendkeys(safe_findtag(wxdriver, "iframe的body",Z "//body"), "", "输入空格占位失败")
在焦点切换成功后,然后我们开始模拟点击视频标签,再点击之前,按照流程要先对该页面进行分析。
点击完视频标签后,弹出一个选择视频对话框,这个对话框里面有两个选项,一个是素材库标签,令一个是视频链接标签,在此我们选择视频链接。由于默认焦点定位在素材库标签,所以我们应该让程序自动点击一下视频链接标签把焦点切换过来。
当自动点击完视频链接标签后,下面有个视频/图文网址标签,该标签对应一个编辑框,我们需要把视频链接输入到该编辑框内,然后再点击确定按钮即可完成视频链接的插入工作。
下面是我们的从点击视频链接标签到最后插入视频链接的综合代码。
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'))
第7步:插入图片
视频链接插入完成后,我们开始插入图片了,首先我们要把鼠标移动到拖拽或选择封面标签上,然后再点击从图片库中选择标签,也就是说,我们要自动化完成滑动鼠标操作和点击鼠标操作。
从现在开始,我们不在鳌述关于分析标签展示,经过这么多次的学习,我相信大家应该都聊熟于心了。还有一点需要注意,由于上传图片的操作浏览器没有露出来,在操作完成视频链接上传之后,我们还需要拉动滚动条让拖拽或选择图片标签暴露出来才能做鼠标的滑动操作。
from component_tools.scrollbar_tool import pullscrool pullscrool(wxdriver, 0.003, 0.1) safe_moveandclick(wxdriver, ("选择封面", '//span[text()="拖拽或选择封面"]'), ("从图片库选择", '//*[@id="js_cover_null"]/ul/li[2]/a'))
完成以上操作后,会弹出一个页面,图片中的今日图片选项是我们自己建立的,这个需要我们手动建立,建立的方法是点击新建分组标签,然后输入今日图片,点击确定,左边就会出现今日图片选项了,我们只需要创建一次永久生效。
今日图片选项出现后,我们就可以上传图片了,目前,我们只有图片的链接,这个时候,我们需要用程序先把图片下载到本地(我们需要在本地先创建一个文件夹来存放我们将要下载的图片),下载图片我们需要使用 requests 库,这个库同样需要下载安装,使用 pip 命令安装:
pip install -i https://mirrors.aliyun.com/pypi/simple requests
由于公众号支持的图片大小为 407*228 像素,我们还需要一个处理图片的库 PIL,同样我们使用 pip 命令安装:
pip install -i https://mirrors.aliyun.com/pypi/simple pillow
由于腾讯视频网站有反爬虫的策略,我们使用 requests 下载图片的时候,需要伪装成浏览器,我们只需要修改 headers 即可。
以上就绪工作完成后,我们就可以下载图片,修改图片大小,上传图片了,整个上传图片流程的代码如下:
import os import requests from io import BytesIO from PIL import Image 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步:保存草稿重复下一步操作
到目前为止,我们已经把爬取的视频名称,视频链接,视频图片都上传到公众号中了,我们的公众号每天最多可以上传8项这样的题材,所以剩余的7步操作都是重复的,在执行下一步重复之前,我们还需要最后一步工作,就是点击保存为草稿标签和点击新建消息标签。
有一个问题,我们怎么知道目前已经上传完成的不是最后一项,但如果是最后一项,我们则需要点击群发标签而不是点击保存为草稿标签,所以我们要做个判断,判断是否重复了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()="继续群发"]'))
当我们已经把 8 个题材都上传完成后,我们还需要更改数据库,把这些已经上传过的视频标记为已上传,以避免下次重复上传。注意:我们上传完 8 个素材,并且扫码发布出去公众号后,修改数据库才有意义,所以我们要判断用户是否发布了,如果发布的话,则会出现首页标签。
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("数据库已经修改")
目前为止我们实现了爬取腾讯视频并自动上传公众号的功能,大家的公众号粉丝超过 500人既可以加入腾讯广告,躺着数钱了。另外,我们还可以写个自动发帖的程序来推广自己的公众号,比如自动加微信群自动发帖,自动在主流论坛发帖等等。