这里有新鲜出炉的 PHP 面向对象编程,程序狗速度看过来!
PHP(外文名: Hypertext Preprocessor,中文名:"超文本预处理器")是一种通用开源脚本语言。语法吸收了 C 语言、Java 和 Perl 的特点,入门门槛较低,易于学习,使用广泛,主要适用于 web 开发领域。PHP 的文件后缀名为 php。
最近在百度阅读上购买了一本《永恒的终结》电子书,但是坑爹的发现只能在线阅读或者在手机 app 上阅读,不能下载下来放到 kindle 里。于是就尝试一下看能不能把这个文章下载下来。有需要的朋友们可以参考借鉴,下面来一起看看吧。
前言
这篇文章主要介绍的是,如何利用 PHP 抓取百度阅读的方法,下面话不多说,来一起看看吧。
抓取方法如下
首先在浏览器里打开阅读页面,查看源代码后发现小说的内容并不是直接写在页面里的,也就是说小说的内容是通过异步加载而来的。
于是将 chrome 的开发者工具切到 network 一栏,刷新阅读页面,主要关注的是 XHR 和 script 两个分类下。
经过排查,发现在 script 分类下有个 jsonp 请求比较像是小说内容,请求的地址是
http://wenku.baidu.com/content/49422a3769eae009581becba?m=8ed1dedb240b11bf0731336eff95093f&type=json&cn=1&_=1&t=1423309200&callback=wenku7
返回的是一个
字符串,然后我发现,如果把地址里面的
- jsonp
去掉,返回的就是一个
- callback=wenku7
字符串,这样解析起来就方便不少,可以直接在 php 里面转换成数组。
- json
再来分析一下返回数据的结构,返回的
字符串之后是一个树状的结构,每个节点都有一个 t 属性和 c 属性,t 属性用来指明这个节点的标签,比如 h2 div 等等,c 属性就是内容了,但也有两种可能,一个是字符串,另一个是数组,数组的每个元素都是一个节点。
- json
这种结构最好解析了,用一个递归就搞定
最终代码如下:
- <?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 'div':
- 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
注:如果不传入百度
或者百度
- cookie
无效,则只能抓取免费阅读部分,要抓完整的内容必须保证
- cookie
可以正常使用。
- cookie
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家学习或者使用 PHP 能有一定的帮助,如果有疑问大家可以留言交流。
来源: http://www.phperz.com/article/17/0806/340825.html