linux 模拟浏览器请求 - CSDN
  • linux环境下,手工模拟浏览器请求,手工拼装http请求 。使用nc命令 先安装nc,切换到root用户:yum install -y nc 安装成功后 先发起个请求nc www.baidu.com 80 -v 然后输入请求行 GET / HTTP/1.0 Host:...

    linux环境下,手工模拟浏览器请求,手工拼装http请求 。使用nc命令

    先安装nc,切换到root用户:yum install -y nc

    安装成功后

    先发起个请求nc www.baidu.com 80 -v

    然后输入请求行

    GET / HTTP/1.0

    Host:www.baidu.com

    最后远程服务器会给你返回许多东西

    展开全文
  • 目前的想法是,linux下有没有什么框架可以模拟浏览器,获得加载后的网页内容,再提取里面的url,或者截获加载过程中浏览器发出的http请求的url,这样应该可以确保抓取网页的完整性。另外,目前是linux下c++开发的,...
  • * 接收请求信息写入日志 * Date: 2018/12/25 */ ini_set('date.timezone', 'Asia/Shanghai'); //定义时间地点 header("Content-type:text/html;charset=utf-8"); //获取真实的ip function g...

    一、准备一个接收文件ipb.php

    1、代码:

    <?php
    /**
     * 接收请求信息写入日志
     * Date: 2018/12/25
     */
    ini_set('date.timezone', 'Asia/Shanghai');  //定义时间地点
    header("Content-type:text/html;charset=utf-8");
    
    //获取真实的ip
    function getIP()
    {
        $ip = '';
        if (getenv("HTTP_CLIENT_IP"))
            $ip = getenv("HTTP_CLIENT_IP");
        else if (getenv("HTTP_X_FORWARDED_FOR"))
            $ip = getenv("HTTP_X_FORWARDED_FOR");
        else if (getenv("REMOTE_ADDR"))
            $ip = getenv("REMOTE_ADDR");
        else $ip = "Unknow";
    
        if ($ip != "Unknow") {  //去除其他ip信息只保留用户ip
            $ip_a = strtr($ip, array(' ' => ''));
            $ip_b = explode(',', $ip_a);
            $ip   = $ip_b[0];
        }
        return $ip;
    }
    
    function index()
    {
        $browser = isset($_SERVER['HTTP_USER_AGENT']) ? strtolower($_SERVER['HTTP_USER_AGENT']) : '';
    
        //ip + 时间 + 浏览器信息 + 换行
        $data_list = "ip:【" . getIP() . "】\r\n";
        $data_list .= "time:【" . date('Y-m-d H:i:s') . "】\r\n";
        $data_list .= "browser:【" . $browser . "】";
        $data_list .= "\r\n\r\n";
    
        //创建文件名
        $xlsName = 'ip.txt';
    
        //写入文件
        $myfile = fopen($xlsName, "a");
        fwrite($myfile, $data_list);
    
        echo '<pre/>';
        echo $data_list;
        echo '成功';
    }
    
    index();
    
    ?>

    2、搭建环境通过浏览器进行访问ipb.php:

    3、查看日志文件ip.txt

    可以正常得到本机ip与浏览器信息

    二、准备一个请求文件ipa.php

    1、代码

    <?php
    /**
     * 模拟请求ip及浏览器
     * Date: 2018/12/25
     */
    
    ini_set('date.timezone', 'Asia/Shanghai');  //定义时间地点
    header("Content-type:text/html;charset=utf-8");
    
    class Script
    {
    
        function index()
        {
            //请求地址
            $curl_url = 'http://index.com/a_web_crawler/ipb.php';
    
            $ch = curl_init();
    
            //生成随机ip
            $ip = mt_rand(11, 191) . "." . mt_rand(0, 240) . "." . mt_rand(1, 240) . "." . mt_rand(1, 240);
    
            //生成浏览器
            $agent_array = [
                //PC端的UserAgent
                "safari 5.1 – MAC"             => "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11",
                "safari 5.1 – Windows"         => "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50",
                "Firefox 38esr"                => "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0",
                "IE 11"                        => "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729; InfoPath.3; rv:11.0) like Gecko",
                "IE 9.0"                       => "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0",
                "IE 8.0"                       => "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)",
                "IE 7.0"                       => "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)",
                "IE 6.0"                       => "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)",
                "Firefox 4.0.1 – MAC"          => "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0.1) Gecko/20100101 Firefox/4.0.1",
                "Firefox 4.0.1 – Windows"      => "Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1",
                "Opera 11.11 – MAC"            => "Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; en) Presto/2.8.131 Version/11.11",
                "Opera 11.11 – Windows"        => "Opera/9.80 (Windows NT 6.1; U; en) Presto/2.8.131 Version/11.11",
                "Chrome 17.0 – MAC"            => "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11",
                "傲游(Maxthon)"                  => "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Maxthon 2.0)",
                "腾讯TT"                         => "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; TencentTraveler 4.0)",
                "世界之窗(The World) 2.x"          => "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)",
                "世界之窗(The World) 3.x"          => "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; The World)",
                "360浏览器"                       => "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; 360SE)",
                "搜狗浏览器 1.x"                    => "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; SE 2.X MetaSr 1.0; SE 2.X MetaSr 1.0; .NET CLR 2.0.50727; SE 2.X MetaSr 1.0)",
                "Avant"                        => "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Avant Browser)",
                "Green Browser"                => "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)",
                //移动端口
                "safari iOS 4.33 – iPhone"     => "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_3 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5",
                "safari iOS 4.33 – iPod Touch" => "Mozilla/5.0 (iPod; U; CPU iPhone OS 4_3_3 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5",
                "safari iOS 4.33 – iPad"       => "Mozilla/5.0 (iPad; U; CPU OS 4_3_3 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5",
                "Android N1"                   => "Mozilla/5.0 (Linux; U; Android 2.3.7; en-us; Nexus One Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1",
                "Android QQ浏览器 For android"    => "MQQBrowser/26 Mozilla/5.0 (Linux; U; Android 2.3.7; zh-cn; MB200 Build/GRJ22; CyanogenMod-7) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1",
                "Android Opera Mobile"         => "Opera/9.80 (Android 2.3.4; Linux; Opera Mobi/build-1107180945; U; en-GB) Presto/2.8.149 Version/11.10",
                "Android Pad Moto Xoom"        => "Mozilla/5.0 (Linux; U; Android 3.0; en-us; Xoom Build/HRI39) AppleWebKit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13",
                "BlackBerry"                   => "Mozilla/5.0 (BlackBerry; U; BlackBerry 9800; en) AppleWebKit/534.1+ (KHTML, like Gecko) Version/6.0.0.337 Mobile Safari/534.1+",
                "WebOS HP Touchpad"            => "Mozilla/5.0 (hp-tablet; Linux; hpwOS/3.0.0; U; en-US) AppleWebKit/534.6 (KHTML, like Gecko) wOSBrowser/233.70 Safari/534.6 TouchPad/1.0",
                "UC标准"                         => "NOKIA5700/ UCWEB7.0.2.37/28/999",
                "UCOpenwave"                   => "Openwave/ UCWEB7.0.2.37/28/999",
                "UC Opera"                     => "Mozilla/4.0 (compatible; MSIE 6.0; ) Opera/UCWEB7.0.2.37/28/999",
                "微信内置浏览器"                      => "Mozilla/5.0 (Linux; Android 6.0; 1503-M02 Build/MRA58K) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/37.0.0.0 Mobile MQQBrowser/6.2 TBS/036558 Safari/537.36 MicroMessenger/6.3.25.861 NetType/WIFI Language/zh_CN",
                // ""=>"",
    
            ];
    
            //要得到类似这样useranget 可以自定义
            //$user_agent = "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11";
            $user_agent = $agent_array[array_rand($agent_array, 1)];  //随机浏览器useragent
    
            //构造ip
            $header = array(
                'CLIENT-IP:' . $ip,
                'X-FORWARDED-FOR:' . $ip,
            );
    
            curl_setopt($ch, CURLOPT_URL, $curl_url); //请求地址
            curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($ch, CURLOPT_USERAGENT, $user_agent); //模拟常用浏览器的$user_agent
    
            $page_content = curl_exec($ch);
            curl_close($ch);
    
            //打印返回信息
            echo '<per/>';
            echo $page_content;
    
        }
    
    }
    
    //运行
    $ts = new Script();
    $ts->index();
    
    ?>
    

    2、通过浏览器进行访问ipa.php:

    3、多访问几次查看ip.txt:

    完成

    展开全文
  • Linux 下curl模拟Http 的get or post请求

    万次阅读 2015-12-11 15:23:05
    一、get请求 curl "http://www.baidu.com"  如果这里的URL指向的是一个文件或者一幅图都可以直接下载到本地 curl -i "http://www.baidu.com"  显示全部信息 curl -l "http://www.baidu.com" 只显示...

    一、get请求


    curl "http://www.baidu.com"  如果这里的URL指向的是一个文件或者一幅图都可以直接下载到本地

    curl -i "http://www.baidu.com"  显示全部信息

    curl -l "http://www.baidu.com" 只显示头部信息

    curl -v "http://www.baidu.com" 显示get请求全过程解析


    wget "http://www.baidu.com"也可以


    二、post请求

    curl -d "param1=value1&param2=value2" "http://www.baidu.com"




    用途说明

    curl命令是一个功能强大的网络工具,它能够通过http、ftp等方式下载文件,也能够上传文件。其实curl远不止前面所说的那些功能,大家可以通过man curl阅读手册页获取更多的信息。类似的工具还有wget

    curl命令使用了libcurl库来实现,libcurl库常用在C程序中用来处理HTTP请求,curlpp是libcurl的一个C++封装,这几个东西可以用在抓取网页、网络监控等方面的开发,而curl命令可以帮助来解决开发过程中遇到的问题。

    常用参数

    curl命令参数很多,这里只列出我曾经用过、特别是在shell脚本中用到过的那些。

    -A:随意指定自己这次访问所宣称的自己的浏览器信息

    -b/--cookie <name=string/file> cookie字符串或文件读取位置,使用option来把上次的cookie信息追加到http request里面去。

    -c/--cookie-jar <file> 操作结束后把cookie写入到这个文件中

    -C/--continue-at <offset>  断点续转

    -d/--data <data>   HTTP POST方式传送数据

    -D/--dump-header <file> 把header信息写入到该文件中

    -F/--form <name=content> 模拟http表单提交数据

    -v/--verbose 小写的v参数,用于打印更多信息,包括发送的请求信息,这在调试脚本是特别有用。

    -m/--max-time <seconds> 指定处理的最大时长

    -H/--header <header> 指定请求头参数

    -s/--slient 减少输出的信息,比如进度

    --connect-timeout <seconds> 指定尝试连接的最大时长

    -x/--proxy <proxyhost[:port]> 指定代理服务器地址和端口,端口默认为1080

    -T/--upload-file <file> 指定上传文件路径

    -o/--output <file> 指定输出文件名称

    --retry <num> 指定重试次数

    -e/--referer <URL> 指定引用地址

    -I/--head 仅返回头部信息,使用HEAD请求

    -u/--user <user[:password]>设置服务器的用户和密码

    -O:按照服务器上的文件名,自动存在本地

    -r/--range <range>检索来自HTTP/1.1或FTP服务器字节范围

    -T/--upload-file <file> 上传文件

    使用示例

    1,抓取页面内容到一个文件中

      [root@xi mytest]# curl -o home.html http://www.baidu.com   --将百度首页内容抓下到home.html中

         [root@xi mytest]#curl -o #2_#1.jpghttp://cgi2.tky.3web.ne.jp/~{A,B}/[001-201].JPG

               由于A/B下的文件名都是001,002...,201,下载下来的文件重名,这样,自定义出来下载下来的文件名,就变成了这样:原来: A/001.JPG —-> 下载后: 001-A.JPG 原来: B/001.JPG ---> 下载后: 001-B.JPG

    2,用-O(大写的),后面的url要具体到某个文件,不然抓不下来。还可以用正则来抓取东西

      [root@xi mytest]# curl -O http://www.baidu.com/img/bdlogo.gif

             运行结果如下:

            % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                                                       Dload  Upload   Total   Spent    Left  Speed
           100  1575  100  1575    0     0  14940      0 --:--:-- --:--:-- --:--:-- 1538k

              会在当前执行目录中生成一张bdlogo.gif的图片。

      [root@xi mytest]# curl -O http://XXXXX/screen[1-10].JPG  --下载screen1.jpg~screen10.jpg

    3,模拟表单信息,模拟登录,保存cookie信息

      [root@xi mytest]# curl -c ./cookie_c.txt -F log=aaaa -F pwd=******http://www.XXXX.com/wp-login.php

    4,模拟表单信息,模拟登录,保存头信息

      [root@xi mytest]# curl -D ./cookie_D.txt -F log=aaaa -F pwd=******http://www.XXXX.com/wp-login.php

      -c(小写)产生的cookie和-D里面的cookie是不一样的。

    5,使用cookie文件

      [root@xi mytest]# curl -b ./cookie_c.txt http://www.XXXX.com/wp-admin

    6,断点续传,-C(大写)

      [root@xi mytest]# curl -C -O http://www.baidu.com/img/bdlogo.gif

    7,传送数据,最好用登录页面测试,因为你传值过去后,curl回抓数据,你可以看到你传值有没有成功

      [root@xi mytest]# curl -d log=aaaa http://www.XXXX.com/wp-login.php

    8,显示抓取错误,下面这个例子,很清楚的表明了。

      [root@xi mytest]# curl -fhttp://www.XXXX.com/asdf

      curl: (22) The requested URL returned error: 404

      [root@xi mytest]# curlhttp://www.XXXX.com/asdf

      <HTML><HEAD><TITLE>404,not found</TITLE>

    9,伪造来源地址,有的网站会判断,请求来源地址,防止盗链。

      [root@xi mytest]# curl -ehttp://localhosthttp://www.XXXX.com/wp-login.php

    10,当我们经常用curl去搞人家东西的时候,人家会把你的IP给屏蔽掉的,这个时候,我们可以用代理

      [root@xi mytest]# curl -x 24.10.28.84:32779 -o home.htmlhttp://www.XXXX.com

    11,比较大的东西,我们可以分段下载

      [root@xi mytest]# curl -r 0-100 -o img.part1http://www.XXXX.com/wp-content/uploads/2010/09/compare_varnish.jpg

      % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current

      Dload  Upload   Total   Spent    Left  Speed

      100   101  100   101    0     0    105      0 --:--:-- --:--:-- --:--:--     0

      [root@xi mytest]# curl -r 100-200 -o img.part2http://www.XXXX.com/wp-ontent/uploads/2010/09/compare_varnish.jpg

      % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current

      Dload  Upload   Total   Spent    Left  Speed

      100   101  100   101    0     0     57      0  0:00:01  0:00:01 --:--:--     0

      [root@xi mytest]# curl -r 200- -o img.part3http://www.XXXX.com/wp-content/uploads/2010/09/compare_varnish.jpg

      % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current

      Dload  Upload   Total   Spent    Left  Speed

      100  104k  100  104k    0     0  52793      0  0:00:02  0:00:02 --:--:-- 88961

      [root@xi mytest]# ls |grep part | xargs du -sh

      4.0K    one.part1

      112K    three.part3

      4.0K    two.part2

      用的时候,把他们cat一下就OK,cat img.part* >img.jpg

    12,不会显示下载进度信息

      [root@xi mytest]# curl -s -o aaa.jpg http://www.baidu.com/img/bdlogo.gif

    13,显示下载进度条

      [root@xi mytest]# curl  -0 http://www.baidu.com/img/bdlogo.gif     (以http1.0协议请求)

    ####################################################################### 100.0%

    14,通过ftp下载文件

      [xifj@Xi ~]$ curl -u用户名:密码 -Ohttp://www.XXXX.com/demo/curtain/bbstudy_files/style.css

      % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current

      Dload  Upload   Total   Spent    Left  Speed

      101  1934  101  1934    0     0   3184      0 --:--:-- --:--:-- --:--:--  7136

      [xifj@Xi ~]$ curl -u 用户名:密码 -O http://www.XXXX.com/demo/curtain/bbstudy_files/style.css

      % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current

      Dload  Upload   Total   Spent    Left  Speed

      101  1934  101  1934    0     0   3184      0 --:--:-- --:--:-- --:--:--  7136

      或者用下面的方式

      [xifj@Xi ~]$ curl -O ftp://用户名:密码@ip:port/demo/curtain/bbstudy_files/style.css

      [xifj@Xi ~]$ curl -O ftp://用户名:密码@ip:port/demo/curtain/bbstudy_files/style.css

      15,通过ftp上传

      [xifj@Xi ~]$ curl -T test.sql ftp://用户名:密码@ip:port/demo/curtain/bbstudy_files/

      [xifj@Xi ~]$ curl -T test.sql ftp://用户名:密码@ip:port/demo/curtain/bbstudy_files/

    15,模拟浏览器头

      [xifj@Xi ~]$ curl -A "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)" -x 123.45.67.89:1080 -o page.html -D cookie0001.txthttp://www.www.baidu.com

    16,PUT、GET、POST

    比如 curl -T localfile http://cgi2.tky.3web.ne.jp/~zz/abc.cgi,这时候,使用的协议是HTTP的PUT method 
    刚才说到PUT,自然想起来了其他几种methos--GET和POST。 
    http提交一个表单,比较常用的是POST模式和GET模式 
    GET模式什么option都不用,只需要把变量写在url里面就可以了
    比如:
    curl http://www.yahoo.com/login.cgi?user=nick&password=12345 
    而POST模式的option则是 -d 
    比如,curl -d "user=nick&password=12345" http://www.yahoo.com/login.cgi
    就相当于向这个站点发出一次登陆申请~~~~~ 
    到底该用GET模式还是POST模式,要看对面服务器的程序设定。 
    一点需要注意的是,POST模式下的文件上的文件上传,比如
    <form method="POST" enctype="multipar/form-data" action="http://cgi2.tky.3web.ne.jp/~zz/up_file.cgi">
    <input type=file name=upload>
    <input type=submit name=nick value="go">
    </form>
    这样一个HTTP表单,我们要用curl进行模拟,就该是这样的语法:
    curl -F upload=@localfile -F nick=go http://cgi2.tky.3web.ne.jp/~zz/up_file.cgi 

    展开全文
  • python爬虫(上)--请求——关于模拟浏览器方法

    万次阅读 多人点赞 2016-10-19 09:54:28
    前言离上一篇更新的博文应该过了挺久的了( python爬虫(上)–请求——关于旅游网站的酒店评论爬取(传参方法)),因为中间考完试紧接着就去实习的缘故,然后到新环境各种熟悉什么的,所以后面有所学到的东西就...

    前言

    离上一篇更新的博文应该过了挺久的了( python爬虫(上)–请求——关于旅游网站的酒店评论爬取(传参方法)),因为中间考完试紧接着就去实习的缘故,然后到新环境各种熟悉什么的,所以后面有所学到的东西就来不及汇总,终于在某个礼拜天的下午,喝着我的雀巢速溶咖啡,一边写着这篇总结。

    上一篇我自己也回去又看了一遍,其实上一篇的博文主要还是用的是 传参 的方法,什么叫传参的方法?就是着重点在分析交互中各种数据请求来源,然后找到我们需要的数据来源,再写个脚本把数据请求回来,最后做个提取就OK了,这种办法的优点在于执行得很快,对比于后面我要说的一种 模拟浏览器 的方法来说,在请求页面的效率上会快上很多,而传参方法的难点在于寻找数据来源的那个URL还有它尾巴的一堆参数的构建,当然简单的比如上一篇的艺龙的酒店评论的话,直接用chrome的开发者工具XHR项目里面就可以找到,但当遇到更为复杂的页面结构,或者采用更加复杂技术的页面(比如混淆代码啊,压缩代码之类的),传参这种办法的工作就变得十分繁琐,特别是在XHR里面没有找到数据来源的URL的时候,要在一堆js脚本里面找到你要的数据的请求来源的时候,你会彻底懵逼了,反正我是懵逼了好几次,而且爬虫有个真理——越是接近人的操作的爬虫越是好的爬虫。因为网站是为了人去访问而服务的,那么就算网站反爬很厉害,但是也不可能去因为爬虫而误伤了正常的用户,对于一个网站而言得不偿失,所以当我懵逼了几次以后,果断转用模拟浏览器的方法,我在这里要明确一点,传参的思路和模拟浏览器的思路是不一样的,所以要分开来认识他们


    爬虫制作总览

    经过实习这一段时间以来的学习和研究,包括对python这门语言更加深入的了解,还有对爬虫中遇到的问题的总结,我觉得大致上爬虫的制作思路如下:

    这里写图片描述
    P.s.更正上图lxml.etee为lxml.etree

    上图中需要补充的是,有时候有登录的需求,登录里面会涉及验证码的问题,其实说白了就是OCR技术的应用,还有访问过频,封IP或者是弹验证码的问题,这些都是爬虫会遇到的独特问题,不过一般按照上图的思路去做爬虫,遇到上面这些问题再相对应的做应对策略就好.

    其实爬虫好玩的地方在于与网站程序猿的之间的博弈,一般而言,没有哪个网站是希望自己的数据被爬虫爬去的,当然谷歌百度这种大的搜索引擎除外,每天都被成百上千的练手也好,娱乐也罢的大大小小的爬虫们爬网站内容,哪个服务器受得了,所以对于山那头的程序猿而言,爬虫生死之战在于把关好请求页面这一步,不让爬虫程序拿到完整静态页面;对于开发爬虫的程序猿而言,爬虫生死之战就在能否成功到达拿到完整静态文本那一步——请求页面(完整是针对动态页面而言需要完整加载出目的数据的文本),因为拿到静态文本以后,我要怎么做网站那头的程序猿就算使用洪荒之力也已经限制不了我了,这时候慢慢做提取都可以,请求页面就是前言里面说的两种办法:传参or模拟浏览器.

    【P.s.传参和模拟浏览器最大的不同是获取数据的地方不一样。传参让人感觉更加底层,就是有点贴近http协议的那种底层,总给人一种要做非常细致推敲工作的过程的感觉,传参取得数据的地方就是你所请求的URL返回的文本,而难就难在这个URL怎么构造才能骗过山那头的各种脚本顺利请求回包含目的数据的源码; 而模拟浏览器的办法,就有点取巧,但是却是面对现在越来越复杂的网站架构技术的最佳办法,也是最贴合人操作浏览器这种想法的方法(最不容易被封),模拟浏览器操作的办法取得数据的地方是浏览器的内核,因为模拟浏览器方法的核心思想是:无论你中间技术怎么复杂,怎么变化,你最终还是要在浏览器内核中渲染好加载好数据来呈现给用户,而渲染好加载好后的必定是一个静态文本,那么我直接拿这个静态文本再提取数据就好了。模拟浏览器操作的方法虽然比传参的方法慢,但是胜在它稳,而且爬取思路非常清晰简单:D】


    模拟浏览器动作

    模拟浏览器的方法其实就是把一个人每天到目的网站上复制黏贴目的数据的过程用程序和机器实现,这过程为:用浏览器打开网站→输入信息和提交等动作→浏览器请求相关网页→浏览器渲染返回信息→人把渲染出来的信息复制黏贴保存系下来.

    这样日复一日,每天都重复一样的机械性 的动作,这毫无疑问是很低效的,但是却是最保险稳定的,因为被封IP的几率很小,甚至可以忽略不计,但是估计这个人得累死,那么我们这些懒鬼当然希望能够让机器帮助我们实现日复一日的这样机械的过程,那么就得模拟这一个过程,这里我们要用到selenium来模拟人来操作浏览器。

    (1)模拟登陆–Selenium

    首先是模拟用户登录,以登录后的状态去请求接下来的页面,因为项目内容保密的缘故,一些信息不方便透露,不过单纯用到的技术还有思想还是可以分享一下的

    Q:为什么最好用登录后状态去请求数据?
    A:(收集自网上的回答)
    1.一方面可能是因为你要的数据在登录后才有,比如微博;
    2.另外一方面也可能是因为你需要会员登录获得优惠的价格信息;
    3.而从单纯的技术的角度的来说,用登录状态来爬是有好处的:
    ①携程网站对于爬虫的频率是有限制的,爬取频率过高,服务器会返回429错误,此时如果没有登录用户无法正确获取数据;
    ②建议:登录账号后利用Cookie进行数据的爬取,虽然登录后过于频繁请求也会导致429错误(python的话20线程10min就会出现),但只要等3min就可以继续快乐地爬取了,而且爬取的数据不会出错,而不登录会数据出错
    ③而值得注意的是,用账号登录之后生成的Cookie不到几个小时就会失效

    模拟用户登录在很久以前还没有验证码的时候还是很简单的,特别是配合selenium的情况下是非常容易做到的,但是自从山那头的程序猿们发明和发展了验证码后,模拟用户登录就没有那么容易了

    补充:关于selenium安装,pip install也可以,apt-get install 也可以,通过pip 安装的都是比较新的版本,而且扯多一句,用pip的话还可以安装一些历史版本,而apt-get是系统安装过的方法,这样安装的永远只有一个版本,但是是比较稳定的版本而且是全局的,但是apt-get有时候会出现一些奇奇怪怪的问题,所以我的建议是如果原来系统里面已经安装的python-xxxxx的库你就可以不用管它,接下来你要新安装的库尽可能都用pip统一管理,还有,无论是pip安装的库还是apt-get安装的库,都会显示在pip list命令打印出来的已安装列表里面,所以有时候你pip uninstall了的库,还会在pip list里面打印出来的原因是因为你的系统自己本身也有一个这样的库,这个系统级的py库你用pip来卸载是卸载不了的.
    (库,模块都是指module,要特别注意,别以为python的库和模块是两码事就好)

    ①没有验证码情况

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    
    from selenium import webdriver
    
    #这里用有GUI界面的Firefox为例子,当然你喜欢Chome,这里换成Chrome也可以
    #构造模拟浏览器
    firefox_login=webdriver.Firefox()
    #Chrome_login=webdriver.Chrome()
    
    #打开网址
    firefox_login.get('###你的URL地址###')
    firefox_login.maximize_window()#窗口最大化,可有可无,看情况
    
    #输入账户密码
    #我请求的页面的账户输入框的'id'是username和密码输入框的'name'是password
    firefox_login.find_element_by_id('username').clear()
    firefox_login.find_element_by_id('username').send_keys(u'###你的账户###')
    firefox_login.find_element_by_name('password').clear()
    firefox_login.find_element_by_name('password').send_keys(u'###你的密码###')
    
    #输入完用户密码当然就是提交了,通过'name'为login来找到提交按钮
    firefox_login.find_element_by_name('login').click()
    
    #浏览器退出
    firefox_login.quit()
    
    #具体的selenium的方法需要你详细去翻翻它的[文档]
    #http://selenium-python.readthedocs.io/

    P.s.要学会用谷歌浏览器的开发者工具(F12或者Ctrl+Shift+I)的Elements去看
    你要输入的框框的信息(id/name/xpath….),或者直接右键你要定位的目标,选择【检查】.举个栗子:

    这里写图片描述

    ②有验证码情况(验证码识别深似海,建议学好数字图像处理)

    验证码这块实在太多了,特别是经过这么多年的发展,已经有各种不同种类的验证码的,我计划着好好研究一番以后另外写一个专门介绍验证码的博文,而下面只是简单聊聊而已。

    对于有验证码(这里指旧式验证码)的登录,其实就是在上面只需要用户名和密码的界面多给你一张验证码的图片(验证码图片请求来源的URL的格式大都是前面相同的地址后面加一串随机数,要知道这个随机数是多少,你就得看看关于请求验证码的js脚本怎么写,不然你连验证码这张图都拿不到,又谈何识别与登录),然后用户看出图片内容,再输入,验证码刚出现是非常正常的字母数字,因为要反爬的缘故,山那边的猿又对验证码图片做了增加噪点,扭曲挤压等图像处理,后来中国的汉字引入,验证码似乎就成了爬虫的专业杀虫剂,现在我见过的最有魔性的验证码是一个卖火车票的网站:D.

    可是还是那句话,如果爬虫很难识别到验证码,用户体验也不会好,为了不伤了用户的心情,程序猿们还是小心翼翼地设计验证码,关于验证码发展史以及山那头的程序猿和爬虫程序猿之间的大战,你可以到知乎这个帖看看为什么有些验证码看起来很容易但是没人做自动识别的

    上面的知乎帖子里面有一个名词:OCR。OCR技术是爬虫们应对验证码图片的神器,OCR全称Optical Character Recognition(光学字符识别),如果你把ocr当成一个黑匣子,那么如果你往这个黑匣子里面丢图片,他就会给你识别出图片内的字符,并输出文本给你,关于ocr的历史自己可以wiki一下,我先来说说ocr的实现思路:输入图片→中值滤波去噪点、二值化图片、分割等图片预处理→紧缩重排→字库特征匹配→字符

    上面实现思路中,关键是:第一,前面对图片的预处理,如果预处理越好,得出的二值化图片越清晰正规,那么后面字库特征匹配准确率就越高;第二,字库的搭建要丰富,特征值要选好。

    当然因为我不是做图像处理的,而且数字图像处理的课我也没有上好,所以上面基本都是班门弄斧,我就直接用现在已经有的轮子——摆在我前面的一堆图像处理和ocr库了,比如:

    1.PIL(Python Image Library,python专属图像处理库,现在较新版本是原来PIL的一个fork叫Pillow,原PIL停止更新)
    2.OpenCV(Open Source Computer Vision Library,是一个在图像操作和处理上比PIL更加先进的库,在python中OpenCV进行图像处理是通过cv2和numpy库实现的,换言之就是依赖于cv2和numpy这两个库)
    3.Tesseract-ocr(前面转手很多次,现在属于google开发的ocr技术项目)
    4.pyocr(依赖于Tesseract-ocr)等等,网上有人推荐先用OpenCV做图片预处理,再用Tesseract-ocr做识别,但是我只是用了PIL和pyocr/Tesseract-ocr,没有用OpenCV,PIL+pyocr识别差强人意,几乎没有几张能出东西,也难怪,因为pyocr已经没有更新很久了,而PIL+Teserract-ocr也只是好一点,可能是我没有训练够的原因,两种识别结果我就不方便给出来了,有机会你可以自己拿一些验证码试试,我这里只是捋顺一下思路,推荐可以直接上OpenCV+Tesseract-ocr试试.

    P.s.扯一下打码平台,打码平台有做好了并且封装好了的ocr平台识别的,还有人工识别打码的,可笑的是,我一开始还以为只有人工打码。这种打码平台一般都是要收费的,而且识别率见仁见智,因为针对性不一定高,我个人的话还是推荐你,在你项目允许的情况下,请尽量自己折腾这一块验证码的识别工作,方便后期排错或者目标网站的验证码有变化的时候,也可以相对应地迅速及时作出调整。详细看“打码平台”那点事儿

    上面谈论的旧式验证码都是“基于知识进行人机判断”(有点像看图说话),而新式验证码是“基于人类固有的生物特征以及操作的环境信息综合决策,来判断是人类还是机器”(看图做动作?),比方说谷歌老大发明的reCaptcha和阿里巴巴的NoCaptcha等(相信不少人都看过拖动块识别的那种验证吧,有兴趣的可以直接搜搜极验~).但是就算是新式的也有人做了破解,还是那句验证码要做还是能识别的,只是成本值不值得而已.

    更多关于验证码的,后面单独一篇慢慢聊,具体地聊,但是这里我先挖个坑:-) ========>填坑

    传参能做么? 其实上面说的用户登录这一步(假设是旧式验证码而且已经识别到了),用传参的方法也可以做到的,一般的登录过程都是POST的方式提交账号密码(和验证码),然后服务器会给你写cookie(而会话状态一般都存在服务器的session中),而cookie又和验证码的生成息息相关,讲真,目前为止我是还没有实际折腾过传参的方式,如果你要折腾实验一下就抓住POST方式和cookie/session这几个点入手】

    附:
    Selelnium支持的真·浏览器驱动:

    1. FireFox Driver
    2. Safari Driver
    3. IE Driver
    4. Chrome Driver
    5. Opera Driver

    Selelnium支持的伪·浏览器驱动:

    1. PhantomJS
    2. HTMLUnit

    Selelnium支持的移动端·浏览器驱动:

    1. Windows Phone Driver
    2. Selendroid
    3. IOS Driver
    4. Appium[支持iPhone,iPad,Android和FirefoxOS]

    (2)无头(无GUI)浏览器–PhantomJS

    Synopsis:PhantomJS is a headless Webkit scriptable with a js API.It has fast & native support for various Web standards: DOM handling,CSS selector,JSON,Canvas,and SVG.

    To Be Brief:PhantomJS is web browser without a graphical user inferface.

    好吧,前面的简单介绍其实是我想打下英文,你完全可以自己上它的官网自己慢慢看,都有。

    再一个就是phantomjs的使用场景:
    1.无需浏览器的Web测试; Testing
    2.页面自动化测试; Page Automation
    3.屏幕捕获; Screen Capture
    4.网络监控; Network Monitoring
    (LinkedIn,Twitter等都在用PhantomJS做测试)

    其实phantomjs这个东西一开始本意是用来做自动测试的(使用场景并没有提到爬虫),结果因为效果很好,很多人就拿来做爬虫.

    而这里我想说说自己对于PhantomJS在爬虫中应用的看法:

    首先,在一般人的认识里浏览器都是像chrome、firefox之类的有图形界面的(当然你要是说你不是一般人…- -b),但是这种GUI浏览器其实执行效率还是算慢的,因为要渲染出图形来,那么无GUI的浏览器的优势就有了,无GUI意味着占用资源少了,执行效率快了,而且适合linux纯CLI界面服务器来跑(纯CLI的linux服务器上面我还真没有试过FireFox和Chrome这种GUI的浏览器是不是能跑~),而爬虫中如果是选择了模拟浏览器这条路子来做页面请求,那么把GUI的浏览器换成无GUI的浏览器是必要的。

    然后,phantomjs在爬虫中的应用,我认为你把它当成一个纯粹的浏览器就够了,当成Chrome一样的浏览器,并不怎么需要操作到phantomjs里面的方法,我们写爬虫的时候写的更多的反而是selenium下面的方法,通过selenium去操作浏览器,无论是phantomjs、HTMLUnit等无GUI的浏览器,还是Chrom、FireFox这种有GUI的浏览器,至于能不能用HTMLUnit代替PhantomJS这个问题,我只能说python和PhantomJS配合比较好,而且js解析十分稳健,相对而言HTMLUnit稍显逊色,但并不是不能用HTMLUnit来作为爬虫用的无头浏览器。

    Tips:
    PhantomJS的渲染引擎是QtWebkit,而它的js解析引擎是Chrome的V8.
    PhantomJS在哪层构建就在哪层quit();
    PhantomJS每个版本都是以花命名,有点浪漫 :D

    P.s.
    ①PhantomJS推荐去官网下载编译好的二进制,因为debian系的distros的源里面那个PhantonJS是不完整的——“It seems that it’s not full-function.”,不完整会导致什么问题么?其他没有遇到过,就遇到过下面这个错误:

    "selenium.common.exception.WebDriverException:
    Message:ErrorUnable to load Atom 'find_elements' from file':
    /ghostdriver/third_party/webdriver-atoms/find_elements.js'"

    看到开头的 selenium我以为是selenium的问题,google了半天没有结果,回来再详细看看错误信息,最后直接把错误贴上去才找到,真觉得自己Too Young .Too Naive,一开始直接贴上去搜索就好了.- -

    ②如果是selenium+phantomjs的搭配,要注意selenium的版本问题,因为selenium从2.27开始才支持PhantomJS,一般pip装最新的selenium就没有问题.

    Selenum+PhantomJS

    现在来实际结合起来做一下,我稍微修改了一下项目代码做成示例:

    #! /usr/bin/env python
    #encoding:utf-8
    
    import sys
    reload (sys)
    sys.setdefaultencoding('utf-8')
    
    from selenium import webdriver
    from selenium.webdriver.support.ui import WebDriverWait 
    
    #PhantomJS动作函数
    def Phantomjs_Get_WebPage(a,b,c):
    
        #通过Selenium构造PhantomJS浏览器
        print 'PhantomJS Browser Structing ...\n'
        browser=webdriver.PhantomJS()
    
        print 'Opening Original Website....\n'
        url='这里填入你的URL'
        browser.get(url)
    
        #填写a并确认
        browser.find_element_by_xpath('xpath_a').clear()
        browser.find_element_by_xpath('xpath_a').send_keys(a)
        browser.find_element_by_xpath('xpath_a').click()
    
        #填写b并确认
        browser.find_element_by_xpath('xpath_b').clear()
        browser.find_element_by_xpath('xpath_b').send_keys(b)
        browser.find_element_by_xpath('xpath_b').click()
    
        #填写c
        browser.find_element_by_xpath('xpath_c').clear()
        browser.find_element_by_xpath('xpath_c').send_keys(c)
    
        #提交确认
        browser.find_element_by_xpath('xpath_d').click()
    
        if(YorN_Xpath(browser,wait_time=10,xpath_Probe="xpath_e")):
    
            webpage_sourcecode=browser.find_element_by_xpath('//*').get_attribute('outerHTML')
            #webpage_sourcecode是unicode
            browser.quit()#请求完直接断开和目标网站链接,充分利用提取和存库的时间
    
            #Extract和save两个函数分别是提取和入库的函数,这里没有给出来,在提取和入库博文的时候再给出来吧
            extracted_Data_singlePage=Extract(webpage_sourcecode,a,b)
            save(extracted_Data_singlePage,a,b) 
    
            return True
    
    
        else:
            print '请求AJAX超时'
            browser.quit()
    
            return False
    
    
    #AJAX是否加载成功的判断函数
    def YorN_Xpath(browser,wait_time=10,xpath_Probe):
    
        try:
            wait_for_ajax_element=WebDriverWait(browser,wait_time)#10秒内每隔500ms扫描一次页面变化
            wait_for_ajax_element.until(
            lambda  the_driver:the_driver.find_element_by_xpath(xpath_Probe).is_displayed())
            print '获取AJAX数据成功\n'
    
            return True
    
        except:
    
            print '获取AJAX数据失败\n'
    
            return False
    

    其实上面这段代码大部分都是上面讲selenium的时候的那些selenium的方法,关键要注意两个地方:

    ①browser=webdriver.PhantomJS()这一句就是selenium和PhantomJS结合的地方,这样说出来你是不是感觉也没有什么特别的。会不会觉得当想换成FireFox浏览器看一下的时候,就直接把语句改成browser=webdriver.FireFox()这样就好了?大多数情况下这样改是没问题的,使可以调通不出错的,可是由于FireFox和PhantomJS之间还是有区别的,所以在某些情况下直接这么改会导致程序报错;

    ②YorN_Xpath(browser,wait_time,xpath_Probe)这一个函数的功能就是为了解决PhantomJS没有等到异步的AJAX数据加载完就返回页面源码的问题。用到的是selenium.webdriver.support.ui下的WebDriverWait 方法,这是显式等待(Explicit Waits,官方文档看这里)。我们把上面构造的PhantomJS浏览器放进函数的browser那一项,wait_time就是等待AJAX上限时间,xpath_Probe是xpath探针,xpath_Probe这里需要填入的是只有AJAX加载成功才会出现的异步加载的那部分数据的xpath。WebDriverWait 方法固定是每500ms检测一次你的输入的xpath_Probe,如果检测有东西,就返回True,如果没有就继续等待500ms,如果总的等待时间超过了我设定的wait_time就会返回False。所以按照上面输入的wait_time=10来说,10s=10 000ms=20x500ms,换言之就是会在10s内对xpath_Probe最多检测20次,20次之中都没有检测到,那就不好意思了,返回False跳出了~

    使用场景:如果你发现你直接用PhantomJS返回的源码里面没有找到一些你要的数据,那么可能是由于你的这些数据是通过异步加载的方式加载的,比如AJAX的方法,而PhantomJS没有等到你的这些异步加载的数据就直接返回了源码,当你遇到这个情况的时候不妨用上面这个函数试试,希望能帮到你.

    P.s.
    Explicit Waits文档里面有一段关于为什么要用WebDriverWait的解释,我觉得讲的很有逻辑,现在单独提出来写在最后(其实我就是想多打打英文- -)

    It is worth nothing that if your page uses a lot of AJAX on load then WebDriver may not know when it has completely loaded.

    These days most of the webapps are using AJAX techniques when a page is loaded to browser,the elements within that page may load at different time intervals.

    This makes locating elements difficult,if the element is not present in the DOM,it will raise ElementVisibleException.

    Using waits,we can solve this issue.Waiting provides some time intervals between actions performed(mostly locating element or any other operation with the element)

    16.8.26更新:如果你遇到下面这个错误,尤其是在最开始的几次页面的请求中报错:

    urllib2.URLError:[urlopen error Error 111]Connection Refused

    那么很有可能是因为你的浏览器退出时机不对导致的,这就我说过的为什么浏览器的构建和退出应该是同一层完成,因为不这样的话,很容易就会出现循环内层退出了浏览器,可是我是在上层构造的浏览器,结果内层的下一次循环浏览器是不可用的状态,也就是“Connection Refused”状态(我一开始还以为urlopen的问题,但是想想我好像没有直接用到urlopen啊,那就应该是浏览器的问题了)


    免责声明

    本博文只是为了分享技术和共同学习为目的,并不出于商业目的和用途,也不希望用于商业用途,特此声明。

    最后思考一个问题:传参方法的效率和浏览器的稳定能不能做一个结合互补?这是我接下来要做的一个尝试.

    展开全文
  • 原文来源:... 项目开发中难免遇到外部接口的调用,小生今天初次接触该类,跟着API方法走了一遍,如有不对的地方,还请哆哆指正,拜谢! ... import java.io.BufferedReader; import java.io....
  • 从列表中随机抽取一个浏览器头作为函数的返回值。 def get_header(): user_agent_list = [ 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95', 'Safari/537....
  • 针对模拟浏览器采用。 webdriver.Firefox() 火狐浏览器模拟 Windows系统解决办法如下: 1、下载geckodriver.exe: 下载地址:https://github.com/mozilla/geckodriver/releases 请根据系统版本选择下载;...
  • Scrapy爬虫:模拟浏览器和使用代理

    千次阅读 2017-04-05 14:27:09
    采用settings.py的方式进行设置user agent和proxy列表 http://www.tuicool.com/articles/VRfQR3U http://jinbitou.net/2016/12/01/2229.html(本人用的这种)   网站的反爬虫策略: ...1.在s...
  • 零. 在用scrapy爬取数据中,有写是通过js返回的数据,如果我们每个都要获取,那就会相当麻烦,而且查看源码也看不到数据的,...Selenium 测试可以在 Windows、Linux 和 Macintosh上的 Internet Explorer、Chrome和 Fir...
  • 使用电脑模拟微信内置浏览器

    千次阅读 2019-01-07 13:24:21
    最近在弄微信开发,需要微信请求,其实很好改 只要把请求头改了就好了。   浏览器呢 就使用 chrome 我在这使用360极速浏览器了。   首先进入开发者模式(F12或者右键审查元素) 如图: 然后 点击 更多 选 More ...
  • 本来准备继续分析BeautifulSoup的,但是好多网页都是反爬虫的,想分析没法分析了 ,那么就跳一节吧,我们先看看如何模拟浏览器进行访问网页,然后在折回去继续说BeautifulSoup。
  • 最近一直在学习linux网络编程这一块的内容,自己做了一个简单web服务器,以前无法确切的了解web浏览器访问网页的的请求过程。现在有着样的条件了,所以就自己实现一下看看过程了。 浏览器展示一个网页的过程:...
  • 我打算用linux命令行curl模拟登录网页www.xxx.com/a.php?a=0&record=0,并把输出内容写入服务器上的一个文件save.txt 同时a.php文件有如下变量: ``` $a=$_GET['a']; $record=$_GET['record'];; foreach循环... ...
  • 模拟Http发送get、post、put、delete请求

    万次阅读 2016-11-14 10:57:47
     首先说一说模拟get请求,get请求最简单的方式是通过地址栏输入地址和参数。这个没什么可说的。有一个模拟get请求的好工具值得学习一下,那就是Opera。我们可以到:http://download.csdn.net/detail/u012453843/967
  • Java HttpClient 如何伪装微信浏览器进行POST请求当我用HttpClient的post去请求外部微信支付跳转时得到一个返回值:{"code":"XXXXXXXXX,"message":"请使用微信打开页面"}当时通过思考我想到了两个办法: 把这个POST...
  • 模拟.net post请求属性

    千次阅读 2016-04-25 17:02:51
    这两天在做一个nodejs的爬虫项目,需要模拟post请求获得网站数据。遇到2个asp.net的网站,掉到坑里面,调试了好几天。总结一下过程。 一般我们模拟post请求的时候最重要的就是post请求里面的formdata就可以了。怎么...
  • 可以设置一些Headers信息,模拟浏览器去访问这些网站,此时,就能够解决这个问题了。接下来我们来找找自己浏览器的Headers属性。  1.首先打开任意网页,按下F12,并选择网络(network)...
1 2 3 4 5 ... 20
收藏数 22,742
精华内容 9,096
热门标签
关键字:

linux 模拟浏览器请求