HTTPクローラ

とりあえず整理したのでアップロード。

とりあえず整理したのでアップロード。

  • タグ:
  • タグはありません
<?php

$dummyCookie = array();
$redirect_count = 0;

//リターンモデルを作る
$returns = array( "req_head" => array(), "res_head" => array() );


/*
    $url     : URL
    $port    : ポート
    $method  : GET, POST, HEADのいずれか(デフォルトはGET)
    $headers : リクエストヘッダ("ヘッダ名"=>"値")3
    $cc      : クッキー
    $post    : POSTの時に送信するデータを格納した配列("変数名"=>"値")
*/
function http($url, $port=80, $method="GET", $headers=null, $cc=null, $post=array(""))
{
    global $dummyCookie;
    global $returns;
    global $redirect_count;
    
    //URLを分解
    $URL = parse_url($url);

    //クエリー
    if (isset($URL['query'])) {
        $URL['query'] = "?".$URL['query'];
    } else {
        $URL['query'] = "";
    }

    //デフォルトのポートは80
    $URL['port'] = $port;

    if( !array_key_exists( "host", $URL ) )
    {
	    $URL['host'] = "sp.mbga.jp";
	    $URL['path'] = "/".$URL['path'];
    }
    
    //リクエストライン
    $request  = $method." ".$URL['path'].$URL['query']." HTTP/1.1\r\n";
	$request .= "Host: ".$URL['host']."\r\n";
    
	//ヘッダ
	if( $headers != null )
	{
	    foreach( $headers as $k => $h )
	    {
		    $request .= $k.":".$h."\r\n";
	    }
	}
    
    //クッキー分解してストア
    if( $cc )
    {
    	$cc = str_replace( "Cookie: ", "", $cc );
		$sep = explode( ";", $cc );

		//受け取ったクッキーパラメータをストア
		foreach( $sep as $c )
		{
			$d = explode( "=", $c );
			if( strcmp( trim($d[0]), "" ) )
			{
				$dummyCookie[trim($d[0])] = trim($d[1]);
			}
		}
    }
    
    //クッキー結合
	if( $dummyCookie != null )
	{
		$request .= "Cookie: ";
		foreach( $dummyCookie as $key => $cookie )
		{
			if( $cookie != null )
			{
				$request .= "{$key}={$cookie}; ";
			}
		}
		$request .= "\r\n";
	}
	$request .= "x-msim-use: on\r\n";

    //POSTの時はヘッダを追加して末尾にURLエンコードしたデータを添付
    if (strtoupper($method) == "POST") {
        while (list($name, $value) = each($post)) {
            $POST[] = $name."=".urlencode($value);
        }
        $postdata = implode("&", $POST);
        $request .= "Content-Type: application/x-www-form-urlencoded\r\n";
        $request .= "Content-Length: ".strlen($postdata)."\r\n";
        $request .= "\r\n";
        $request .= $postdata;
    } else {
        $request .= "\r\n";
    }
    $request .= "\r\n\r\n";

	//var_dump($dummyCookie);

    //WEBサーバへ接続
    $err = "";
    if( $port == 443 )
    {
	    $fp = fsockopen("ssl://".$URL['host'], $URL['port']);
    }else{
	    $fp = fsockopen($URL['host'], $URL['port']);
	}
	
    //接続に失敗した時の処理
    if (!$fp) {
        die("ERROR\n");
    }

	//Timeoutを2秒に
    stream_set_timeout($fp, 2);
    
    //要求データ送信
    fwrite($fp, $request);

    //応答データ受信
    $response = "";
    $Cnt=0;
    $redirect = null;
    while (!feof($fp))
    {
   		$line = fgets($fp, 1024);
        $response .= $line;
        if( strpos($line, "Set-Cookie") !== false )
        {
        	//キーパース
        	$line = str_replace( "Set-Cookie: ", "", $line );
        	$elements = explode( ";", $line );

			//設定をパース
			$kvp = explode( "=", array_shift($elements) ); //VALUE取得
			$key_name = $kvp[0];
			$value = $kvp[1];
			
			$expire=null;
			$path=null;
			$domain=null;
			$secure=null;
			$httponly=null;
			foreach( $elements as $elm )
			{
				$kvp = explode( "=", $elm );
				switch( $kvp[0] )
				{
				case "expire":
					$expire = $kvp[1];
					break;
				case "path":
					$path = $kvp[1];
					break;
				case "domain":
					$domain = $kvp[1];
					break;
				case "secure":
					$secure = $kvp[1];
					break;
				case "httponly":
					$httponly = $kvp[1];
					break;
				}
	        }
	        
	        $dummyCookie[$key_name] = $value; //( $key_name, $value, $expire, $path, $domain, $secure, $httponly );
        }
        if( strpos($line, "Location") !== false )
        {
        	$redirect = trim(str_replace( "Location: ", "", $line ));
        }
        //if( stripos($line, "Content-Type") !== false ) break;
    }

    //ヘッダ部分とボディ部分を分離
    $DATA = explode("\r\n\r\n", $response, 2);

    //リクエストヘッダをコメントアウトして出力
	//echo "<!-- resuest headers \r\n {$request} -->";
	$returns["req_head"][] = str_replace( "\r\n", "<BR>", $request );

    //レスポンスヘッダをコメントアウトして出力
	//echo "<!-- response headers \r\n {$DATA[0]} -->";
	$returns["res_head"][] = str_replace( "\r\n", "<BR>", $DATA[0] );

    $redirect_count = 0;
    //echo "<hr><hr>";

    if( $redirect != null )
    {
    	$redirect_count++;
    	if($redirect_count>2)
    	{
    		//リダイレクト三回でexit
    		exit;
    	}
    	
    	//echo "redirect to:".$redirect;
	    
	    //接続を終了
	    fclose($fp);
	    $fp = null;
	    
	    $returns["body"][] = $DATA[1];
    	$DATA[1] = http($redirect, 80, "GET", "Referer: {$redirect}");
    }

    //接続を終了
    if($fp)
    {
    	fclose($fp);
    }
    
    //メッセージボディを出力
    return $DATA[1];
}



