PHP如何采集網站數據


需求:

  對於剛搭建的網站,數據比較單一,那么如何采集點數據呢。

前言:

  這里我們可以用PHP寫的一個框架QueryList,官網文檔:http://www.querylist.cc/docs/guide/v4/overview;

說明:

  如果你之前沒有做過數據采集,希望快速的理解,和入門。那么下面的文字可以給你帶來幫助。

 

什么是數據采集:

  數據采集就是通過代碼,模擬瀏覽器請求,將第三方網站上資源(圖片資源,文字資源),采集到本地。簡而言之,比如有一個線上的博客網站,你自己也搭建了一個網站,但是沒有博客怎么辦。一般你可以通過復制粘貼,搬運到自己的網站上。所謂的數據采集,就是通過代碼實現剛才的操作流程。

 

核心處理點:

  這里使用代碼操作,主要就是兩塊:

    一個是,如何按規則選中我們要采集的網站字段;這個主要是用 DOM內容選擇:CSS選擇器

    一個是,如何將選中的數據采集下來;這個就是通過 HTTP客戶端:GuzzleHTTP

  簡而言之,代碼主要是用css選擇器按規則,選中需要采集的數據,然后用模擬HTTP客戶端請求,采集數據。

 

我們要做什么:

  現在,我們要將一個第三方網站的數據,采集下來,然后寫入到自己數據庫中。

我們大致怎么做:

  步驟一,按官方文檔,在自己項目(這邊項目是用tp6.0搭建的項目)中安裝QueryList擴展;

  步驟二,采集博客列表,然后循環列表,采集列表詳情,而后將詳情里面的圖片下載到本地,最后對數據進行處理,自己需要哪些字段就存取哪些字段;

  步驟三,對上面的數據進行格式化后,寫入到自己數據庫中;

上代碼:

  1、在ThinkPHP6.0項目中通過Composer安裝QueryList擴展

composer require jaeger/querylist

  2、DataCj.php控制器中引入 use QL\QueryList類,按步驟處理,用redis做數據中轉,最后拿到具體格式數據。對於選擇器的使用具體見QueryList文檔。

<?php
/*
 * @Fun: 數據采集
 * @User: JessieK
 * @Date: 2021-11-03 15:50:22
 */

namespace app\v1\controller;

use think\Request;
use QL\QueryList;
use think\facade\Cache;
use think\facade\Db;
use lib\XFace;
use think\Model;
class DataCj
{
    protected $api_url;//接口域名

    public function __construct()
    {
        $host = 1;//環境切換 1:test環境;2:prod環境
        if($host == 1){
            $this->api_url = 'https://a.cn';
        }else{
            $this->api_url = 'https://b.cn';
        }
    }

    /**
     * @name: 采集尋找朋友數據 列表
     * @param {Request} $request
     * @return {*}
     */    
    public function xunrenla_xunzhaopengyou(Request $request)
    {
        $page = $request->param('page', 1);
        $renewal = $request->param('renewal', 0);
        //放入緩存
        $redis = Cache::store('redis');
        $key = $request->action() .'_'. $page;
        $data_list = $redis->get($key);
        if(!$data_list || $renewal){
            //采集網址
            $url = 'http://www.xunrenla.com/xunzhaopengyou/list_6_'. $page .'.html';
            //元素采集規則
            $rules = [
                //姓名
                'name' => ['.siteContent a', 'title'],
                //詳情地址
                'url' => ['.siteContent a', 'href'],
                //圖片地址
                'img' => ['.siteImg img', 'src'],
            ];
            //切片選擇器,選擇列表范圍
            $range = '.layui-col-md8 .layui-card-body>div';
            //開始采集
            $rt = QueryList::get($url)->rules($rules)->range($range)->queryData();
            $rt_key = count($rt) - 1;
            unset($rt[$rt_key]);
            // d($rt);
            $res = $redis->set($key, $rt, 2592000);
            echo '開始寫入緩存'.$res;
            exit('寫入緩存,數量值='.$rt_key);
        }else{
            exit('已有緩存,數量值='. count($data_list));
        }
    }

