# php爬虫技术4
---
## 爬虫抓取方式
1. 接口
2. 网页
3. 心得
---
### 1. 接口
* 很多网站是第三方平台,可以直接调用接口数据。
* 比如:
* 腾讯开发平台:微信登录、微信支付。网址:open.tencent.com
* 阿里巴巴开放平台:产品、物流、会员、搜索。网址:open.1688.com
* 聚合数据:短信验证码、快递、天气、车辆违章。网址:www.juhe.cn
* 我们做个聚合数据示例:
* 手机号码归属地key:4d6cce531387deeedf359687fb04c163
* 全国天气预报key:abc4b64ae7656b460723402175a5650b
> **示例:**
```php
$url = "http://v.juhe.cn/weather/citys";
$params = array(
"key" => "db741b7e6bcb5d461ce892c1f16040fd",
);
$paramstring = http_build_query($params);
$content = juheCurl($url, $paramstring);
$result = json_decode($content, true);
if ($result) {
return_json(0,$result);
} else {
return_json(1,'接口出错');
}
// json数据格式整理
function return_json($code,$data=array()){
if($code == 0){
$array = array(
'code' => 0,
'msg' => 'success',
'data' => $data
);
}else{
$array = array(
'code' => $code,
'msg' => $data
);
}
echo json_encode($array);
exit;
}
// 通过curl请求接口
function juheCurl($url, $params = false, $ispost = 0){
$httpInfo = array();
$ch = curl_init();
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); // 默认值,让 cURL 自己判断使用哪个版本。 (强制使用 HTTP/1.1)。
curl_setopt($ch, CURLOPT_USERAGENT, 'JuheData'); // 在HTTP请求中包含一个"User-Agent: "头的字符串。
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 60); // 在尝试连接时等待的秒数。设置为0,则无限等待。
curl_setopt($ch, CURLOPT_TIMEOUT, 60); // 设置超时限制防止死循环
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 要求结果保存到字符串中还是输出到屏幕上
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); // 爬取重定向页面
if ($ispost) {
curl_setopt($ch, CURLOPT_POST, true); // 发送一个常规的Post请求
curl_setopt($ch, CURLOPT_POSTFIELDS, $params); // Post提交的数据包
curl_setopt($ch, CURLOPT_URL, $url); // 设置URL
} else {
// GET请求,组装url
if ($params) {
curl_setopt($ch, CURLOPT_URL, $url.'?'.$params);
} else {
curl_setopt($ch, CURLOPT_URL, $url);
}
}
$response = curl_exec($ch); // 运行cURL,请求URL,把结果复制给变量
if ($response === FALSE) {
echo "cURL Error: " . curl_error($ch); //捕抓异常
return false;
}
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); // 获取一个cURL连接资源句柄的信息
$httpInfo = array_merge($httpInfo, curl_getinfo($ch));
curl_close($ch);
return $response;
}
```
---
### 2. 网页
* 网页抓取,我们拿新闻做案例:news.cyol.com
* 新闻网站,我们一般不抓取热门,只会抓取分类和新闻列表,新闻内容
* 很多网站也是这样,比如淘宝网站,我们不可能抓取首页上的商品
* 没有规则的,抓取后,无法批量处理。而且推荐的商品,在列表里也会有这条商品的。
> 第一步:找寻新闻分类接口、或新闻分类规则
* zqbapp.cyol.com/zqzxapi/api.php?s=/Web/getTypeListCache
> 第二步:根据数据,创建数据库
> news_source_cat:来源分类表
```php
CREATE TABLE `news_source_cat` (
`cat_id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '分类ID',
`source_id` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '来源ID',
`source_fid` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '来源父ID',
`source_name` varchar(50) NOT NULL COMMENT '来源分类名',
`source_status` tinyint(1) unsigned NOT NULL DEFAULT '1' COMMENT '来源状态 1开启 0禁用',
`num` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '抓取次数',
PRIMARY KEY (`cat_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='来源分类表';
```
> 第三步:抓取数据,存储到数据库
```php
require 'function.php';
$url = "https://zqbapp.cyol.com/zqzxapi/api.php?s=/Web/getTypeListCache";
// 获取到数据
$a = juheCurl($url);
// 去除数据的开头括号 和 结束括号
$a = substr($a,1);
$a = substr($a,0,strlen($a)-1);
// json解析获取的数据
$b = json_decode($a,true);
// 循环处理数据
foreach ($b['data'] as $v) {
if($v['tid'] <= 0){
continue;
}else{
setCatData($v);
}
}
return true;
function setCatData($a){
$data = array(
'source_id' => $a['tid'],
'source_fid'=> $a['pid'],
'source_name' => $a['cnname']
);
$ret = insert('news_source_cat',$data);
if(empty($ret)){
return false;
}
if(!empty($a['childs'])){
foreach($a['childs'] as $v){
setCatData($v);
}
}
}
```
> 第四步:找寻新闻列表接口、或新闻列表规则
* zqbapp.cyol.com/zqzxapi/api.php?s=/Web/getNewsListCache/tid/767/page/1
> 第五步:根据数据,创建数据库
> news_list:来源新闻表
```php
CREATE TABLE `news_list` (
`news_id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '新闻ID',
`cat_id` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '本地分类ID',
`source_id` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '来源ID',
`source_nid` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '来源新闻ID',
`title` varchar(500) NOT NULL COMMENT '标题',
`title_md5` char(32) NOT NULL COMMENT '加密后的标题',
`f_title` varchar(500) NOT NULL COMMENT '父标题',
`type` tinyint(3) unsigned NOT NULL DEFAULT '1' COMMENT '类型 1文字新闻 2图文新闻 3联图新闻 4三连图 5普通新闻大图 6 视频 7 H5 8广告 9直播',
`img` varchar(500) NOT NULL COMMENT '图片',
`url` varchar(500) NOT NULL COMMENT '详情网址',
`content` text NOT NULL COMMENT '新闻详情',
PRIMARY KEY (`news_id`)
) ENGINE=MyISAM AUTO_INCREMENT=160 DEFAULT CHARSET=utf8 COMMENT='新闻列表';
```
> 第六步:抓取数据,存储到数据库
```php
require 'function.php';
// 查询分类表,单条数据
$cat = find('news_source_cat','*','source_status=1','num');
for($i=1;$i<=5;$i++){
if($cat['source_fid'] == 676){
$url = 'https://zqbapp.cyol.com/zqzxapi/api.php?s=/Web/getNewsListCache/tid/'.$cat['source_id'].'/page/'.$i;
}else{
$url = 'https://zqbapp.cyol.com/zqzxapi/api.php?s=/Web/typeHomePage/tid/'.$cat['source_id'].'/Page/'.$i;
}
// 获取到数据
$a = curl_data($url);
// 去除数据的开头括号 和 结束括号
$a = substr($a,1);
$a = substr($a,0,strlen($a)-1);
// json解析获取的数据
$b = json_decode($a,true);
// 循环处理数据
if($b['code'] == '200'){
if($cat['source_fid'] == 676){
foreach ($b['data'] as $v){
$ret = setListData($v);
echo $ret;
}
}else{
foreach ($b['data']['typenews'] as $v){
$ret = setListData($v);
echo $ret;
}
}
}
}
function setListData($a){
// 赋值标题给新变量
$title = trim($a['title']);
// 查询新闻是否已存在,存在进入下一条新闻抓取
$news = find('news_list','*','title_md5="'.md5($title).'"');
if($news){
return $a['nid'].'已存在,采集失败!<br/>';
}
// 通过来源ID,查询本项目分类ID
$cat = find('news_source_cat','*','source_id='.$a['tid']);
// 接口的方式,无法得到新闻详情
/*
* $url = 'https://zqbapp.cyol.com/zqzxapi/api.php?s=/News/newsinfo';
* $curl = curl_data($url,array('device'=>12,'nid'=>$a['nid']),1);
*/
// 抓取新闻详情url数据
$curl = curl_data($a['newsurl']);
// 正则表达式
$pattem = '/<div class="news-content dd" id="news-content">(.*?) <\/div>/si';
// 截取需要的文章详情
$preg = preg_match($pattem,$curl,$matches);
$content = $matches[1].'</div>';
// 把来源网站的图片标识,替换为HTML标识
$content = preg_replace('/data-original/','src',$content);
$data = array(
'cat_id' => $cat['cat_id'],
'source_id' => $a['tid'],
'source_nid'=> $a['nid'],
'title' => $title,
'title_md5' => md5($title),
'f_title' => $a['outline'],
'type' => $a['type'],
'img' => $a['imgs'][0],
'url' => $a['newsurl'],
'content' => htmlspecialchars($content),
);
$ret = insert('news_list',$data);
if(empty($ret)){
return $a['nid'].'采集失败!<br/>';
}
return $a['nid'].'采集成功!<br/>';
}
```
---
### 3. 抓取心得
* 尽可能找到要来源的接口。
* 如果来源有app,尽可能先从app进行获取接口。
* 如果来源没有app,可以找找来源有没有手机网页版。
* 手机网页版,也是用ajax请求列表,列表也属于接口返回。
* 只能抓取pc网页版,尽可能把正则写简单些。
* 比如抓取新闻:1,匹配标题。2,匹配新闻时间。3,匹配详情。
* 如果新闻详情,内容有不对称的,可以在后台做处理功能。
* 新闻列表,都是可以翻页的。需要记得抓取页数。每次不要超过100条抓取。
* 如果有重复的新闻。可以在抓取时,对新闻标题,进行md5加密
* 加密后,匹配数据库里的加密标题。不要用标题进行匹配,因为字符串匹配不够准确。
- 序言
- PHP基础
- 认识PHP
- 环境安装
- PHP语法
- 流程控制
- PHP数组
- PHP函数
- PHP类与对象
- PHP命名空间
- PHP7新特性
- PHP方法库
- PHP交互
- 前后端交互
- 项目常规开发流程
- MySQL数据库
- 会话控制
- Ajax分页技术
- 细说函数
- 类与对象
- 对象进阶
- 类与对象进阶
- OOP面向对象
- 设计模式
- 路由与模板引擎
- 异常类
- PHP爬虫
- PHP抓取函数
- PHP匹配函数
- 正则表达式
- PHP字符串函数
- 抓取实战
- PHP接口
- 了解接口
- PHP插件
- PHPSpreadsheet
- ThinkPHP6
- 安装
- 架构
- 数据库
- 数据库操作
- 视图
- 模版
- 模型
- 杂项
- 命令行
- 交互
- 微信小程序
- 介绍
- 配置
- 组件
- 交互
- API
- 其他知识
- 百度小程序
- 介绍
- 配置
- 组件
- 交互
- API
- 其他知识
- Linux
- 服务器上线流程
- 安装svn
- MySQL
- 认识MySQL
- MySQL函数
- 杂项
- composer依赖管理工具