• 利用phantomjs模拟QQ自动登录


    之前为了抓取兴趣部落里的数据,研究了下QQ自动登录。

    当时搜索了一番,发现大部分方法都已经失效了,于是准备自己开搞。

    第一个想到的就是参考网上已有方案的做法,梳理登陆js的实现,通过其他语言重写。
    考虑到js可能会更新,放弃了此方案。

    第二个想到的是能不能直接调用QQ自己的js方法,模拟进行提交呢。
    搜索一番后发现神器 ———— "phantomjs".

    PhantomJS is a headless WebKit scriptable with a JavaScript API. It has fast and native support for various web standards: DOM handling, CSS selector, JSON, Canvas, and SVG.

    于是开搞,代码实现如下。

    var page = require('webpage').create();
    var fs = require("fs");
    page.settings.userAgent = 'Mozilla/5.0 (iPhone; CPU iPhone OS 8_0 like Mac OS X) AppleWebKit/600.1.3 (KHTML, like Gecko) Version/8.0 Mobile/12A4345d Safari/600.1.4';
    page.open('http://ui.ptlogin2.qq.com/cgi-bin/login?pt_no_onekey=1&style=9&appid=1006102&s_url=http%3A%2F%2Fxiaoqu.qq.com%2Fmobile%2Fbarindex.html%3F_lv%3D29313%26_bid%3D128%26_wv%3D1027%26from%3Dshare_link%23bid%3D37469%26type%3D%26source%3Dindex%26scene%3Drecent%26from%3Ddongtai%26webview%3D1&low_login=0&hln_css=http%3A%2F%2Fpub.idqqimg.com%2Fqqun%2Fxiaoqu%2Fmobile%2Fimg%2Fnopack%2Flogin-logo.png', function(status){
        if (status == 'success') {
            page.render('index.png');
            setTimeout(function() {
                page.evaluate(function() {
                    document.getElementById('u').value = 'QQ号码';
                    document.getElementById('p').value = 'QQ密码';
                    pt.check(false);
    //document.getElementById('go').click(); //pt.check()或.click() }); setTimeout(
    function() { file = fs.open("cookie.log", 'w'); file.write(JSON.stringify(page.cookies)); file.close(); phantom.exit(); }, 2000); }, 1000); } });

    cookie会写入到当前目录下的cookie.log文件,有了cookie接下来的事情就简单多了。使用php或js将cookie种到浏览器下即可。

     优化后的qq.js代码:

    /**
     * QQ自动登录,用phantomjs模拟浏览器,自动登录到QQ兴趣部落
     * @example 执行方式:cd /phantom && ./phantomjs qq.js QQ号 QQ密码
     * phantomjs下载:http://phantomjs.org/download.html
     * 安装依赖(重要,否则会报错):
     * sudo yum install fontconfig freetype libfreetype.so.6 libfontconfig.so.1 libstdc++.so.6
     */
    var page = require('webpage').create();
    var fs = require("fs");
    var args = require('system').args;
    
    page.settings.userAgent = 'Mozilla/5.0 (iPhone; CPU iPhone OS 8_0 like Mac OS X) AppleWebKit/600.1.3 (KHTML, like Gecko) Version/8.0 Mobile/12A4345d Safari/600.1.4';
    page.open('http://ui.ptlogin2.qq.com/cgi-bin/login?pt_no_onekey=1&style=9&appid=1006102&s_url=http%3A%2F%2Fxiaoqu.qq.com%2Fmobile%2Fbarindex.html%3F_lv%3D29313%26_bid%3D128%26_wv%3D1027%26from%3Dshare_link%23bid%3D37469%26type%3D%26source%3Dindex%26scene%3Drecent%26from%3Ddongtai%26webview%3D1&low_login=0&hln_css=http%3A%2F%2Fpub.idqqimg.com%2Fqqun%2Fxiaoqu%2Fmobile%2Fimg%2Fnopack%2Flogin-logo.png', function(status){
        if (status == 'success') {
            page.render('index.png');
            setTimeout(function() {
                page.evaluate(function(_args) {
                    document.getElementById('u').value = _args[1]; //QQ号码
                    document.getElementById('p').value = _args[2]; //QQ密码
                    pt.check(false);
                }, args); //要使用传参的形式将全局变量args传入到page.evaluate()
                setTimeout(function() {
                    //将cookie转换成json格式写入到cookie.log文件
                    //file = fs.open("cookie.log", 'w');
                    //file.write(JSON.stringify(page.cookies));
                    //file.close();
    
                    //将cookie转换成json格式打印出来
                    console.log(JSON.stringify(page.cookies));
                    
                    phantom.exit(); //记得退出
                }, 2000);
            }, 1000);
        }
    });

    qq.js也可以使用以下代码进行自动登录:

    page.open('https://ui.ptlogin2.qq.com/cgi-bin/login?style=9&appid=1006102&daid=0&s_url=http%3A%2F%2Fid.qq.com&low_login=0', function(status){
        if (status == 'success') {
            //page.render('index1.png'); //截屏,为了调试使用
            setTimeout(function() {
                page.evaluate(function(_args) {
                    document.getElementById('u').value = _args[1]; //QQ号码
                    document.getElementById('p').value = _args[2]; //QQ密码
                    document.getElementById('go').click(); //pt.check()或.click()
                }, args); //要使用传参的形式将全局变量args传入到page.evaluate()
                setTimeout(function() {
                    //将cookie转换成json格式写入到cookie.log文件
                    //file = fs.open("cookie.log", 'w');
                    //file.write(JSON.stringify(page.cookies));
                    //file.close();
    
                    //将cookie转换成json格式打印出来
                    console.log(JSON.stringify(page.cookies));
                    //page.render('index.png'); //截屏,为了调试使用
     //console.log(page.content);  phantom.exit(); //记得退出 }, 2000); }, 1000); } });

    php调用phantomjs代码:

        public function actionQqLogin() {
            $ret = false;
            $qq = 'QQ号';
            $pwd = 'QQ密码';
            
            $command = "cd /phantom/ && ./phantomjs qq.js {$qq} {$pwd}";
            $cookie_json = @exec($command);  //只返回最后一行
            //echo $cookie_json.'<br/><br/>';  //test
            if ($cookie_json) {
                $cookie_arr = json_decode($cookie_json, true);
                //print_r($cookie_arr); //test
                if ($cookie_arr) {
                    foreach ($cookie_arr as $cookie) {
                        //echo $cookie['value'].'  ';
                        //注意:不要用setcookie(),用setrawcookie()不会对cookie value进行url编码
                        $ret = setrawcookie($cookie['name'], $cookie['value'], $cookie['expires'], '/', $cookie['domain']);
                    }
                }
            }
            if ($ret) {
                echo '登录成功!';
            }
            
            //return $ret;
        }
    附:
    下载phantomjs的Windows版本:http://phantomjs.org/download.html
    在当前文件夹下运行cmd命令:
    1. 在桌面上先按住Shift键,然后鼠标右键,出现选项“在此处打开命令窗口(W)”也可以打开命令行。
    2. 点击“在此处打开命令窗口(W)”,进入CMD命令行界面。
     
    参考文章:
    利用phantomjs模拟QQ自动登录:https://www.liudon.org/1327.html
    QQ模拟登录实现之四两拨千斤(基于V8引擎):http://ju.outofmemory.cn/entry/246396
    PhantomJS在Windows7下实现网站自动下载截图(包含PhantomJS在Windows7下的安装):http://www.cnblogs.com/huangcong/archive/2013/04/18/3027654.html
    Linux服务器安装PhantomJS使用方法:http://www.111cn.net/sys/linux/103737.htm
    编译好的Linux下phantomjs文件下载:https://bitbucket.org/ariya/phantomjs/downloads
    php结合phantomjs实现网页全屏截图:http://www.oicqzone.com/pc/2014091319762.html
    phantomjs装配(linux,附带环境变量设置) ,以及casperjs安装:http://www.myexception.cn/linux-unix/1756766.html
     
    如何把全局参数传递给 phantomjs 的 page.evaluate 方法:
    phantomjs是一个无界面浏览器,可用于网页截图和前端自动化测试,基于
    webkit内核(也就是chrome使用的内核),并使用js编写业务脚本来请求、浏览和操作页面。最近前端监控需要用到phantomjs,特地研究
    了一下这个组件,把其中一个大坑发出来给大家分享一下。
    
    !!!!注意page.evaluate中的回调函数作用域链
    
    page.evaluate中的函数是在目标网页执行的,其上下文、作用域链已经不能与phantomjs执行这个js同日而语,因此请勿在evaluate中引用phantomjs的api或你这个js文件中的全局变量,否则出了错,都很难定位。
    
    错误示例:
    
    [javascript] view plain copy
    var page = require('webpage').create();  
    var url = 'http://json2form.wikisoft.me//';  
    var globalVar = 1;  
    page.open(url, function (status)   
    {  
        if (status != "success")   
        {  
            console.log('FAIL to load the address');  
        }  
          
        page.evaluate(function()  
        {  
            var x = globalVar;//引用本js的一个全局变量  
            page.method();//执行phantomjs的一个api  
        });  
    });  
    
    正确引用全局变量的方法是把全局变量进行传参
    
    [javascript] view plain copy
    var express = require('express');  
    var router = express.Router();  
    var mysql = require('mysql');  
    var phantom = require('phantom');  
    
    /* GET home page. */  
    router.get('/', function (req, res, next) {  
        var pageContent,  
            paraObj = {title: 'lalala3', content: 'notenote3'};  
      
        phantom.create().then(function (ph) {  
            ph.createPage().then(function (page) {  
                page.open('http://www.baidu.com/').then(function (status) {  
                    page.evaluate(function (_paraObj) {  
                        var desObj = {};  
                        desObj.title = _paraObj.title;  
                        desObj.note = _paraObj.content;  
                        return desObj;  
                    }, paraObj).then(function (_desObj) {  
                        //console.log(html);  
                        res.render('index', {title: _desObj.title, content: _desObj.note});  
                        page.close();  
                        ph.exit();  
                    });  
                });  
            });  
        });  
      
    });  
      
    module.exports = router;
     
     
     
  • 相关阅读:
    数据结构与算法之美-二分查找(下)
    数据结构与算法之美-二分查找(上)
    数据结构与算法之美-排序优化
    数据结构与算法之美-线性排序
    DRF框架之路由Routers
    DRF框架之视图集(ModelViewSet)简介
    DRF框架之视图子类简介
    DRF框架之视图的扩展类简介
    DRF框架之视图基类APIView和GenericAPIView简介
    DRF框架之ModelSerializer序列化器
  • 原文地址:https://www.cnblogs.com/imxiu/p/6023930.html
Copyright © 2020-2023  润新知