# 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依賴管理工具