Php Galkuri

http://www.phpschool.com/link/tipntech/48559

<?php
/******************************************************************************
*	프로그램명	: 갈쿠리
*	버젼				: 1.01
*	변경일			: 2006-09-14
*	작성자			: 강용석
*	메일				: <a href="mailto:[email protected]">[email protected]</a>
*	용도				: 텍스트 파싱
******************************************************************************/
 
class GalKuRi {
	// public
	var $response_header		= '';				// 응답헤더 저장
	var $contents					= '';				// 페이지 전체 내용 저장
	var $parse_value				= array();		// 결과가 저장될 배열
 
	// private
	var $_goods_no				= 0;				// 결과배열에 저장할때 쓰일 상품 번호
	var $_offset						= 0;				// 검색 시작 번지
	var $_page_no					= 0;				// 페이지 별로 읽을 경우 페이지 번호 저장변수
	var $_page_var					= '';				// 페이지 별로 읽을 경우 페이지 변수명을 저장하는 변수
	var $_parse_pattern			= array();		// 읽어들일 문자 패턴 2차원배열
	var $_process_func			= '';				// 페이지 별로 처리할때 결과를 처리할 외부함수
	var $_roop						= 1;				// 페이지를 계속 파싱할지 여부
	var $_set_cookies			= '';				// 쿠키 저장
	var $_set_referer				= '';				// 레퍼러 저장
	var $_skip_offset				= array();		// 건너뛸 문장
	var $_wait							= 0;				// 한페이지 처리후 멈춤시간(단위 초)
 
	function voidSetPattern($field,$token_start,$token_end,$del_str='') {
		/********************************************************************
		* public
		* 파싱할 패턴문자 설정
		* ex) $buf->voidSetPattern(필드명,시작문자,끝문자,[지울문자]);
		*
		* 텍스트 내용중 < 와 > 사이에 있는 문자열을 name 이라는 이름으로 빼내고
		* 결과문자열중 \ 를 지우고자 하는경우
		* ex) $buf->voidSetPattern('name','<','>','\');
		********************************************************************/
		if($field ===== '_default_')
			$this->voidError('_default_ 는 사용할수 없는 단어입니다.' );
 
		$this->_parse_pattern[$field] = array($token_start,$token_end,$del_str);
	}
 
	function voidSetSkipOffset($field,$token) {
		/********************************************************************
		* public
		* 파싱후 패턴과 동일한 문자가 중간에 존재하여 그부분의 뒷부분 부터 파싱을 원할경우
		* ex) $buf->voidSetSkipOffset(필드명,찾을문자);
		*
		* name 필드 파싱후 다음 파싱 패턴과 동일한 문자가 있을경우 건너뜀
		* ex) $buf->voidSetSkipOffset('name','<');
		*
		* 필드명을 _default_ 라고 설정할경우 파싱전 해당 문자로 이동을 한후에
		* 파싱을 시작함. default 시작위치를 설정
		* ex) $buf->voidSetSkipOffset('_default_','<');
		********************************************************************/
		$this->_skip_offset[$field] = $token;
	}
 
	function voidSetCookie($var,$value) {
		/********************************************************************
		* public
		* 쿠키를 설정합니다.
		* ex) $buf->voidSetCookie(쿠키명,쿠키값);
		********************************************************************/
		$this->_set_cookies .= $var.'='.urlencode($value).';';
	}
 
	function voidSetReferer($ref) {
		/********************************************************************
		* public
		* 레퍼러를 설정합니다.
		* ex) $buf->voidSetReferer(레퍼러);
		********************************************************************/
		$this->_set_referer = $ref;
	}
 
	function voidSetPage($var,$func='',$page=1) {
		/********************************************************************
		* public
		* 페이지 처리를 원할경우 설정
		* ex) $buf->voidSetPage(페이지변수명,[외부처리함수],[시작페이지]);
		* 하나의 주소에 연속된 페이지가 존재할경우 계속 읽어들일수 있습니다.
		*
		* 페이지변수 pagenum=1,2,3,4,5 식으로 페이지가 존재하는 경우
		* ex) $buf->voidSetPage('pagenum','func',1);
		*
		* 주의) 페이지가 많을경우 배열에 결과값이 계속 쌓이므로 리소스가 커질수 있으니
		* 생성자에 설정할수 있는 외부 함수를 이용하여 페이지 마다 바로 처리하시기 바라며
		* 역시나 시간이 오래 걸릴수 있으니 쉘모드에서 실행하시기 바랍니다.
		********************************************************************/
		$this->_page_var = $var;
		$this->_page_no = $page;
		$this->_process_func = $func;
	}
 
	function voidSetSleep($sec) {
		/********************************************************************
		* public
		* 페이지 처리시 완료후 잠시 멈춰있을 시간입니다.
		* ex) $buf->voidSetSleep(초);
		********************************************************************/
		$this->_wait = $sec;
	}
 
	function voidGetAllContents($url,$method = 'get',$port = '80') {
		/********************************************************************
		* public
		* 전체 페이지 내용을 <span style="background-color:YELLOW; color:RED;">긁어</span>오는 부분입니다.
		* ex) $buf->voidGetAllContents(주소,[메소드],[포트]);
		*
		* 결과 값은 
		* $buf->response_header; 응답헤더만 별도 저장
		* $buf->contents; 전체페이지 내용저장
		********************************************************************/
		if($method != 'get' && $method != 'post')
			$this->voidError('method 값이 다릅니다. '.$method);
 
		$url_info = parse_url($url);
		$fp = fsockopen($url_info['host'], $port, $errno, $errstr);
		if(!$fp) {
			$this->voidError($errstr.' ('.$errno.')');
		}
 
		if($method ===== 'post')	{
			fputs($fp,"POST ".$url_info['path']." HTTP/1.0\r\n");
			fputs($fp,"Host: ".$url_info['host']."\r\n");
			fputs($fp,"User-Agent: PHP Script\r\n");
 
			if($this->_set_referer) 
				fputs($fp,"Referer: ".$this->_set_referer."\r\n");
 
			if($this->_set_cookies)
				fputs($fp,"Cookie: ".$this->_set_cookies."\r\n");
 
			fputs($fp,"Content-Type: application/x-www-form-urlencoded\r\n");
			fputs($fp,"Content-Length: ".strlen($url_info['query'])."\r\n");
			fputs($fp,"Connection: close\r\n\r\n");
			fputs($fp,$url_info['query']);
		}
		else {
			fputs($fp,"GET ".$url_info['path'].($url_info['query'] ? '?'.$url_info['query'] : '')." HTTP/1.0\r\n");
			fputs($fp,"Host: ".$url_info['host']."\r\n");
			fputs($fp,"User-Agent: PHP Script\r\n");
 
			if($this->_set_referer) 
				fputs($fp,"Referer: ".$this->_set_referer."\r\n");
 
			if($this->_set_cookies)
				fputs($fp,"Cookie: ".$this->_set_cookies."\r\n");
 
			fputs($fp,"Connection: close\r\n\r\n");
		}
 
		$this->contents = '';
		$this->response_header = '';
 
		while(trim($buf = fgets($fp,1024)) != "") { //응답헤더를 읽어옵니다.
			$this->response_header .= $buf;
		}
 
		while(!feof($fp)) { //내용을 읽어옵니다.
			$this->contents .=&nbsp; fgets($fp,1024);
		}
		fclose($fp);
	}
 
	function voidParsePage($url,$method = 'get',$port = '80') {
		/********************************************************************
		* public
		* 파싱하는 부분 main 이 되겠습니다.
		* 페이징 처리와 계속 파싱할것인지 결정을 하고
		* 외부함수 처리 역시 여기서 합니다.
		* ex) $buf->voidParsePage(주소,[메소드],[포트]);
		*
		* _default_ 오프셋이 있으면 그쪽으로 이동시키고 패턴에 등록된 것만큼 반복을 합니다.
		* name,img,price 패턴이 등록되 있다면
		* name파싱,img파싱,price파싱을 계속 반복합니다.
		* 더이상 내용이 없다면 종료시키거나 페이지설정이 되있다면
		* 다음페이지를 읽어들여서 다시 파싱을 반복하고 페이지가 없을때까지 반복 파싱.
		********************************************************************/
		$this->_roop = 1;
		$page_now = $this->_page_no;
		$page = '';
		$key = array_keys($this->_parse_pattern);
		$cnt=count($key);
 
		while($this->_roop) {
			$this->_goods_no = 0;
			$this->_offset = 0;
			$parse_count = 0;
			$this->voidGetAllContents($url.$page,$method,$port);
 
			if($this->_skip_offset['_default_'])
				$this->voidGetOffset($this->_skip_offset['_default_']);
 
			if($this->_roop) {
				while($this->_roop) {
					for($i=0;$i<$cnt;$i++) {
						$this->voidGetText($key[$i]);
						if(!$this->_roop) {
							if($cnt != count($this->parse_value[$this->_goods_no]))
								unset($this->parse_value[$this->_goods_no]);
							break;
						}
						$parse_count++;
					}
					$this->_goods_no++;
				}
			}
 
			if($this->_page_var) {
				if($parse_count >= $cnt) {
					$page = '&'.$this->_page_var.'='.(++$page_now);
					$this->_roop = 1;
					if($this->_wait)
						sleep($this->_wait);
				}
				else {
					$this->_roop = 0;
					break;
				}
			}
 
			if($this->_process_func) {
				call_user_func($this->_process_func,$this->parse_value);
				$this->parse_value = array();
			}
		}
	}
 
	function voidGetOffset($str) {
		/********************************************************************
		* private
		* 검색위치를 건너뛰는 부분입니다.
		* ex) $buf->voidGetOffset(문자);
		* 해당문자가 없으면 종료합니다.
		********************************************************************/
		$tmp_offset = strpos($this->contents,$str,$this->_offset);
		if($tmp_offset)
			$this->_offset = $tmp_offset + strlen($str);
		else
			$this->_roop = 0;
	}
 
	function voidGetText($field) {
		/********************************************************************
		* private
		* 패턴 사이의 문자열을 추출하는 부분입니다.
		* ex) $buf->voidGetText(필드);
		* 역시나 해당문자가 없으면 종료합니다.
		********************************************************************/
		$spos = strpos($this->contents,$this->_parse_pattern[$field][0],$this->_offset);
		if(!$spos) {
			$this->_roop = 0;
			return;
		}
		$spos += strlen($this->_parse_pattern[$field][0]);
 
		$epos = strpos($this->contents,$this->_parse_pattern[$field][1],$spos);
		if(!$epos) {
			$this->_roop = 0;
			return;
		}
		$this->_offset = $epos + strlen($this->_parse_pattern[$field][1]);
 
		$str = substr($this->contents,$spos,$epos-$spos);
 
		if($this->_parse_pattern[$field][2])
			$this->parse_value[$this->_goods_no][$field] = str_replace("\r\n",'',str_replace($this->_parse_pattern[$field][2],'',trim($str)));
		else
			$this->parse_value[$this->_goods_no][$field] = str_replace("\r\n",'',trim($str));
 
		if($this->_skip_offset[$field])
			$this->voidGetOffset($this->_skip_offset[$field]);
	}
 
	function voidError($msg) {
		exit($msg);
	}
}
?>

다운로드에 올릴려다고 허접한 거라서 그냥 여기다 올리네요. 웹페이지에서 필요한 부분만 가져오는 프로그램을 클래스로 만들어서 조금이라도 쉽고 편하게 가져올수 있도록 만들어 봤습니다. 아 이거 만들때는 스누피가 있는걸 몰라서 걍 만든거니 스누피 쓴다니 만다니 라고 말씀하시면 상처입습니다 -ㅂ-;

간단한 사용설명은——————————————————————- $buf = new GalKuRi;&nbsp; 객체생성 $buf→voidSetCookie(쿠키명,쿠키값); 쿠키설정 $buf→voidSetReferer(레퍼러); 레퍼러설정 $buf→voidSetPage(페이지변수명,외부함수,페이지번호); 페이지 처리 설정 외부함수는 한페이지후 결과를 처리하기 위해 설정 $buf→voidSetSleep(초); 한페이지 처리수 정지시간 $buf→voidSetPattern(필드명,시작문자,끝문자,[지울문자]); 파싱할 패턴 설정 시작문자와 끝문자 사이의 문자열을 배열로 저장 $buf→voidSetSkipOffset(필드명,찾을문자); 파싱후 패턴에 넣은 문자와 동일한 문자가 있어서 방해될경우 그문자까지 오프셋을 뛰어 넘음 $buf→voidParsePage(주소,[메소드],[포트]); 파싱시작

# # 파싱된 데이타를 처리하는 방법 # $buf→parse_value 배열을 처리하면 됨

# # voidSetPage('page','func',1) 에서 외부 함수를 설정했을경우 # 한페이지 처리시는 괜찬으나 페이지가 많으면 배열이 많이 늘어나니 # 페이지가 많을 경우에는 외부 함수 사용을 추천 # function func(&$val) { &nbsp; $val 결과배열 처리 }


# # 참고 # 단순히 전체페이지 내용을 원할경우(voidSetPattern 불필요) #

$buf = new GalKuRi; $buf→voidSetCookie(쿠키명,쿠키값); $buf→voidSetReferer(레퍼러); $buf→voidGetAllContents(주소,[메소드],[포트]); echo $buf→response_header; 헤더값 echo $buf→contents; 전체내용


간단한 예제 몇개.

스쿨 팁텍 목록 가져오기

function voidPrint(&$val) { &nbsp;print_r($val); }

$buf = new GalKuRi; $buf→voidSetPage('page','voidPrint',1); $buf→voidSetSkipOffset('_default_','<!– 목록 –>'); $buf→voidSetPattern('num','<td id="bb_list">','<'); $buf→voidSetPattern('kind','<span class=small>','<'); $buf→voidSetPattern('view_url',"<a href='..","'"); $buf→voidSetPattern('title',"<span style=>","<"); $buf→voidSetPattern('name','title="','"'); $buf→voidSetPattern('regtime','title="','"'); $buf→voidSetPattern('regdate','>','<'); $buf→voidSetPattern('hit','<td id="bb_list">','<'); $buf→voidParsePage('<a href="http://www.phpschool.com/gnuboard4/bbs/board.php?bo_table=tipntech&page=1');" target="_blank">http://www.phpschool.com/gnuboard4/bbs/board.php?bo_table=tipntech&page=1');</a> &nbsp; 디엡숍 상품 리스트(tv였나.. ㅡㅡ;;) 가져오기 function voidPrint(&$val) { &nbsp;print_r($val); } $buf = new GalKuRi; $buf→voidSetPage('DTYPE=IMAGE&pageNo=','voidPrint',1); $buf→voidSetSkipOffset('_default_','<form name="prodlist"'); $buf→voidSetCookie('ACODE','1ltjzE.wkt10'); $buf→voidSetCookie('tcateid','D42414'); $buf→voidSetCookie('pmmcBGIBLE8BRMUSEGM2B78CVG78KJ4','0'); $buf→voidSetCookie('pmmczGIBLE8BRMUSEGM2B78CVG78KJ4','1'); $buf→voidSetPattern('image_url','<img src="http://shopimage.hanmail.net/m_productimages/','"'); $buf→voidSetPattern('content_url','<a href="','"'); $buf→voidSetPattern('goods_name','>','</a>'); $buf→voidSetPattern('price','<strong class="price">','원',','); $buf→voidParsePage('<a href="http://dnshop.daum.net/front/category/DetailCategory?CID=D42414');" target="_blank">http://dnshop.daum.net/front/category/DetailCategory?CID=D42414');</a> 옥션 상품리스트 (무슨상품이었더라… ㅡㅡ;;) 가져오기 function voidPrint(&$val) { &nbsp;print_r($val); } $buf = new GalKuRi; $buf→voidSetPage('page','voidPrint',1); $buf→voidSetSkipOffset('_default_','<table class="listView" border="0" cellpadding="0" cellspacing="0" align="NotSet" style="width: 900px" >'); $buf→voidSetPattern('image',"<img src='","'",); $buf→voidSetPattern('content',"<a target=\"_top\" href='","'",); $buf→voidSetPattern('name','class="itemName">','</a>',); $buf→voidSetPattern('price','

','

',','); $buf→voidParsePage('<a href="http://listings.auction.co.kr/category/list.aspx?category=01180000&frm=home');" target="_blank">http://listings.auction.co.kr/category/list.aspx?category=01180000&frm=home');</a>

네이버 검색 결과페이지 관련키워드 가져오기 $buf = new GalKuRi; $buf→voidSetSkipOffset('_default_','<div class="SuggestWord">'); $buf→voidSetPattern('keyword',')));">','<'); $buf→voidSetSkipOffset('keyword','rsk.list1'); $buf→voidParsePage('<a href="http://search.naver.com/search.naver?where=nexearch&query='.urlencode('아디다스').'&frm=t1&sm=top_hty');" target="_blank">http://search.naver.com/search.naver?where=nexearch&query='.urlencode('아디다스').'&frm=t1&sm=top_hty');</a>

print_r($buf→parse_value);

아.. 개인적으로만 사용가능합니다. 그리고 악플은 상처받으니 사절이삼~

$this 가 빠진 메소드가 있어서 소스를 새로 올렸습니다. ㅈㅅ

누구나 수정하실 수 있습니다. 위키 사용법 참고하세요.