精华内容
下载资源
问答
  • Android自动填写验证码源码,更多请查看我的博客:https://blog.csdn.net/xiayiye5
  • AutoInputAuthCode实现Android开发中自动填写验证码功能库
  • 这是一个关于自动获取并填写验证码的demo,详情请前往博客查看http://blog.csdn.net/u014452224/article/details/53910230
  • Android自动填写验证码

    千次阅读 2015-11-25 17:27:19
    第四篇博客就来总结下项目中使用到的一个提升用户体验的功能: Android自动填写验证码 从字面上来看,很明显的可以看出它的实现流程:监听->有改变->获取信息->改变ui观察者模式 观察者模式是软件设计模式中的一...

      第四篇博客就来总结下项目中使用到的一个提升用户体验的功能: Android自动填写验证码
      从字面上来看,很明显的可以看出它的实现流程:监听->有改变->获取信息->改变ui

    观察者模式

      观察者模式是软件设计模式中的一种,在此模式中,一个目标物件管理所有相依于它的观察者物件,并且在本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供的方法来实现。此种模式通常被用来实现事件处理系统
      观察者模式Observer完美的将观察者和被观察的对象分离开,在模块之间划定接线,提高应用程序的可维护性和重用性。同时定义了对象间一种一对多的以来关系,以便一个对象的状态发生变化时,所有依赖于它的对象都得到通知并自动刷新。
    观察者:Observer将自己注册到被观察对象中,被观察对象将观察者存放在一个容器里
    被观察:当被观察者对象发生了某种变化,从容器中得到所有注册过的观察者,将变化通知观察者
    撤销观察:观察者告诉被观察者要撤销观察,被观察者从容器中将观察者去除
    ContentObserver
      内容观察者,目的是观察捕捉特定uri引起的数据库的变化,继而做一些相应的处理,类似于数据库中的触发器。
      流程如下:
      1. 创建ContentObserver派生类,重载onChange()方法处理回调。
      2. 利用context.getContentResolover() 获得ContentResolove对象,调用registerContentObserver()方法去注册
      3. 在不需要使用时(例如验证码获取成功后),调用unregisterContentObserver()取消注册

    实现

      在我们创建的SmsObserver类中,必须要实现onChange方法,这是一个检测uri是否变化的方法。
      而验证短信发来的时候,会调用两次,第一次的uri会提示raw,此时只是表示短信到了,还没有写入数据库中。而第二次变化的时候才是我们需要接收与检测的,此时才表示短信已经被写入了数据库中。
    而对于相关验证码的提取,使用正则表达式的方式,获取连续的4个数字(根据自己的需要)。
     另外,在AndroidManifest文件中添加Read_SMS的权限

    相关代码如下:

    package com.screform.mmd.customview;
    
    import android.content.Context;
    import android.database.ContentObserver;
    import android.database.Cursor;
    import android.net.Uri;
    import android.os.Handler;
    import android.util.Log;
    
    import com.screform.mmd.aty.Aty_Register;
    
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    
    /**
     * Created by lizhongquan on 15-11-18.
     * Class to Observer the sms and notify to setText in editText_IdentifyingCode
     */
    public class SmsObserver extends ContentObserver {
    
        private Context context;
        private Handler handler;
    
        /**
         * Creates a content observer.
         *
         * @param handler The handler to run {@link #onChange} on, or null if none.
         */
        public SmsObserver(Context context, Handler handler) {
            super(handler);
    
            this.context = context;
            this.handler = handler;
        }
    
        /**
         * code ChangeListener
         *
         * @param selfChange change or not
         * @param uri        the uri of event
         */
        @Override
        public void onChange(boolean selfChange, Uri uri) {
            super.onChange(selfChange, uri);
    
            Log.d("info", "SMS is changed");
            Log.d("info", uri.toString());
    
            // When the sms is coming, it will be change twice.
            // the first time change is not the one we need.
            // The sms is not writed into the database in this time
            if (uri.toString().equals("content://sms/raw")) {
                return;
            }
    
            // handle the second change
    
            // get the inboxUri
            Uri inboxUri = Uri.parse("content://sms/inbox");
    
            // query the inbox
            // get the sms
            Cursor mCursor = context.getContentResolver().query(inboxUri, null, null, null, "date desc");
    
            if (null != mCursor) {
                if (mCursor.moveToFirst()) {
                    String address = mCursor.getString(mCursor.getColumnIndex("address"));
                    String body = mCursor.getString(mCursor.getColumnIndex("body"));
    
                    Log.d("info", "address is :" + address + ", body is " + body);
    
                    if (address.equals("106900321100")) {
                        // use a regular expression to resolve and get the identifying code
                        // get the four consecutive numbers
                        Pattern pattern = Pattern.compile("(\\d{4})");
                        Matcher matcher = pattern.matcher(body);
    
                        if (matcher.find()){
                            Log.d("info", "Identifying code is " + matcher.group(0));
                            handler.obtainMessage(Aty_Register.GETSMS, matcher.group(0))
                                    .sendToTarget();
                        }
                    }
                }
            }
    
            // close mCursor
            mCursor.close();
        }
    }

    在Aty_Register.java中:

    initObserver():

     Uri uri = Uri.parse("content://sms");
     smsObserver = new SmsObserver(Aty_Register.this, handler);
     getContentResolver().registerContentObserver(uri, true, smsObserver);

    onStop()中: 取消注册

    @Override
        protected void onStop() {
            super.onStop();
            getContentResolver().unregisterContentObserver(smsObserver);
            Log.d("info", "unregister");
        }

    handler中: 更新UI

    case GETSMS:
          editText_IdentifyingCode.setText(msg.obj.toString());
          break;

    AndroidManifest:

    <uses-permission android:name="android.permission.READ_SMS" />
    展开全文
  • python自动填写验证码

    2016-11-24 03:52:52
    网上有很多自动填写图片验证码的方法,想问一下各位大神怎么自动填写简单的js生成的text类型验证码?就是在网页源代码上就能找到的四位数字验证码
  • 爬虫学习_selenium自动填写验证码

    千次阅读 2019-08-27 23:34:40
    爬虫学习_selenium自动填写验证码介绍一哈项目第一步 打开网站第二步 获取验证码图片第二步 获取验证码图片第三步 识别验证码如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右...

    介绍一哈

    最近在跟着静觅大神。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。的书、博客学习爬虫,准备学学写写记录一下。希望可以跟各位互相学习一下(抱拳)

    项目

    在学习了tesseract识别验证码后,准备用selenium + tesserocr写个中国知网的自动填写验证码
    网站地址: 点我点我.

    页面如下:
    在这里插入图片描述

    第一步 打开网站

    直接用selenium打开 不多说不多说
    讲究一点 可以添加点响应时长 和 等待浏览器加载完毕的 设置

    from selenium import webdriver
    
    browser = webdriver.Chrome()
    browser.get('http://my.cnki.net/elibregister/commonRegister.aspx')
    

    第二步 获取验证码图片

    一开始的想法是 获取网页中验证码图片的地址 下载图片 再做验证码识别 然后再填入
    在这里插入图片描述
    在network中发现 CheckCode.aspx 就是验证码 那么我们就可以通过 [Request URL] 得到验证码图片地址(http://my.cnki.net/elibregister/CheckCode.aspx)
    在这里插入图片描述

    import requests
    
    headers = {
    	'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 '
                              '(KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36'
    }
    url = 'http://my.cnki.net/elibregister/CheckCode.aspx'
    
    res = requests.get(url, headers=headers)
    with open('./checkcode.png', 'wb') as f:
    	f.write(res.content)
    

    好了! 我们现在已经获取到验证码存到本地了! 只要识别之后 填入就ok了!
    但是突然想到 用selenium打开的页面中的验证码与我们自己通过url获取的验证码其实没有一毛钱关系!
    当时 还在想 有啥方法 可以 让selenium打开的页面 与 requests请求获取的验证码在同一个Session下进行
    反正就是挺憨憨的

    第二步 获取验证码图片

    没错!还是第二步。后来发现 selenium 获取验证码其实有简单粗暴的方法 就是直接截图 o(╥﹏╥)o

    		browser = webdriver.Chrome()
            browser.get('http://my.cnki.net/elibregister/commonRegister.aspx')
            browser.save_screenshot('./checkcode.png')  # 保存整个网页
            
            element = browser.find_element_by_xpath('//*[@id="checkcode"]')  # 获取验证码元素
            left = element.location['x']
            top = element.location['y']
            right = element.location['x'] + element.size['width']
            bottom = element.location['y'] + element.size['height']
            
            im = Image.open('./checkcode.png')
            im = im.crop((left, top, right, bottom))  # 切割
            im.save('./checkcode.png')
    

    第三步 识别验证码

    识别图片用到的是tesseract软件对应python中的tesserocr库
    这块不多说 首先安装部分有点小坑 需要避雷 hjtoh 的一篇博客说的挺详细 大家有问题可以对照的看看。博客地址
    其次是使用方法 涉及到很多图像的知识

    		image = Image.open(image_path)  
            image = image.convert('L')  # 将图片转为灰度图片
            threshold = 138  # 设置阈值
            table = []
            for i in range(256):
                if i < threshold:
                    table.append(0)
                else:
                    table.append(1)
    
            image = image.point(table, '1')
            image.show()
            res = tesserocr.image_to_text(image)
            result = res.replace(' ', '')
    

    总之 照着写 噼里啪啦 最终结果就出来了 中间具体原理没去研究 这段断码我们唯一要去改动只是阈值 threshold
    原始图片
    在这里插入图片描述

    比如 threshold = 138
    在这里插入图片描述
    比如 threshold = 100
    在这里插入图片描述
    又比如 threshold = 180
    在这里插入图片描述
    很明显 阈值设为 140左右时 识别效果最好
    实际设置时 根据验证码的款式 多试几个值 择优而选

    得到验证码后 填入(ps: 这种简单操作的识别下 误识别率还是很高的)

    		input = browser.find_element_by_xpath('//*[@id="txtOldCheckCode"]')
            input.send_keys(res)
    

    结束

    好了 最初设想的功能就已经全部实现了
    第一遍博客 写的有点累啊
    最后逼叨几句
    1、 个人想法是利用tesseract做验证码识别 在实际情况下可能并不多

    因为它的基础识别功能 对于验证码这块来说 还是挺弱的
    在这里插入图片描述
    验证码主体 和 干扰的竖线 灰度值不一样(不知道是不是灰度值这个词 反正就是这个意思 :干扰竖线比主体颜色淡!)所以才

    能用这个方法处理图片 以此得到 可识别的 图片

    如果碰到干扰线 跟 验证码 一个色儿的 那就去除不掉了 或者验证码 不是标准字体 那也就识别不出了

    当然可以通过深度学习 训练自己 的验证码识别 器 但可能成本有点高

    所以我猜想大多情况还是会使用 专业的验证码网站提供的 接口去做 验证的识别吧

    完整代码

    import tesserocr
    from PIL import Image
    from lxml import html
    import requests
    from selenium import webdriver
    import time
    
    
    class TestImage(object):
        def __init__(self):
            self.headers = {
                'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 '
                              '(KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36'
            }
    
            self.url = 'http://my.cnki.net/elibregister/commonRegister.aspx'
            self.check_url = 'http://my.cnki.net/elibregister/CheckCode.aspx'
    
        def check_code(self, image_path):
            image = Image.open(image_path)
            image = image.convert('L')
            threshold = 135
            table = []
            for i in range(256):
                if i < threshold:
                    table.append(0)
                else:
                    table.append(1)
    
            image = image.point(table, '1')
            image.show()
            res = tesserocr.image_to_text(image)
            result = res.replace(' ', '')
            # print(result)
            return result
    
        def login(self):
            browser = webdriver.Chrome()
            browser.get('http://my.cnki.net/elibregister/commonRegister.aspx')
            # browser = browser.get('https://www.baidu.com')
            browser.save_screenshot('bdbutton.png')
            element = browser.find_element_by_xpath('//*[@id="checkcode"]')
            print(element)
            print(element.location)  # 打印元素坐标
            print(element.size)  # 打印元素大小
            left = element.location['x']
            top = element.location['y']
            right = element.location['x'] + element.size['width']
            bottom = element.location['y'] + element.size['height']
    
            im = Image.open('./bdbutton.png')
            im = im.crop((left, top, right, bottom))
            im.save('bdbutton.png')
    
            res = self.check_code('./bdbutton.png')
            input = browser.find_element_by_xpath('//*[@id="txtOldCheckCode"]')
            input.send_keys(res)
    
    
    if __name__ == '__main__':
        test = TestImage()
        test.login()
    
    
    展开全文
  • 自动填写验证码问题

    2020-12-08 20:16:08
    <div><p>请问点击自动填写后 能否提供API触发回调呢 尝试过valuechange同样无反应 racobserve text也无回调</p><p>该提问来源于开源项目:zhwayne/WLUnitField</p></div>
  • AutoInputAuthCode是一个帮助Android开发者快速实现自动填写验证码的类库

    前言

    该类库的实现原理:《Android开发:实现APP自动填写注册验证码功能》。感兴趣的可以看下。

    项目地址:https://github.com/xiong-it/AutoInputAuthCode

    本文原创作者:MichaelX,博客地址:http://blog.csdn.net/xiong_it.转载请注明来源

    本篇文章已授权微信公众号 guolin_blog(郭霖)独家发布.


    AutoInputAuthCode使用介绍

    在Android Studio打开你的app module中的build.gradle,添加依赖:

    dependencies {
       ...
       compile 'tech.michaelx.authcode:authcode:1.0.0' // 添加依赖
       ...
    }

    如果无法下载上述依赖,可以打开你的项目根目录下的build.gradle,添加maven仓库地址

    allprojects {
        repositories {
            jcenter()
            maven { url 'https://dl.bintray.com/xiong-it/AndroidRepo'} // 添加这行
        }
    }

    示范代码

    AutoInputAuthCode是一个帮助Android开发者快速实现自动填写验证码的类库,客户端示例代码如下:

    CodeConfig config = new CodeConfig.Builder()
                            .codeLength(4) // 设置验证码长度
                            .smsFromStart(133) // 设置验证码发送号码前几位数字
                            //.smsFrom(1690123456789) // 如果验证码发送号码固定,则可以设置验证码发送完整号码
                            .smsBodyStartWith("百度科技") // 设置验证码短信开头文字
                            .smsBodyContains("验证码") // 设置验证码短信内容包含文字
                            .build();
    
    AuthCode.getInstance().with(context).config(config).into(EditText);
    1. 通过单例获取一个AuthCode对象;
    2. 提供一个上下文对象给AuthCode,放心,我会妥善处理你的上下文;
    3. 提供一个你的验证码特征描述;
    4. 告诉AuthCode你想将验证码写入哪个EditText.

    搞定,收工!

    效果图

    注意事项

    自动填写验证码需要读取短信权限,请在清单中添加权限:

    <uses-permission android:name="android.permission.RECEIVE_SMS"/>
    <uses-permission android:name="android.permission.READ_SMS"/>

    由于读取短信在API 23(Android 6.0)上权限级别是dangerous。所以还需要动态申请权限,但是申请权限需要依赖于Activity或者Fragment中的onRequestPermissionsResult()回调,所以需要开发者自己实现。

    可参考AutoInputAuthCode中sample的代码。

    该库实现原理请参考:《Android开发:实现APP自动填写注册验证码功能》

    总结

    该库实际上被完成有一段时间了,一直在试着上传jcenter,有空把上传代码到jcenter总结下发出来,虽然上传jcenter在网上教程挺多的,但是很多都不够细节,容易误解,我就是被坑的一个。

    祝大家撸码愉快!
    项目地址:https://github.com/xiong-it/AutoInputAuthCode

    展开全文
  • 传智播客_Andorid_20天精通Android开发视频_第11天视频_视频_11_自动填写验证码完成.avi
  • 传智播客_Andorid教程_20天从零到精通Android开发视频_第11天 11_自动填写验证码完成
  • 一个小功能实现短线验证码自动填写功能。 拿到这个功能时,首先需要怎么去拦截获取手机短信。就用观察着来观察系统里的短消息的数据库的变化,“表“内容观察者,只要数据库发生变化,都会出发该ContentObserver ...

    一个小功能实现短线验证码验自动填写功能。

    拿到这个功能时,首先需要怎么去拦截获取手机短信。就用观察着来观察系统里的短消息的数据库的变化,“表“内容观察者,只要数据库发生变化,都会出发该ContentObserver 的派生类。

      于是,首先需要一个SMSContentObserver的监听类:

    import android.content.Context;
    import android.database.ContentObserver;
    import android.database.Cursor;
    import android.database.CursorIndexOutOfBoundsException;
    import android.net.Uri;
    import android.os.Handler;
    import net.panatrip.debugtoolbox.log.Log;
    
    import net.panatrip.biqu.manager.SMSManager;
    
    import java.lang.ref.WeakReference;
    
    
    //用来观察系统里短消息的数据库变化  ”表“内容观察者,只要信息数据库发生变化,都会触发该ContentObserver 派生类  
    public class SMSContentObserver extends ContentObserver {
        private static String TAG = "SMSContentObserver";
        private WeakReference<Context> mContext;
        private Handler mHandler;   //更新UI线程
    
        public SMSContentObserver(Context context, Handler handler) {
            super(handler);
            mContext = new WeakReference<Context>(context);
            mHandler = handler;
        }
    
        /**
         * 当所监听的Uri发生改变时,就会回调此方法
         *
         * @param selfChange 此值意义不大 一般情况下该回调值false
         */
        @Override
        public void onChange(boolean selfChange) {
            //查询收件箱里的内容
            Uri outSMSUri = Uri.parse("content://sms/inbox");
            Cursor c = mContext.get().getContentResolver().query(outSMSUri, null, null, null,"date desc");
            if (c != null && c.moveToFirst()) {
                try{
                    Log.e(TAG, "the number of send is" + c.getString(c.getColumnIndex("address")) + "  " + c.getString(c.getColumnIndex("body")));
                    StringBuilder sb = new StringBuilder();
                    sb.append(c.getString(c.getColumnIndex("body")));
                    mHandler.obtainMessage(SMSManager.MSG_OUTBOXCONTENT, sb.toString()).sendToTarget();
                }catch (CursorIndexOutOfBoundsException ex){
                    ex.printStackTrace();
                }finally {
                    c.close();
                }
            }
        }
    
    }  
    然后,我们需要一个接口回调去把拦截消息显示出去,需要一个开关去接受消息和关闭消息

    public class SMSManager {
        private SMSContentObserver smsContentObserver;
        public static int MSG_OUTBOXCONTENT = 2;
        public static String ACTION = "android.provider.Telephony.SMS_RECEIVED";
        private static volatile SMSManager _instance = null;
        private IntentFilter intentFilter;
        private boolean startFlag = false;
        private  MessageListener mMessageListener;
    
        //回调接口
        public interface MessageListener {
            public void onReceived(String message);
        }
    
        private Handler mHandler = new Handler() {
    
            public void handleMessage(Message msg) {
                String outbox = (String) msg.obj;
                mMessageListener.onReceived(outbox);
            }
        };
    
        private SMSManager(){
    
        }
    
        public static SMSManager getInstance() {
            if (_instance == null) {
                synchronized (SMSManager.class) {
                    if (_instance == null) {
                        _instance = new SMSManager();
                    }
                }
            }
            return _instance;
        }
    
        /**
         * 开始接收
         *
         * @param context
         */
        public void startReceiveSMS(Context context,MessageListener listener) {
            smsContentObserver = new SMSContentObserver(context, mHandler);
            mMessageListener = listener;
            Uri smsUri = Uri.parse("content://sms");
            context.getContentResolver().registerContentObserver(smsUri, true,smsContentObserver );
        }
    
    
        /**
         * 停止接收
         *
         * @param context
         */
        public void stopReceiveSMS(Context context) {
    
          if(smsContentObserver!=null) {
                context.getContentResolver().unregisterContentObserver(smsContentObserver);
                smsContentObserver=null;
            }
        }
    
    
    
    
    
    页面的调用
    

        SMSManager.getInstance().startReceiveSMS(getApplicationContext(), new SMSManager.MessageListener() {
            @Override
            public void onReceived(String message) {
                String code = BQUtils.patternCode(message);
                etCode.setText(code);
            }
        });
    }




    展开全文
  • 就感觉挺麻烦的,所以就搞了个自动查询吧. 待解决问题: 如何访问学校教务系统网站,获取数据.一开始我是想采用http协议get,post直接获取html数据的…不过实在有点懒了,还是直接用之前就用过的selenium库吧. 验证码...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 623
精华内容 249
关键字:

自动填写验证码