    /**
     * @name: 采集尋找朋友數據 下載圖片到本地
     * @param {Request} $request
     * @return {*}
     */    
    public function xunrenla_xr(Request $request)
    {
        $page = $request->param('page', 1);
        $key = 'xunrenla_xunzhaopengyou_'. $page;
        //取的緩存里面的數據
        $redis = Cache::store('redis');
        $xr_list = $redis->get($key);
        if($xr_list){
            lg('已取出,開始處理圖片='. count($xr_list));
            //定義圖片存放路徑
            $img_path = runtime_path() . 'xrl_img/';
            $time = time();
            foreach($xr_list as $key => $value){
                //判斷圖片地址是否存在
                if(strstr($value['img'], 'http')){
                    $img_string = file_get_contents($value['img']);
                    lg('准備下載會員='.$value['name']);
                    //保存圖片
                    $name = md5($value['name'] . $time . $key).'.jpg';
                    $img_name = $img_path . $name;
                    $put_res = file_put_contents($img_name, $img_string);
                    lg('下載結果='.$put_res);
                    //追加路徑
                    $xr_list[$key]['img_path'] = $img_name;
                }else{
                    //刪除圖片不存在的
                    unset($xr_list[$key]);
                    lg('當前圖片路徑不存在,跳過');
                }
            }
            lg('准備寫入緩存,實際下載數量='.count($xr_list));
            $res = $redis->set($request->action() . '_'. $page, $xr_list, 2592000);
            exit('處理完成res='.$res);
        }else{
            exit('暫無數據');
        }
    }
    
    /**
     * @name: 圖片上傳 test服務器
     * @param {Request} $request
     * @return {*}
     */    
    public function xunrenla_upd_img(Request $request)
    {
        $page = $request->param('page', 1);
        $key = 'xunrenla_xr_'. $page;
        //取的緩存里面的數據
        $redis = Cache::store('redis');
        $xr_list = $redis->get($key);
        if(!$xr_list){
            exit('暫無數據');
        }
        $upd_key = $request->action() . '_'. $page;
        $upd_value = $redis->get($upd_key);
        if($upd_value){
            exit('已處理'.count($upd_value));
        }
        lg('開始處理圖片,待處理數='.count($xr_list));
        foreach($xr_list as $key => $value){
            //獲取圖片base64字符
            $base_sting = imgToBase64($value['img_path']);
            if($base_sting){
                lg('獲取圖片base64字符成功name'.$value['name']);
                lg('准備上傳test服務器');
                $https_res = httpCurl($this->api_url . '/index/baseStringApi', ['chars' => $base_sting, 'filename' => md5($value['name'])], 1);
                if($https_res && $https_res['code'] == 200){
                    lg('上傳成功path='.$https_res['data']['path']);
                    $xr_list[$key]['test_img_path'] = $https_res['data']['path'];//追加到新元素
                }else{
                    unset($xr_list[$key]);
                    lg('上傳失敗https_res='.$https_res['msg']);
                }
            }else{
                unset($xr_list[$key]);
                lg('獲取圖片base64失敗');
            }
        }
        lg('准備寫入緩存,實際上傳數='.count($xr_list));
        $res = $redis->set($upd_key, $xr_list, 2592000);
        exit('處理完成res='.$res);
    }

    /**
     * @name: 采集尋人朋友 列表詳情
     * @param {Request} $request
     * @return {*}
     */    
    public function xunrenla_details(Request $request)
    {
        $page = $request->param('page', 1);
        $key = 'xunrenla_upd_img_'. $page;
        //取的緩存里面的數據
        $redis = Cache::store('redis');
        $xr_list = $redis->get($key);
        if(!$xr_list){
            exit('暫無數據');
        }

        foreach($xr_list as $key => $value){
            $ql = QueryList::get($value['url']);
            lg('開始采集詳情='.$value['name']);
            $rt = [];
            $rt['name'] = jq_zh($ql->find('.layui-col-md9 li:nth-child(1)')->text(), ':');
            $rt['sex'] = jq_zh($ql->find('.layui-col-md9 li:nth-child(2)')->text(), ':');
            $rt['age'] = jq_zh($ql->find('.layui-col-md9 li:nth-child(3)')->text(), ':');
            $rt['lost_time'] = jq_zh($ql->find('.layui-col-md9 li:nth-child(4)')->text(), ':');
            $rt['jg'] = jq_zh($ql->find('.layui-col-md9 li:nth-child(5)')->text(), ':');
            $rt['szdd'] = jq_zh($ql->find('.layui-col-md9 li:nth-child(6)')->text(), ':');
            $rt['sg'] = jq_zq(jq_zh($ql->find('.layui-col-md9 li:nth-child(7)')->text(), ':'), 'C');
            $rt['lxr'] = jq_zh($ql->find('.layui-col-md9 li:nth-child(9)')->text(), ':');
            $rt['ph'] = jq_zq(jq_zh($ql->find('.layui-col-md9 li:nth-child(10)')->text(), ':'), '提');

            $rt['fp'] = jq_zh($ql->find('.layui-col-md8 .layui-hide-xs')->text(), ':');
            
            $rt['ms'] = jq_zh($ql->find('.article-content div:nth-child(1) p')->text(), ':');
            //數組詳情追加
            $xr_list[$key]['detaile'] = $rt;
        }

        lg('采集完成,准備寫入緩存');
        $res = $redis->set($request->action() . '_'. $page, $xr_list, 2592000);
        exit('處理完成res='.$res);
    }

    /**
     * @name: 對采集數據進行清洗,格式化經緯度
     * @param {Request} $request
     * @return {*}
     */    
    public function xunrenla_data_up(Request $request)
    {
        $page = $request->param('page', 1);
        $key = 'xunrenla_details_'. $page;
        //取的緩存里面的數據
        $redis = Cache::store('redis');
        $xr_list = $redis->get($key);
        if(!$xr_list){
            exit('暫無數據');
        }
        $upd_key = $request->action() . '_'. $page;
        $upd_value = $redis->get($upd_key);
        // d($upd_value);
        if($upd_value){
            exit('已處理'.count($upd_value));
        }
        // d($xr_list);
        lg('開始處理數據,待處理數='.count($xr_list));
        $data_list = [];
        foreach($xr_list as $key => $value){
            //解析地址
            lg('准備解析地址');
            $dzz = str_replace(' ', '', $value['detaile']['jg']);
            $addres_res = XFace::showLocation($dzz);
            if($addres_res['status']){
                lg('地址解析失敗,res='.$addres_res['msg']);
                unset($xr_list[$key]);
            }else{
                lg('解析成功,res='.$addres_res['msg']);
                $data_list[$key]['member_id'] = 8;//會員uid
                $data_list[$key]['member_name'] = '人人尋客服-小尋';//會員昵稱
                $data_list[$key]['member_headr'] = 'https://thirdwx.qlogo.cn/mmopen/vi_32/IxNUxicGvfiaibrSkUd9wMYibhOicua4icbwNUr8VQKKePQTnpUxxUL9kYTRBakq2Nsg9QxJVx4gpM5FHbibrOFloJwKQ/132';//會員頭像
                $data_list[$key]['lost_type'] = 1;//尋人類型,0找親人,1幫忙找',
                // $data_list[$key]['title'] = $value['name'];//尋人標題
                $data_list[$key]['name'] = $value['name'];//姓名
                if($value['detaile']['sex'] == '男'){//性別(1男,2女
                    $data_list[$key]['sex'] = 1;
                }else{
                    $data_list[$key]['sex'] = 2;
                }
                $data_list[$key]['age'] = getAge(strtotime($value['detaile']['age']));//年齡
                $data_list[$key]['height'] = $value['detaile']['sg'];//身高
                $data_list[$key]['face_img'] = $value['test_img_path'];//圖片
                // $data_list[$key]['phone'] = '';//手機號id
                // $data_list[$key]['lost_trait'] = $value['detaile']['ms'];//外貌特征
                $data_list[$key]['lost_time'] = strtotime($value['detaile']['lost_time'] . '14:35');//走失時間

                $data_list[$key]['lost_lon'] = $addres_res['data']['lon'];//走失地點(經度',
                $data_list[$key]['lost_lat'] = $addres_res['data']['lat'];//走失地點(緯度'

                // $data_list[$key]['address'] = $value['detaile']['szdd'];//具體位置(通過經緯度解析)
                // $data_list[$key]['province_id'] = 1;//省id',
                // $data_list[$key]['city_id'] = 1;//市id',
                // $data_list[$key]['district_id'] = 1;//區id',

                $data_list[$key]['address_detail'] =$dzz;//詳細地址(預留字段',
                $data_list[$key]['describe'] = str_replace(' ', '', $value['detaile']['ms']);//走失描述
                $data_list[$key]['insert_time'] = strtotime($value['detaile']['fp']);//創建時間
                $data_list[$key]['make_type'] = 2;//創建類型(1會員發布,2采集發布,默認為1',
                $data_list[$key]['m_phone'] = $value['detaile']['ph'];//采集發布,手機號',
                $data_list[$key]['laiyuan'] = '尋人啦www.xunrenla.com';//來源
            }
        }
        lg('采集完成,准備寫入緩存,實際寫入數='.count($data_list));
        $res = $redis->set($upd_key, $data_list, 2592000);
        exit('處理完成res='.$res);
    }

    /**
     * @name: 將采集數據 寫入test數據庫
     * @param {Request} $request
     * @return {*}
     */    
    public function xunrenla_data_insert(Request $request)
    {
        $page = $request->param('page', 1);
        $key = 'xunrenla_data_up_'. $page;
        //取的緩存里面的數據
        $redis = Cache::store('redis');
        $xr_list = $redis->get($key);
        // d($xr_list);die;
        if(!$xr_list){
            exit('暫無數據');
        }
        $debug = $request->param('debug', 0);
        if($debug != 99){
            d($xr_list);
            die;
        }
        lg('開始組裝數據');
        $inser_data = [];
        foreach($xr_list as $key => $value){
            //組裝數據
            $time = time();
            $pj_data = [
                'name' => $value['name'],
                'sex' => $value['sex'],
                'age' => $value['age'],
                'height' => $value['height'],
                'face_img' => $value['face_img'],
                // 'phone' => $data['phone'],

                'member_id' => $value['member_id'],
                'member_name' => $value['member_name'],
                'member_headr' => $value['member_headr'],

                'lost_type' => $value['lost_type'],
                // 'title' => $data['title'],
                // 'lost_trait' => $value['describe'],//外貌特征
                'lost_time' => $value['lost_time'],
                'lost_lon' => $value['lost_lon'],//經度
                'lost_lat' => $value['lost_lat'],//緯度
                'address_detail' => $value['address_detail'],//詳細位置
                // 'address' => $adres_res['data']['formatted_address'],//具體地址(經緯度解析

                // 'province_id' => $adres_res['data']['province_id'],
                // 'city_id' => $adres_res['data']['city_id'],
                // 'district_id' => $adres_res['data']['district_id'],
                
                'describe' => $value['describe'],//走失描述
                'insert_time' => $time,
                // 'update_time' => $time,
                'make_type' => $value['make_type'],
                'm_phone' => $value['m_phone'],
                'laiyuan' => $value['laiyuan'],
            ];
            $inser_data[$key] = $pj_data;
            // lg('准備寫入數據庫name='.$value['name']);
            // $tset_data = Db::table('t_lost_person')->insert($insert_data);
            // lg('寫入完成tset_data='.$tset_data);
            // die;
        }
        lg('組裝完成,總計inser_data='.count($inser_data));
        lg('准備批量寫入數據庫');
        $tset_data = Db::table('t_lost_person')->insertAll($inser_data);
        exit('批量寫入完成tset_data='.$tset_data);
        // d($inser_data);
    }
}

說明:

  以上請在采集的時候,注意網站版權問題,如上代碼,僅做學習使用,請勿用作商業用途。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM