2017年10月

爬取目标是https站点,目前环境是python2.7。

requests.get("https://blog.pucipuci.cn/checkip.php",verify=False)

报警告

/var/python2.7/lib/python2.7/site-packages/urllib3/util/ssl_.py:339: SNIMissingWarning: An HTTPS request has been made, but 

the SNI (Subject Name Indication) extension to TLS is not available on this platform. This may cause the server to present an 

incorrect TLS certificate, which can cause validation failures. You can upgrade to a newer version of Python to solve this. 

For more information, see https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
  SNIMissingWarning
/var/python2.7/lib/python2.7/site-packages/urllib3/util/ssl_.py:137: InsecurePlatformWarning: A true SSLContext object is not 

available. This prevents urllib3 from configuring SSL appropriately and may cause certain SSL connections to fail. You can 

upgrade to a newer version of Python to solve this. For more information, see 

https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
  InsecurePlatformWarning
<Response [200]>

虽然报警告,但内容还是有的。<Response [200]>

处理

pip install pyopenssl ndg-httpsclient pyasn1

安装失败
报错中有一个 No package 'libffi' found
处理

yum install libffi-devel

虽然安装失败,但无法再重新安装 必须卸载原安装的包

pip uninstall pyopenssl ndg-httpsclient pyasn1
pip install pyopenssl ndg-httpsclient pyasn1

报错:Could not find .egg-info directory in install record for cryptography>=1.9 (from pyopenssl)
处理

pip install --upgrade setuptools pip
pip uninstall pyopenssl ndg-httpsclient pyasn1
pip install pyopenssl ndg-httpsclient pyasn1

再运行

requests.get("https://blog.pucipuci.cn/checkip.php",verify=False)

还有一行警告,

/var/python2.7/lib/python2.7/site-packages/urllib3/connectionpool.py:858: InsecureRequestWarning: Unverified HTTPS request is 

being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-

usage.html#ssl-warnings
  InsecureRequestWarning)
<Response [200]>

去掉 verify=False

requests.get("https://blog.pucipuci.cn/checkip.php",verify=False)

成功

html = requests.get("https://blog.pucipuci.cn/checkip.php")
print(html.content)

输出正确内容,无警告。

客户对服务器硬重启几次,MYSQL挂了,启动不起来。
The server quit without updating PID..
试了一些常用方法无效之后,意识可能有损坏的情况。
vim my.cnf
添加 innodb_force_recovery= 1
启动mysql成功。
去掉 innodb_force_recovery= 1
重启mysql顺利成功!
然后在网站上测试了一下注册新用户,成功!
这是临时的应急的方法,有时候好好研究下 innodb_force_recovery .

这台机器不是自己的,又没付什么费用,确实不上心 ,一切几乎都是默认设置。

有时候需要些故障敲打下那些不肯在服务器和维护上出费用的人。

pc 电脑web浏览器js通过usb控制安卓手机打电话挂电话

分析与介绍

基于js/javascript通过usb数据线控制安卓手机打电话拔号或挂断的需求即浏览器通过usb数据线控制安卓手机打电话拔号或挂断的一键拔号。

技术构架: PC电脑(google浏览器,firefox浏览器,360浏览器) 的js/javascripts 通过usb数据线连接安卓手机,控制安卓手机打电话拔号或挂断。

应用场景:CRM客户管理系统,产品订单系统 等需要大量对客户进行电话访问的工作,工作人员戴上耳机,通过网页按钮一键拔号和挂断,可直接不再需要工作人员拿起电话 按键拔号 挂断电话等重复劳动。

特点:趋近于零成本,这年头安卓手机普及率非常高,即使没有,无游戏需求的通话型安卓手机,其价格也才几百元左右,客服团队增加十人,也只是加十台手机。
相对于租用传统电话呼叫中心,根据使用规模定义出 小型电话呼叫中心 中型电话呼叫中心 大型电话呼叫中心,其价格就几万至几十万不等每年。

时代背景:在以前,电脑就是电脑,电话就是电话,手机就是手机,而我们的大量客户资料管理。客户服务都是电脑端,如果不购买价格昂贵的电话呼叫中心,就需要重复的拿起电话,对着客户资料按键号码,按键呼叫,再挂断,放下电话。完成一次通话,固定得要付出1-2分钟用于非通话操作。 而安卓手机时代,就改变了这样的格局,我们能够通过只是原来百分之一的成本,就能够实现原来的需求。

原始测试界面 (号码为随便书写 )
112.jpg

视频演示: http://www.meipai.com/media/861369712

开发技术组成

