作为程序员一定要保持良好的睡眠,才能好编程

反防盗链采集图片CURL篇

发布时间:2018-11-08

今天心血来潮,想采集一个站点,做个自己的内容站,


想着还是不错的,可是在查看的过程中,发现此站是防盗链的,

一般请求是 403 没有访问权限,这怎么办?


像简单的


file_get_contents()


fopen()


这样的函数肯定是不能用的了。


想到了一个curl 命令 可以模拟浏览器的请求,去访问,这样就可以了吧。


说来就来,怀揣着怀疑的态度做个测试吧:


我这个框架是使用了yaf进行了封装,下面是我一个controller中的一个调用:


caiji1.png

意思是采集 这张图片,存放在本地



NewsModel.php 给出代码


fetchBefore 这个方法是 curl发出请求之前触发,添加header头信息,

这些header头从Charles 抓包工具中截取出来的,放在了这里


geturl 方法 使用file_put_contents() 把请求的内容存放在了本地


class NewsModel extends BaseModel {

  protected function _init() {
    parent::_init();
    $this->_host = 'http://g.yt99.com';
    //$this->_host = 'http://k.yt99.com';
  }

  public function fetchBefore($url, $data) {

    //$this->setRequestOptions(CURLOPT_COOKIE,'acw_tc=dede581e15416489660366317ece9fedad784adaaeedf1582f420846de');
    $this->setRequestHeader([
      "accept" => "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
      "accept-encoding" => "gzip, deflate, br",
      "accept-language" => "zh-CN,zh;q=0.9",
      "cache-control" => "no-cache",
      "pragma" => "no-cache",
      "upgrade-insecure-requests" => "1",
      "user-agent" => "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.81 Safari/537.36"
    ]);


    return $data;

  }


  protected function fetchFinish($data) {

    return $data;
  }

  public function geturl($imageurl, $param = []) {


    $result = $this->send($imageurl, $param);


    echo file_put_contents(APP_PATH . DS . 'c.gif', $result);


  }


}


caiji2.png


程序运行后:


caiji3.png


打开本地文件,可以看到:


caiji4.png


已经成功的把文件down下来了。



最后结论:

1、防盗链不要愉,可能 通过采取反防盗链的方式去获取

2、抓包工具截取 request header 头信息  通过判断、测试  猜测服务器需要哪些header头信息进行传递


多次试探后,应该就能成功。当然,如果特别复杂的盗链是不能破解的。呵呵


好,这次把一次反盗链的方式方法记录下来,以后可能用到。








curl.php

class Curl{

private $_curl;
private $response_header_continue = FALSE;
private $_cookies;
private $_reqHeaders;

  
    public function __construct(array $defaultOptions = []) {
      $this->_curl = curl_init();
    
      $this->setOption(CURLOPT_HEADERFUNCTION, [$this, 'addResponseHeaderLine']); 
    }
    public function addResponseHeaderLine($curl, $header_line) {
      $trimmed_header = trim($header_line, "\r\n");
    
      if ($trimmed_header === "") {
        $this->response_header_continue = FALSE;
      } else if (strtolower($trimmed_header) === 'http/1.1 100 continue') {
        $this->response_header_continue = TRUE;
      } else if (!$this->response_header_continue) {
        $this->response_headers[] = $trimmed_header;
      }
    
      return strlen($header_line);
    }
    
    
   public function setHeader(array $data) {
      $this->_reqHeaders = array_replace($this->_reqHeaders, $data);
    
      foreach ($this->_reqHeaders as $key => $value) {
        if ($value !== NULL) {
          $header[] = is_integer($key) ? $value : $key . ': ' . $value;
        }
      }
      $this->_options[CURLOPT_HTTPHEADER] = $header; //CURLOPT_COOKIE
   }
   
   public function getOption($key) {
      return isset($this->_options[$key]) ? $this->_options[$key] : NULL;
    }
    
    public function setOption($key, $value) {
      $this->_options[$key] = $value;
    }
    
    public function setCookie($key, $val) {
      $this->_cookies[$key] = $val;
      $this->setOption(CURLOPT_COOKIE, http_build_query($this->_cookies, '', '; '));
    } 
        
    public function getResponseHeaders($headerKey = NULL) {
      $headers = [];
      $headerKey = strtolower($headerKey);
    
      foreach ($this->response_headers as $header) {
        $parts = explode(":", $header, 2);
    
        $key = isset($parts[0]) ? $parts[0] : NULL;
        $value = isset($parts[1]) ? $parts[1] : NULL;
    
        $headers[trim(strtolower($key))] = trim($value);
      }
    
      if ($headerKey) {
        return isset($headers[$headerKey]) ? $headers[$headerKey] : FALSE;
      }
    
      return $headers;
    }
    
    public function __destruct() {
      curl_close($this->_curl);
    }

}