//////////////////////////////////////////////////////////////////////////////////////////////////////
// ここから本体
//
// アクセスにフックをかけるロガータイプのソースですが
// 改造することで、HTML解析スクリプトとして利用できます。
// コマンドラインからのアクセスも可能です。
//
////

//GETかPOSTのどっちかで変数拾ってくる
function GetParam( $name )
{
	$ret = null;

	if(isset($_GET[$name])) {
		$ret = $_GET[$name];
	}
	if(isset($_POST[$name])) {
		$ret = $_POST[$name];
	}
	
	return $ret;
}

//リクエスト
$url = GetParam("url");
$port = GetParam("port");
$method = GetParam("mt");
$cookie = GetParam("c");
$postParam = GetParam("pp");

$url="";
//やや雑な値チェック
if( $url === null )
{
	echo "URLが無いです";
	exit;
}
if( $port == null )
{
	$port = 80;
}
if( $method === null )
{
	$method = "GET";
}

//HTMLからPOST値もらうときのパーサ
$params = array();
if( $postParam )
{
	$ar = explode( ",", $postParam );
	foreach( $ar as $a )
	{
		$d = explode( "::", $a );
		$params[$d[0]] = $d[1];
	}
}

//リクエストヘッダ
//スマホからm○bageにハックする仕様になってる
$request_header = array();
//$request_header["Referer"] = "";
$request_header["User-Agent"] = "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_2_1 like Mac OS X; ja-jp) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 Mobile/8C148 Safari/6531.22.7";
$request_header["Accept"] = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
$request_header["Accept-Language"] = "ja,en-us;q=0.7,en;q=0.3";
$request_header["Accept-Encoding"] = "gzip,deflate";
$request_header["Accept-Charset"] = "Shift_JIS,utf-8;q=0.7,*;q=0.7";
$request_header["Keep-Alive"] = "115";
$request_header["Connection"] = "keep-alive";

/*
//Basic認証用のヘッダ
if ($user && $pass) {
	$request_header["Authorization"] = "Basic ".base64_encode($user.":".$pass);
}
*/


//Webリクエスト
//$body = http( $url, $port, $method, $request_header, $cookie, $params );
$body = http( "https://www.google.co.jp/", 80, "GET", $request_header, null, null );


//本体を表示する(したい場合は)
//echo $body;

//////

//解析するならここで$bodyをごにょごにょする

//////



//以下データ出力は任意に

//リクエストヘッダ描画
/*
$counts = count($returns["req_head"]);
for( $i=0; $i<$counts; $i++ )
{
	echo "リクエスト<br />";
	echo $returns["req_head"][$i];
	echo "<hr>";
	echo "レスポンス<br />";
	echo $returns["res_head"][$i];
	echo "<hr>";
}
*/

//ファイル出力
/*
$fp = fopen( "http.txt", "w" );
if( $fp )
{
	fwrite($fp,$body,strlen($body));
	fclose($fp);
}
*/


//HTMLからのクロール用に出力するもの
/*
//ストアしたクッキーパラメータをHTMLに返す
$cookies = "";
if( $dummyCookie != null )
{
	$cookies .= "Cookie: ";
	foreach( $dummyCookie as $key => $cookie )
	{
		if( $cookie != null )
		{
			$cookies .= "{$key}={$cookie}; ";
		}
	}
	$cookies .= "\r\n";
}

$c_enc = urlencode($cookies);
$c_enc = str_replace( "+", "%20", $c_enc );
*/
/* 外部クローラ用コールバック
echo "<script type='text/javascript'>";
echo "req_callback(\"".$c_enc."\")";
echo "</script>";
*/

?>