html+ js+websocket ,在电脑上浏览器的权限是有限的,这是为了电脑安全而设定的规则,要在浏览器上与电脑通信 与安卓通信,那么必然是使用 websocket。

adb , adb全名Andorid Debug Bridge. 顾名思义, 这是一个Debug工具,是一个桥,实现usb连接电脑和手机的桥,在这里主要实现websocke端口转发。

websocket server ,在手机端,安卓app实现websocket的服务端,实现对websocket客户端拔号,挂断的请求响应。

程序健壮性开发

adb的运行是基于usb数据库连通的情况下,如果用户拔出了usb数据线,在下次重新插上usb数据线,adb是不会重新运行的,这里则需要实现自动化重新运行。同时,端口转发也是需要实现usb断开后连接的自动重新设置。

app需要防止异常关闭异常退出,这里需要做监控,一旦app异常关闭,则马上自动启动,避免响应拔号请求失败。

开发代码段介绍

html+ js+websocket 实现部分

function call(number){
    if(number != '10086' && number !='10010'&& number !='0'){
        var myreg = /^(((13[0-9]{1})|(15[0-9]{1})|(17[0-9]{1})|(18[0-9]{1}))+\d{8})$/;
        if(!myreg.test(number)) {
            alert('手机号码格式错误');
            return;
        }
    }
    var ws = new WebSocket('ws://127.0.0.1:50000');
    ws.onopen = function(event) {
        ws.send(number)
    };
    ws.onerror = function(event){
        alert('手机连接失败,请检查USB连接是否拔除,如果已重新连接USB,请等待一小会');
    }
    ws.onmessage = function(event) { //监听中
        var content = event.data;
        //返回输入的号码
        console.log('即将拔打:'+content)
        //用完就关
        ws.close();
    };
    ws.onclose = function(event){
        console.log('关闭连接');
    }
}

adb桥代码实现部分

@ECHO ON
C:
cd C:\android
::BY SHW 2017/09/18
::功能描述
::通用服务调用,每秒实时检查 1. USB是否连接 2.app是否已安装/安装 3.app是否已启动/启动

::检查USB连通性,通过端口转发监听是否存在
netstat -ano | findstr 127.0.0.1  | findstr 50000
IF ERRORLEVEL 1 (
    echo usb is not connect > debug.txt
    adb forward tcp:50000 tcp:8888
    adb start-server
    exit
)
::检查app是否已经安装
adb shell pm list packages telhelper | findstr "com.example.admin.telhelper"
IF ERRORLEVEL 1 (
    echo install and start > debug.txt
    ::安装并启动
    adb install -f c:\android\app20170920.apk
    adb shell am start -n com.example.admin.telhelper/com.example.admin.telhelper.MainActivity
) else (
    ::如果已经安装 检查是否运行
    adb shell "ps | grep u0_" | findstr "com.example.admin.telhelper"
    IF ERRORLEVEL 1 (
        echo install but not run > debug.txt
        adb shell am start -n com.example.admin.telhelper/com.example.admin.telhelper.MainActivity
    )
)
exit;
::-----------------------------------------

app响应电脑拔号请求或挂断请求代码

//初始化app 监听拔号请求
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        TextView t1 = (TextView)findViewById(R.id.t1);
        t1.setText("拔号服务运行中...");
        serverManager=new ServerManager();
        serverManager.Start(8888);
        Timer timer = new Timer();
        TimerTask  task = new TimerTask(){
            public void run() {
                call();
            }
        };
        timer.schedule (task, 100, 100);
        moveTaskToBack(true);

    }
    
    //拔号
    public void call(){
        if(serverManager != null) {
            if (serverManager.tel != null) {
                String tel = serverManager.tel;
                if(tel.equals("0")){ //挂断
                    serverManager.tel = null;
                    closeCall();
                }else {
                    serverManager.tel = null;
                    Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:" + tel));
                    startActivity(intent);
                }

                //删除通话记录 功能已移动到通话状态监听事件中
                /**
                ContentResolver cResolver = getContentResolver();
                Uri callUri = Uri.parse("content://call_log/calls");
                cResolver.delete(callUri, null, null);
                 **/

            }
        }
        //call(serverManager);
    }


    //挂断电话
    private void closeCall()
    {
        try
        {
            //通过反射拿到android.os.ServiceManager里面的getService这个方法的对象
            Method method = Class.forName("android.os.ServiceManager").getMethod("getService", String.class);
            //通过反射调用这个getService方法,然后拿到IBinder对象
            IBinder iBinder = (IBinder) method.invoke(null, new Object[] {TELEPHONY_SERVICE});
            ITelephony telephony = ITelephony.Stub.asInterface(iBinder);
            telephony.endCall();
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }