1 2 3 4 5 6 L

Page Header > Subtitle

[PHP] PHP를 이용한 심플한 게시판 파싱

Guzzle, domCrawer, css-selector 설치

guzzle + domcrawler을 사용하기 위해서는  php 5.5 이상이어야 한다. (웹사이트 보안을 위해서라도 php 5.6 또는 php 7.x 를 사용하길 권장)

guzzle + domcralwer 등은 composer 로 설치한다.  php 에서 composer 를 사용하는 방법은 구글링으로 쉽게 구할수 있음으로 본글에서는 설명하지 않습니다. 

 

composer.json

{
 "require": {
 "php": ">=5.6.0",
 "guzzlehttp/guzzle": "~6.0",
 "symfony/dom-crawler": "3.4.*",
 "symfony/css-selector": "3.4.*",
 "fabpot/goutte" : "^3.1"
 }
}
 

 

Guzzle + Dom crawler + css selector 라이브러리를 사용했는데, 굳이 따로 쓸필요없이, Goutte 라이브러리만 써도 된다. 아래 예제에서 Sir class는 위의 방식대로 작업한것이고, 아래 Sir2 클래스 파일은 Goutte를 사용한 방식이다. 내부에서 쓰는 라이브러리가 동일함으로 그냥 Goutte 를 쓰는걸 추천한다. 

 

require __DIR__."/vendor/autoload.php";
 
use GuzzleHttp\Client;
use Symfony\Component\DomCrawler\Crawler;
class Sir
{
    private $protocol = "http";
    private $doamin = "sir.co.kr";
 
    public function __construct() {
    }
    public function __destruct() {
    }
    public function getList($page = 1) {
        $bo_table = "cm_free"; //자유게시판명
        $url = $this->protocol."://".$this->doamin."/{$bo_table}/p{$page}";
        $client = new GuzzleHttp\Client();
        //http 접속시 ssl 오류가 발생하면, ['verify' => false] 옵션을 추가한다.
        $result = $client->request('GET', $url, ['verify' => false]);
        $html = $result->getBody()->getContents();
        $dom = new Crawler($html);
        $items = $dom->filter('div.sir_ul01 ul')->children();
        $result = array();
        foreach($items as $item) {
            $row = array();
            $obj = new Crawler($item);
            try {
                $title =  $obj->filter('a.title_link')->text();
                $href = $obj->filter('a.title_link')->attr("href");
                if(strpos($href, "//") ===0) $href = $this->protocol.":".$href;
                $row['title'] = trim($title);
                $row['href'] = trim($href);
                $result[] = $row;
            } catch(Exception $e) {
                echo $e->getMessage();
            }
        }
        return $result;
    }
    /**
     * url 에 있는 파일을 다운받아 $filepath 에 저장한다.
     * $filepath 는 cheditor 경로
     * @param $url
     * @param $filepath
     * @param $is_dryrun true : 실제 파일다운로드를 실행하지 않음. default : false
     */
    public function downloadAndSaveImage($url, $filepath, $is_dryrun = false) {
        if(!$is_dryrun) {
            $file_handle = fopen($filepath, 'w');
            $client = new \GuzzleHttp\Client();
            $response = $client->get($url, ['save_to' => $file_handle]);
            return ['response_code'=>$response->getStatusCode(), 'url' => $url];
        } else {
            return ['response_code'=>200, 'url' => $url];
        }
    } 
}​ ​ 

require __DIR__."/vendor/autoload.php";
 
use Goutte\Client;
use Symfony\Component\DomCrawler\Crawler;
class Sir2
{
    private $protocol = "http";
    private $doamin = "sir.co.kr";
    public function __construct() {
    }
    public function __destruct() {
    }
    public function getList($page = 1) {
        $bo_table = "cm_free"; //자유게시판 id
        $url = $this->protocol."://".$this->doamin."/{$bo_table}/p{$page}";
        $client = new \Goutte\Client();
        // Create and use a guzzle client instance that will time out after 90 seconds
        $guzzleClient = new \GuzzleHttp\Client(array(
            'timeout' => 90,
            'verify' => false,
        ));
        $client->setClient($guzzleClient);
        $crawler = $client->request('GET', $url);
        $items = $crawler->filter('div.sir_ul01 ul')->children();
 
        $result = array();
        foreach($items as $item) {
            $row = array();
            $obj = new Crawler($item);
            try {
                $title =  $obj->filter('a.title_link')->text();
                $href = $obj->filter('a.title_link')->attr("href");
                if(strpos($href, "//") ===0) $href = $this->protocol.":".$href;
                $row['title'] = trim($title);
                $row['href'] = trim($href);
                $result[] = $row;
            } catch(Exception $e) {
                echo $e->getMessage();
            }
        }
        print_r($result);
        return $result;
    }
    public function getMemoList($page = 1) {
        $login_url = $this->protocol."://".$this->doamin."/bbs/login.php";
        $memo_url = $this->protocol."://".$this->doamin."/bbs/memo.php";
        $client = new \Goutte\Client();
        // Create and use a guzzle client instance that will time out after 90 seconds
        $guzzleClient = new \GuzzleHttp\Client(array(
            'timeout' => 90,
            'verify' => false,
        ));
        $client->setClient($guzzleClient);
        $crawler = $client->request('GET', $login_url);
        //$crawler = $client->click($crawler->selectLink('로그인')->link());
        $form = $crawler->selectButton('로그인')->form();
        $crawler = $client->submit($form, array('mb_id' => 'your_id', 'mb_password' => 'your_password'));
        //todo 로그인 오류 체크
        $crawler = $client->request('GET', $memo_url);
        $items = $crawler->filter('div.tbl_wrap table tbody')->children();
        $result = array();
        foreach($items as $item) {
            $row = array();
            $obj = new Crawler($item);
            $sender_name =  $obj->filter("td")->eq(1)->filter("a")->text();
            $sender_link =  $obj->filter("td")->eq(1)->filter("a")->attr("href");
            $parts = parse_url($sender_link);
            parse_str($parts['query'], $query);
            $send_mb_id = $query['mb_id'];
            $send_datetime =  $obj->filter("td")->eq(2)->text();
            $read_datetime =  $obj->filter("td")->eq(3)->text();
            $row['send_mb_nick'] = $sender_name;
            $row['send_mb_id'] = $send_mb_id;
            $row['send_datetime'] = $send_datetime;
            $row['read_datetime'] = $read_datetime;
            $result[] = $row;
        }
        return $result;
    }
    /**
     * url 에 있는 파일을 다운받아 $filepath 에 저장한다.
     * $filepath 는 cheditor 경로
     * @param $url
     * @param $filepath
     * @param $is_dryrun true : 실제 파일다운로드를 실행하지 않음. default : false
     */
    public function downloadAndSaveImage($url, $filepath, $is_dryrun = false) {
        if(!$is_dryrun) {
            $file_handle = fopen($filepath, 'w');
            $client = new \GuzzleHttp\Client();
            $response = $client->get($url, ['save_to' => $file_handle]);
            return ['response_code'=>$response->getStatusCode(), 'url' => $url];
        } else {
            return ['response_code'=>200, 'url' => $url];
        }
    } 
}​ ​ 

 

include_once('./_common.php');
ini_set('display_errors', 'On');
error_reporting(E_ALL & ~E_NOTICE);
include_once __DIR__."/Sir.php";
include_once __DIR__."/Sir2.php";
$sir = new Sir();
$sir2 = new Sir2();
 
for($i = 0; $i < 3; $i++) {
    $list = $sir->getList($i); //자유게시판 리스트를 스크래핑(파싱)한다.
    echo "<xmp>";
    print_r($list);
    echo "</xmp>";
}
echo "<h1>내쪽지함</h1><br>";
$list = $sir2->getMemoList(1); //로그인후 내쪽지함 목록을 파싱한다.
echo "<xmp>";
print_r($list);
echo "</xmp>";​ 

0
0
이 글을 페이스북으로 퍼가기 이 글을 트위터로 퍼가기 이 글을 카카오스토리로 퍼가기 이 글을 밴드로 퍼가기
captcha
자동등록방지 숫자입력

PHP/Python

번호 제목 글쓴이 날짜 조회수
77 PHP 정말로 URL이 존재 하는지를 알고 싶다면 미도어묵 01-12 1,042
76 PHP [Nginx PHP-FPM] 페이지 access denied. 뜨는 현상 (see security.limit_extensions) - php7 … 미도어묵 11-05 1,206
75 PHP PHP를 이용한 심플한 게시판 파싱 미도어묵 11-01 1,078
74 PHP CI3 / php7.1 이상 버전 session 버그시~~~ 미도어묵 10-31 694
73 PHP PHP 5 Forms - Validate E-mail and URL 미도어묵 10-01 660
72 PHP php 전화번호 정규식 미도어묵 06-25 761
71 PHP 문자열에 휴대폰번호가 있으면 010-***-****으로 변경. 미도어묵 06-25 752
70 PHP 영상 썸네일 api function 미도어묵 02-13 748
69 PHP php memcached example 미도어묵 01-02 699
68 PHP php curl 을 이용한 자동 로그인 미도어묵 12-22 849
67 PHP Home / APIs / Requests::register_autoloader() – Register the built-in autoloader 미도어묵 12-21 761
66 PHP 업로드된 이미지 정사각형으로 썸네일 만드는 함수 미도어묵 11-01 759
65 PHP PHP + redis(phpredis) 연동하기 기본 사용 샘플 미도어묵 09-18 1,273
64 PHP Simple PHP MySQL Rest API Sample Example Tutorial 미도어묵 09-15 721
63 PHP Creating a simple REST API in PHP 미도어묵 09-15 704
62 PHP 게시물이 삭제 되었습니다 관리자 08-30 794
61 PHP php 링크 파일 다운받기 관리자 08-28 730
60 PHP php용 형태소 분석기 설치 및 바인딩과 실사용 +1 관리자1 08-28 985
59 PHP PHP로 HTML DOM 파싱하기 관리자 08-25 726
58 PHP PHP7: install ext-dom issue(composer require --dev phpunit/phpunit) 관리자 08-04 752