python制作网易账号余额查询工具
来源:互联网 发布:淘宝的昵称有什么用 编辑:程序博客网 时间:2024/04/28 01:18
制作一个自动登录,手动滑动验证码,自动读取余额的工具,完成后再做验证码识别的部分。
先展示一下完成的结果。
github地址:https://github.com/TechKuki/NeteastBalance
实现自动登录
python自带的tkinter框架没有能够支持展示网页的控件,查询到python开发gui程序还可以使用wxPython,PyQt,PySide等。
这里我们使用PyQt5,使用 pip3 install PyQt5
安装。安装完成后PyQt5的版本是5.9。
正常思路是寻找登录的接口,然后post数据上去,但是找了好久只找到要post的地址,没找到怎么生成post数据。这里如果有大佬研究过了请指教一下。
换一种思路,操作js代码进行登录。
浏览器里打开http://ecard.163.com/index_login?refer_uri=%2Findex,然后F12,进入Console,执行 document.getElementById('dologin').click()
可以看到模拟了登录的点击操作。
然后来找一找PyQt中向页面执行js代码的接口,查询到QWebEngineView的runJavaScript函数可以执行,但是这个函数只能操作打开的页面的dom对象,而登录要操作的文本框、按钮等在一个iframe当中,无论怎么写js代码都操作不到,这里卡住了。继续在api里找,找到QWebEngineScript的setRunsOnSubFrames看起来像是可以在iframe中执行代码,写几行代码实验了下果然可以。
写js的时候又发现,网页中的某些东西是动态加载进来的,我们的js执行的时候有可能网页还没加载完,所以这里用了一个计时器。
关键代码:
# -*- coding: utf-8 -*-import sysfrom PyQt5.QtCore import QUrlfrom PyQt5.QtWidgets import QApplicationfrom PyQt5.QtWebEngineWidgets import QWebEngineView, QWebEngineScriptapp = QApplication(sys.argv)browser = QWebEngineView()browser.load(QUrl("http://ecard.163.com/account/query_balance"))script = QWebEngineScript()script.setInjectionPoint(QWebEngineScript.Deferred)script.setRunsOnSubFrames(True)script.setSourceCode(""" var box = document.getElementById('cnt-box'); if(box){ function interFunc(){ if(box.children.length == 4 && document.getElementById('nerror').children.length == 2){ clearInterval(interId); email = document.getElementsByName('email');email[0].value='username@163.com'; password = document.getElementsByName('password');password[0].value='password'; document.getElementById('dologin').click(); } } var interId = setInterval(interFunc, 100); }""")browser.page().scripts().insert(script)browser.show()sys.exit(app.exec_())
实现查询数据
这里同样通过执行js的方式实现,在浏览器的开发者工具中找到需要提取的部分,然后使用QWebEnginePage的loadFinished信号。
关键代码:
def js_callback(balance): print(balance)def load_finished(isOk): if isOk: if page.requestedUrl() == QUrl("http://ecard.163.com/handle_query_verify"): page.runJavaScript("document.getElementsByClassName('red bold')[2].innerText", js_callback) else: print("load error")page.loadFinished.connect(load_finished)
实现连续查询
因为有多个账号需要查询余额,所以我们要实现在查询完一个账号后继续查询下个账号。这一步我将代码封装成了一个类,连续查询的逻辑没什么好讲的,直接上代码。
class Balance(QWebEngineView): def __init__(self, accounts): #... def loadFinished(self, isOk): #... def jsCallback(self, balance): self.index = self.index + 1 print(balance) self.startQuery() def startQuery(self): if self.index < len(self.accounts): self.load(self.urlLogin)if __name__ == "__main__": accounts = [('user1@163.com', 'password'), ('user2@163.com', 'password'), ('user3@163.com', 'password')] app = QApplication(sys.argv) balanceView = Balance(accounts) balanceView.startQuery() balanceView.show() sys.exit(app.exec_())
调整验证码显示
到上一步已经实现了查询工具的主要逻辑,但是因为我们是直接将网页加载进来,页面上有很多多余的内容十分碍眼,而且登录界面的验证码和查询界面的验证码不在一个位置,每次查询需要拖动view的滚动条且鼠标移动的距离非常远,导致使用体验非常差。
这一步我们把页面上多余的内容全部删除或者隐藏,调整验证码显示的位置,做到页面上只显示关键部分。
在chrome的开发者工具上逐个元素的删除调整,将有调整的元素都记录下来,这里需要有一丢丢的css知识。最后关键代码如下。
def loadFinished(self, isOk): if isOk: requestedUrl = self.page().requestedUrl() if requestedUrl == self.urlLogin: self.page().runJavaScript(""" //#footer,#header,#urs_tab,#phone_tab删掉 $('#footer').remove() $('#header').remove() $('#urs_tab').remove() $('#phone_tab').remove() //.nowbg的class属性删掉 $('.nowbg').removeAttr('class') //#wrap的min-width属性去掉 $('#wrap').css('min-width', 'initial'); //#center的width属性去掉 $('#center').css('width', 'initial'); //#login的border-top,height,position,right,top属性去掉,加margin:auto; $('#login').css('border-top', 'initial'); $('#login').css('height', 'initial'); $('#login').css('position', 'initial'); $('#login').css('right', 'initial'); $('#login').css('top', 'initial'); $('#login').css('margin', 'auto'); """) elif requestedUrl == self.urlVerify: self.page().runJavaScript(""" //#footer,#header,.situation删掉 $('#footer').remove() $('#header').remove() $('.situation').remove() //#wrap的min-width属性去掉 $('#wrap').css('min-width', 'initial'); //#main的width属性去掉 $('#main').css('width', 'initial'); //.mb-content的margin: 100px auto 78px auto; $('.mb-content').css('margin', '100px auto 78px auto') """) elif requestedUrl == self.urlBalance: self.page().runJavaScript("document.getElementsByClassName('red bold')[2].innerText", self.jsCallback) else: print("load error")if __name__ == "__main__": #... balanceView.resize(360, 363) #...
到这里工具已经基本可用了,调整完后使用的界面如下:
验证码拖动后自动点击确定
每次拖完验证码后还需要再点一下按钮,这个点按钮的工作也可以让js来做。验证码验证成功后右边会出现一个绿色的对勾,通过检查这个对勾是否存在来确定点击按钮的时机。关键代码如下。
//登录界面function verifyFunc(){ if(document.getElementsByClassName('u-suc').length == 2){ clearInterval(verifyId); document.getElementById('dologin').click(); }}var verifyId = setInterval(verifyFunc, 100);//查询界面function verifyFunc(){ if($('.TxtStatus').children().length == 1){ clearInterval(verifyId); $('#query_verify_form').submit(); }}var verifyId = setInterval(verifyFunc, 100);
查询结果展示到窗体上
查询结果目前都是直接打印到控制台里,查看起来十分不方便,这一步我们把查询结果显示在一个表格上。并且整理了下界面的显示。
表格代码:
# -*- coding: utf-8 -*-from PyQt5.QtWidgets import QTableWidget, QTableWidgetItem, QAbstractItemView, QHeaderViewclass BalanceTable(QTableWidget): def __init__(self): QTableWidget.__init__(self) self.setEditTriggers(QAbstractItemView.NoEditTriggers) self.setColumnCount(2) self.horizontalHeader().setSectionResizeMode(0, QHeaderView.Stretch) self.horizontalHeader().setSectionResizeMode(1, QHeaderView.ResizeToContents) self.setHorizontalHeaderLabels(["账号", "余额"]) def addItem(self, account, balance): rowCount = self.rowCount() self.insertRow(rowCount) self.setItem(rowCount, 0, QTableWidgetItem(account)) self.setItem(rowCount, 1, QTableWidgetItem(balance))
之前的回调函数处理成调用BalanceTable的addItem函数。
class BalanceView(QWebEngineView): #... def jsCallback(self, balance): if self.queryCallBack: self.queryCallBack(self.accounts[self.index][0], balance) self.index = self.index + 1 self.startQuery() #... def startQuery(self, queryCallBack=None): if queryCallBack: self.queryCallBack = queryCallBack #...class Neteast(QWidget): def startQuery(self): if self.accounts: self.balanceView.startQuery(self.queryCallBack) def queryCallBack(self, account, balance): self.balanceTable.addItem(account, balance)
增加查询进度条
进度条的使用比较简单,我们要用到的只有2个函数。
progressBar = QProgressBar()progressBar.setTextVisible(False)progressBar.setValue(val)vboxLayout.addWidget(progressBar)
账号密码提出到单独文件
账号和密码直接写到代码里看起来总有那么一点不舒服,最后一步我们把账号单独放在一个文件里。
#neteast.pyif __name__ == "__main__": from account import accounts #...#account.pyaccounts = [('user1@163.com', 'password'), ('user2@163.com', 'password'), ('user3@163.com', 'password')]
最后完成的代码可以在github上查看。
- python制作网易账号余额查询工具
- 【机房】余额查询
- python域名查询工具
- python selenium 自动化查询上海公交卡余额,并邮件通知
- Python 实现火车票查询工具
- Python 实现火车票查询工具
- PY2exe-python的exe制作工具
- android 深圳通余额查询widget
- 公交余额查询(深圳通)
- 机房收费系统之余额查询
- 使用PHP,实现查询天府通余额
- [第一次机房收费系统]查询余额优化
- 机房收费系统之查询余额
- 机房收费-查询-查看学生余额
- 机房系统——查询余额窗体
- 金蝶EAS,后台代码查询科目余额,SQL查询科目余额
- 【详解】Python写入账户余额Excel表
- 账号密码泄密查询
- Python基础-函数
- linux下的FTP服务
- 看完这些,你就知道为什么Xmanager这么好用?
- Python基础-类和对象
- 第七周作业
- python制作网易账号余额查询工具
- springSecurity(1)---入门示例
- 多维数组
- 如何让 Vim 成为我们的神器
- 17素材网 素材或源码 免费下载
- 【备忘】年薪50万2017年最新北风网Spark2.0从入门到精通教程
- 基于JQuery实现相同内容合并单元格的代码
- AI程序员双11省钱攻略——老铁们走一波~
- 超越ImageNet?李飞飞力赞高徒的视频描述研究入选计算机视觉最前沿的十大论文