머리말
이번 글은 주로 PHP를 활용한 바이두리딩 캡처 방법을 소개합니다.
크롤링 방법은 다음과 같습니다
먼저 브라우저에서 독서 페이지를 열어서 소스코드를 확인하여 소설의 내용이 직접 쓰여져 있지 않은지 확인하세요. 즉, 소설의 내용이 비동기적으로 로드된다고 합니다.
그래서 Chrome의 개발자 도구를 네트워크 열로 전환하고 읽기 페이지를 새로 고치고 XHR과 스크립트의 두 가지 범주에 집중했습니다.
조사 결과 스크립트 카테고리에 소설 내용과 유사한 jsonp 요청이 있는 것으로 확인되었습니다. 요청한 주소는
http://www.php.cn/ 응답은
jsonp문자열이었고, 주소에서
callback=wenku7를 제거하면 반환되는 것은
json문자열이라는 것을 알았습니다. 구문 분석하기가 훨씬 더 편리하며 PHP에서 배열로 직접 변환할 수 있습니다.
반환된 데이터의 구조를 분석해 보겠습니다. 반환된
json문자열 뒤에는 트리와 같은 구조가 있습니다. 각 노드에는 t 속성이 있음을 나타냅니다. h2 p 등과 같은 이 노드의 레이블, c 속성은 내용이지만 두 가지 가능성이 있습니다. 하나는 문자열이고 다른 하나는 배열이며 배열의 각 요소는 노드입니다.
이런 종류의 구조는 파싱하기에 가장 좋으며, 한 번의 재귀로 수행할 수 있습니다
최종 코드는 다음과 같습니다.
<?php class BaiduYuedu { protected $bookId; protected $bookToken; protected $cookie; protected $result; public function __construct($bookId, $bookToken, $cookie){ $this->bookId = $bookId; $this->bookToken = $bookToken; $this->cookie = $cookie; } public static function parseNode($node){ $str = ''; if(is_string($node['c'])){ $str .= $node['c']; }else if(is_array($node['c'])){ foreach($node['c'] as $d){ $str .= self::parseNode($d); } } switch($node['t']){ case 'h2': $str .= "\n\n"; break; case 'br': case 'p': case 'p': $str .= "\n"; break; case 'img': case 'span': break; case 'obj': $tmp = '(' . self::parseNode($node['data'][0]) . ')'; $str .= str_replace("\n", '', $tmp); break; default: trigger_error('Unkown type:'.$node['t'], E_USER_WARNING); break; } return $str; } public function get($page = 1){ echo "getting page {$page}...\n"; $ch = curl_init(); $url = sprintf('http://wenku.baidu.com/content/%s/?m=%s&type=json&cn=%d', $this->bookId, $this->token, $page); curl_setopt_array($ch, array( CURLOPT_URL => $url, CURLOPT_RETURNTRANSFER => 1, CURLOPT_HEADER => 0, CURLOPT_HTTPHEADER => array('Cookie: '. $this->cookie) )); $ret = json_decode(curl_exec($ch), true); curl_close($ch); $str = ''; if(!empty($ret)){ $str .= self::parseNode($ret); $str .= $this->get($page + 1); } return $str; } public function start(){ $this->result = $this->get(); } public function getResult(){ return $this->result; } public function saveTo($path){ if(empty($this->result)){ trigger_error('Result is empty', E_USER_ERROR); return; } file_put_contents($path, $this->result); echo "save to {$path}\n"; } } //使用示例 $yuedu = new BaiduYuedu('49422a3769eae009581becba', '8ed1dedb240b11bf0731336eff95093f', '你的百度域cookie'); $yuedu->start(); $yuedu->saveTo('result.txt');
이 클래스의 처음 두 매개변수는 소설의 소개 페이지에서 얻을 수 있습니다. 첫 번째 매개변수
bookId는
url
ebook
에서 두 번째 매개변수
bookToken
는 페이지 소스 코드의
bdjsonUrl
를 검색하고
m
매개변수 뒤의 문자열은 다음과 같습니다. .
참고:
Baiducookie
가 전달되지 않거나 Baidu
cookie
가 유효하지 않은 경우 무료 읽기 부분만 캡처할 수 있으며, 완전한 것을 캡쳐해야 합니다. 콘텐츠는
cookie
가 정상적으로 사용될 수 있도록 보장되어야 합니다.
요약
위는 PHP를 사용하여 바이두리딩을 캡쳐하는 방법의 예시입니다. PHP 중국어 홈페이지(www.php.cn)!