利用PHP抓取百度阅读的方法示例


Posted in PHP onDecember 18, 2016

前言

这篇文章主要介绍的是,如何利用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去掉,返回的就是一个json字符串,这样解析起来就方便不少,可以直接在php里面转换成数组。

再来分析一下返回数据的结构,返回的json字符串之后是一个树状的结构,每个节点都有一个t属性和c属性,t属性用来指明这个节点的标签,比如h2 div等等,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 '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就是urlebook后面跟着的字符串,第二个参数bookToken在页面源代码搜索bdjsonUrlm参数后面的那个字符串就是。

注:如果不传入百度cookie或者百度cookie无效,则只能抓取免费阅读部分,要抓完整的内容必须保证cookie可以正常使用。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家学习或者使用PHP能有一定的帮助,如果有疑问大家可以留言交流。

PHP 相关文章推荐
E路文章系统PHP
Dec 11 PHP
PHP 得到根目录的 __FILE__ 常量
Jul 23 PHP
php 字符过滤类,用于过滤各类用户输入的数据
May 27 PHP
PHP中使用addslashes函数转义的安全性原理分析
Nov 03 PHP
php+mysqli使用面向对象方式更新数据库实例
Jan 29 PHP
[原创]php获取数组中键值最大数组项的索引值
Mar 17 PHP
php实现的简单美国商品税计算函数
Jul 13 PHP
php微信开发自定义菜单
Aug 27 PHP
PHP入门教程之面向对象基本概念实例分析
Sep 11 PHP
谈谈从phpinfo中能获取哪些值得注意的信息
Mar 28 PHP
laravel5.6 框架邮件队列database驱动简单demo示例
Jan 26 PHP
tp5框架前台无限极导航菜单类实现方法分析
Mar 29 PHP
详解PHP数据压缩、加解密(pack, unpack)
Dec 17 #PHP
Yii2中datetime类的使用
Dec 17 #PHP
php生成二维码图片方法汇总
Dec 17 #PHP
PHP二维数组去重算法
Dec 17 #PHP
php格式化时间戳
Dec 17 #PHP
PHP生成唯一ID之SnowFlake算法
Dec 17 #PHP
简单解决微信文章图片防盗链问题
Dec 17 #PHP
You might like
PHP中new static()与new self()的区别异同分析
2014/08/22 PHP
php使用str_replace实现输入框回车替换br的方法
2014/11/24 PHP
又十个超级有用的PHP代码片段
2015/09/24 PHP
PHP自定义函数获取URL中一级域名的方法
2016/08/23 PHP
php表单文件iframe异步上传实例讲解
2017/07/26 PHP
广泛收集的jQuery拖放插件集合
2012/04/09 Javascript
页面js遇到乱码问题的解决方法是和无法转码的情况
2014/04/30 Javascript
Ext GridPanel加载完数据后进行操作示例代码
2014/06/17 Javascript
简单的jQuery入门指引
2015/07/28 Javascript
基于jQuery实现选取月份插件附源码下载
2015/12/28 Javascript
js 动态生成json对象、时时更新json对象的方法
2016/12/02 Javascript
浅析BootStrap中Modal(模态框)使用心得
2016/12/24 Javascript
Vue源码学习之初始化模块init.js解析
2017/11/02 Javascript
Vue全家桶实践项目总结(推荐)
2017/11/04 Javascript
layDate日期控件使用方法详解
2018/11/15 Javascript
详解mpvue中小程序自定义导航组件开发指南
2019/02/11 Javascript
Element Dialog对话框的使用示例
2020/07/26 Javascript
[04:40]DOTA2-DPC中国联赛1月26日Recap集锦
2021/03/11 DOTA
在Python中使用判断语句和循环的教程
2015/04/25 Python
Python字符串格式化输出方法分析
2016/04/13 Python
pandas求两个表格不相交的集合方法
2018/12/08 Python
Python实现点阵字体读取与转换的方法
2019/01/29 Python
python中time.ctime()实例用法
2021/02/03 Python
利用指针变量实现队列的入队操作
2012/04/07 面试题
建筑公司文秘岗位职责
2013/11/29 职场文书
开水果连锁店创业计划书
2013/12/29 职场文书
安全责任书范本
2014/04/15 职场文书
初三学习计划书范文
2014/04/30 职场文书
文秘专业应届生求职信
2014/05/26 职场文书
国家领导干部党的群众路线教育实践活动批评与自我批评材料
2014/09/23 职场文书
见习报告的格式
2014/11/04 职场文书
孕妇离婚协议书范本
2014/11/20 职场文书
2014年统计工作总结
2014/11/21 职场文书
庆祝教师节新闻稿
2015/07/17 职场文书
公司客户答谢酒会祝酒词
2015/08/11 职场文书
JS数组去重详情
2021/11/07 Javascript