zoukankan      html  css  js  c++  java
  • PHP网络爬虫之CURL学习

    PHP的CURL

    php的curl可以实现模拟http的各种请求,这也是php做网络爬虫的基础,也多用于接口api的调用。

    这个时候有人就要发问了:为什么你特么不用file_get_contents?

    curl的性能比它好,而且可以完成更多复杂的操作,不仅仅只是获取页面数据。

    下面先分别介绍一些常用的函数。

    • curl_init 初始化一个curl对话

    • curl_setopt 设置curl参数,即传输选项

    • curl_exec 执行请求

    • curl_close 关闭一个curl对话

    主要是上面四个


    • curl_errno 返回最后一次错误码,php已经定义了诸多错误枚举编码

    • curl_errror 返回一个保护当前会话最近一次错误的字符串

    下面直接上实例吧,相关解释都在注释里面

    1. 在网络上下载一个网页并把内容中的“百度”替换为“屌丝”之后输出

    <?php
    /**
     * 实例描述:在网络上下载一个网页并把内容中的“百度”替换为“屌丝”之后输出
     */
    $curlobj = curl_init();            // 初始化
    curl_setopt($curlobj, CURLOPT_URL, "http://www.baidu.com");        // 设置访问网页的URL
    curl_setopt($curlobj, CURLOPT_RETURNTRANSFER, true);           // 执行之后不直接打印出来
    $output=curl_exec($curlobj);  // 执行
    curl_close($curlobj);          // 关闭cURL
    echo str_replace("百度","屌丝",$output);
    ?>

    2. 通过调用WebService查询北京的当前天气

    <?php
    /**
     * 实例描述:通过调用WebService查询北京的当前天气
     */
    $data = 'theCityName=北京';
    $curlobj = curl_init();    
    curl_setopt($curlobj, CURLOPT_URL, "http://www.webxml.com.cn/WebServices/WeatherWebService.asmx/getWeatherbyCityName");  
    curl_setopt($curlobj, CURLOPT_HEADER, 0); 
    curl_setopt($curlobj, CURLOPT_RETURNTRANSFER, 1);  
    curl_setopt($curlobj, CURLOPT_POST, 1);  
    curl_setopt($curlobj, CURLOPT_POSTFIELDS, $data);  
    curl_setopt($curlobj, CURLOPT_HTTPHEADER, array("application/x-www-form-urlencoded; charset=utf-8", 
        "Content-length: ".strlen($data)
        )); 
    $rtn = curl_exec($curlobj);   
    if(!curl_errno($curlobj)){
        // $info = curl_getinfo($curlobj); 
        // print_r($info);
        echo $rtn;  
    } else {
      echo 'Curl error: ' . curl_error($curlobj);
    }
    curl_close($curlobj);
    ?>

    3. 模拟需要登录的网址并抓取网页的内容

    <?php
    /**
     * 实例描述:模拟需要登录的网址并抓取网页的内容
     */
    $data=array('username' => 'promonkey', 
        'password' => '1q2w3e',
        'remember'=>1);
    $data='username=zjzhoufy@126.com&password=1q2w3e&remember=1';
    $curlobj = curl_init();            // 初始化
    curl_setopt($curlobj, CURLOPT_URL, "http://www.imooc.com/user/login");     // 设置访问网页的URL
    curl_setopt($curlobj, CURLOPT_RETURNTRANSFER, true);           // 执行之后不直接打印出来
    
    // Cookie相关设置,这部分设置需要在所有会话开始之前设置
    date_default_timezone_set('PRC'); // 使用Cookie时,必须先设置时区
    curl_setopt($curlobj, CURLOPT_COOKIESESSION, TRUE); 
    curl_setopt($curlobj, CURLOPT_HEADER, 0); 
    curl_setopt($curlobj, CURLOPT_FOLLOWLOCATION, 1); // 这样能够让cURL支持页面链接跳转
    
    curl_setopt($curlobj, CURLOPT_POST, 1);  
    curl_setopt($curlobj, CURLOPT_POSTFIELDS, $data);  
    curl_setopt($curlobj, CURLOPT_HTTPHEADER, array("application/x-www-form-urlencoded; charset=utf-8", 
        "Content-length: ".strlen($data)
        )); 
    curl_exec($curlobj);   // 执行
    curl_setopt($curlobj, CURLOPT_URL, "http://www.imooc.com/space/index");
    curl_setopt($curlobj, CURLOPT_POST, 0);  
    curl_setopt($curlobj, CURLOPT_HTTPHEADER, array("Content-type: text/xml"
        )); 
    $output=curl_exec($curlobj);  // 执行
    curl_close($curlobj);          // 关闭cURL
    echo $output;
    ?>

    4. 登录网站的信息抓取并下载个人空间页面 + 自定义实现页面链接跳转抓取

    <?php
    /**
     * 实例描述:登录网站的信息抓取并下载个人空间页面
     * 自定义实现页面链接跳转抓取
     * 
     */
    $data='username=demo_peter@126.com&password=123qwe&remember=1';
    $curlobj = curl_init();            // 初始化
    curl_setopt($curlobj, CURLOPT_URL, "http://www.imooc.com/user/login");     // 设置访问网页的URL
    curl_setopt($curlobj, CURLOPT_RETURNTRANSFER, true);           // 执行之后不直接打印出来
    
    // Cookie相关设置,这部分设置需要在所有会话开始之前设置
    date_default_timezone_set('PRC'); // 使用Cookie时,必须先设置时区
    curl_setopt($curlobj, CURLOPT_COOKIESESSION, TRUE); 
    curl_setopt($curlobj, CURLOPT_HEADER, 0); 
    // 注释掉这行,因为这个设置必须关闭安全模式 以及关闭open_basedir,对服务器安全不利
    //curl_setopt($curlobj, CURLOPT_FOLLOWLOCATION, 1);  
    
    curl_setopt($curlobj, CURLOPT_POST, 1);  
    curl_setopt($curlobj, CURLOPT_POSTFIELDS, $data);  
    curl_setopt($curlobj, CURLOPT_HTTPHEADER, array("application/x-www-form-urlencoded; charset=utf-8", 
        "Content-length: ".strlen($data)
        )); 
    curl_exec($curlobj);   // 执行
    curl_setopt($curlobj, CURLOPT_URL, "http://www.imooc.com/space/index");
    curl_setopt($curlobj, CURLOPT_POST, 0);  
    curl_setopt($curlobj, CURLOPT_HTTPHEADER, array("Content-type: text/xml"
        )); 
    $output=curl_redir_exec($curlobj);  // 执行
    curl_close($curlobj);          // 关闭cURL
    echo $output;
    
    /**
     * 自定义实现页面链接跳转抓取
     */
    function curl_redir_exec($ch,$debug="") 
    { 
        static $curl_loops = 0; 
        static $curl_max_loops = 20; 
    
        if ($curl_loops++ >= $curl_max_loops) 
        { 
            $curl_loops = 0; 
            return FALSE; 
        } 
        curl_setopt($ch, CURLOPT_HEADER, true); // 开启header才能够抓取到重定向到的新URL
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 
        $data = curl_exec($ch); 
        // 分割返回的内容
        $h_len = curl_getinfo($ch, CURLINFO_HEADER_SIZE); 
        $header = substr($data,0,$h_len);
        $data = substr($data,$h_len - 1);
    
        $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); 
        if ($http_code == 301 || $http_code == 302) { 
            $matches = array(); 
            preg_match('/Location:(.*?)
    /', $header, $matches); 
            $url = @parse_url(trim(array_pop($matches))); 
            // print_r($url); 
            if (!$url) 
            { 
                //couldn't process the url to redirect to 
                $curl_loops = 0; 
                return $data; 
            } 
            $last_url = parse_url(curl_getinfo($ch, CURLINFO_EFFECTIVE_URL)); 
            if (!isset($url['scheme'])) 
                $url['scheme'] = $last_url['scheme']; 
            if (!isset($url['host'])) 
                $url['host'] = $last_url['host']; 
            if (!isset($url['path'])) 
                $url['path'] = $last_url['path'];
    
            $new_url = $url['scheme'] . '://' . $url['host'] . $url['path'] . (isset($url['query'])?'?'.$url['query']:''); 
            curl_setopt($ch, CURLOPT_URL, $new_url); 
    
            return curl_redir_exec($ch); 
        } else { 
            $curl_loops=0; 
            return $data; 
        } 
    } 
    ?>

    从FTP服务器下载一个文件到本地

    <?php
    /**
     * 实例描述:把本地文件上传到FTP服务器上
     */
    $curlobj = curl_init();    
    $localfile = 'ftp01.php';
    $fp = fopen($localfile, 'r');
    
    curl_setopt($curlobj, CURLOPT_URL, "ftp://192.168.1.100/ftp01_uploaded.php");  
    curl_setopt($curlobj, CURLOPT_HEADER, 0); 
    curl_setopt($curlobj, CURLOPT_RETURNTRANSFER, 1);  
    curl_setopt($curlobj, CURLOPT_TIMEOUT, 300); // times out after 300s
    curl_setopt($curlobj, CURLOPT_USERPWD, "peter.zhou:123456");//FTP用户名:密码
    
    //上传和下载主要是下面子三个参数不一样
    curl_setopt($curlobj, CURLOPT_UPLOAD, 1);
    curl_setopt($curlobj, CURLOPT_INFILE, $fp);
    curl_setopt($curlobj, CURLOPT_INFILESIZE, filesize($localfile));
    $rtn = curl_exec($curlobj);  
    fclose($fp); 
    if(!curl_errno($curlobj)){
        echo "Uploaded successfully.";  
    } else {
      echo 'Curl error: ' . curl_error($curlobj);
    }
    curl_close($curlobj);
    ?>

    6.下载网络上面的一个HTTPS的资源

    <?php
    /**
     * 实例描述:下载网络上面的一个HTTPS的资源
     */
    $curlobj = curl_init();            // 初始化
    curl_setopt($curlobj, CURLOPT_URL, "https://ajax.aspnetcdn.com/ajax/jquery.validate/1.12.0/jquery.validate.js");       // 设置访问网页的URL
    curl_setopt($curlobj, CURLOPT_RETURNTRANSFER, true);           // 执行之后不直接打印出来
    
    // 设置HTTPS支持
    date_default_timezone_set('PRC'); // 使用Cookie时,必须先设置时区
    curl_setopt($curlobj, CURLOPT_SSL_VERIFYPEER, 0); // 对认证证书来源的检查从证书中检查SSL加密算法是否存在
    curl_setopt($curlobj, CURLOPT_SSL_VERIFYHOST, 2); // 
    
    $output=curl_exec($curlobj);  // 执行
    curl_close($curlobj);          // 关闭cURL
    echo $output;
    ?>

    原生PHP模拟http请求

    有时候为了简单模拟一个http请求,这样就去用curl有点浪费,其实php自身已经可以实现这个功能,

    需要在服务器端模拟 POST/GET 等请求,也就是在 PHP 程序中去实现模拟,改怎么做到呢?或者说,在 PHP 程序里,给你一个数组,如何将这个数组 POST/GET 到另外一个地址呢?当然,使用 CURL 很容易办到,那么如果不使用 CURL 库,又该怎么办呢?其实,在 PHP 里已经有相关的函数实现了,这个函数就是接下来要讲的 stream_context_create()。

    直接 show you the code,这是最好的方法:

    $data = array(
        'foo'=>'bar', 
        'baz'=>'boom', 
        'site'=>'www.nowamagic.net', 
        'name'=>'nowa magic'); 
    
    $data = http_build_query($data); 
    
    //$postdata = http_build_query($data);
    $options = array(
        'http' => array(
            'method' => 'POST',
            'header' => 'Content-type:application/x-www-form-urlencoded',
            'content' => $data
            //'timeout' => 60 * 60 // 超时时间(单位:s)
        )
    );
    
    $url = "http://www.nowamagic.net/test2.php";
    $context = stream_context_create($options);
    $result = file_get_contents($url, false, $context);
    
    echo $result;
    http://www.nowamagic.net/test2.php 的代码为:
    
    $data = $_POST;
    
    echo '<pre>';
    print_r( $data );
    echo '</pre>';

    运行结果为:

    Array
    (
        [foo] => bar
        [baz] => boom
        [site] => www.nowamagic.net
        [name] => nowa magic
    )

    一些要点讲解:

    1. 以上程序用到了 http_build_query() 函数,构造URL字符串。

    2. stream_context_create() 是用来创建打开文件的上下文件选项的,比如用POST访问,使用代理,发送header等。就是 创建一个流,再举一个例子吧:

    $context = stream_context_create(array( 
        'http' => array( 
            'method'  => 'POST', 
            'header'  => sprintf("Authorization: Basic %s
    ", base64_encode($username.':'.$password)). 
            "Content-type: application/x-www-form-urlencoded
    ", 
            'content' => http_build_query(array('status' => $message)), 
            'timeout' => 5, 
        ), 
    )); 
    $ret = file_get_contents('http://twitter.com/statuses/update.xml', false, $context); 

    1. stream_context_create创建的上下文选项即可用于流(stream),也可用于文件系统(file system)。对于像 file_get_contentsfile_put_contentsreadfile直接使用文件名操作而没有文件句柄的函数来说更有用。stream_context_create增加header头只是一部份功能,还可以定义代理、超时等。这使得访问web的功能不弱于curl。

    2. stream_context_create() 作用:创建并返回一个文本数据流并应用各种选项,可用于fopen(),file_get_contents()等过程的超时设置、代理服务器、请求方式、头信息设置的特殊过程。

    3. stream_context_create 还能通过增加 timeout 选项解决file_get_contents超时处理:

    $opts = array(
        'http'=>array(
        'method'=>"GET",
        'timeout'=>60,
      )
    );
    //创建数据流上下文
    $context = stream_context_create($opts);
    
    $html =file_get_contents('http://www.nowamagic.net', false, $context);
    
    //fopen输出文件指针处的所有剩余数据:
    //fpassthru($fp); //fclose()前使用
    

    参考:http://www.cnblogs.com/lazycat-cz/p/4050436.html

    http://www.cnblogs.com/fyy-888/p/5381992.html

  • 相关阅读:
    mysql BETWEEN操作符 语法
    mysql IN操作符 语法
    mysql LIKE通配符 语法
    mysql TOP语句 语法
    mysql DELETE语句 语法
    mysql Update语句 语法
    mysql INSERT语句 语法
    mysql ORDER BY语句 语法
    mysql OR运算符 语法
    mysql AND运算符 语法
  • 原文地址:https://www.cnblogs.com/hoewang/p/10257254.html
Copyright © 2011-2022 走看看