900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > php使用guzzlehttp/guzzle进行数据采集

php使用guzzlehttp/guzzle进行数据采集

时间:2020-11-06 03:21:21

相关推荐

php使用guzzlehttp/guzzle进行数据采集

php使用guzzlehttp/guzzle进行数据采集

一、需求目的1、采集某个平台网站的数据2、将采集回来的数据与本身平台系统的现有数据汇总 二、实现步骤1、分析平台网站2、确定方案3、封装功能类4、使用功能类进行后续处理 三、具体实现开启数据抓取脚本开启数据同步脚本界面展示

一、需求目的

1、采集某个平台网站的数据

2、将采集回来的数据与本身平台系统的现有数据汇总

二、实现步骤

1、分析平台网站

分析登录校验方式 session 或 token 分析界面数据渲染方式 异步数据渲染 或 直接页面和数据一起渲染

2、确定方案

分析后,发现网站的登录比较简单,直接账号密码登录即可,并且登录校验是通过cookie进行校验的分析后,发现界面数据的渲染方式是异步数据渲染,代表有接口可以返回数据,直接对接口进行请求即可

3、封装功能类

确认完方案后,为了后续使用方便,特意封装一个功能类,其他地方使用的时候就比较简单

一、设置基础信息

- 设置对应平台域名

- 设置对应的账号密码

- 设置cookie序列化后保存的路径

二、功能方法

- 获取句柄方法(带cookie)

- 认证授权方法

- 带cookie的请求方法

- 简单的http方法

- 外部API返回处理方法

- 某个数据列表页面的获取等

4、使用功能类进行后续处理

三、具体实现

开启数据抓取脚本

使用功能类获取某个数据列表接口,得```json{'count'=>10000,'data_list'=>[{...}]}```获取这批数据在数据库的流水号,并分开保存在数据库表 log 中(为了后续有个计算抓取进度,我把这个数据保存放在了功能类中,每获取完一次接口,都先保存到数据库,同时还保存了要抓取的总数量)

开启数据同步脚本

读取数据库 log 表,按id升序取n条记录

循环记录列表

设置记录状态修改为处理中

具体同步的逻辑(每个人不一样,这里就不展开了)

将记录状态修改为已完成(或者处理失败等)

界面展示

其他数据展示就不说了,这里写一下进度条的展示

找个进度条的代码样式(网上应该很多,我这里用的是后台管理模版自带的)

获取进度数据

数据抓取进度 获取log表最后一条数据的流水号,并得到该流水号要获取的总数量(总数量/每次获取的数量)+1 ,得到该流水号共有多少条记录总记录数量/当前流水号的记录数量,得数据抓取进度 数据同步进度 获取同批流水号记录,通过状态 未处理 等状态判断未处理和已处理的数量已处理 / 总数量,得数据同步进度 将进度和当前属于哪种进度的相关信息返回(界面简单通过定时器和ajax,所以可以看到进度条和文字在变化)

功能类代码

<?phpnamespace App\Common\Features;use App\Common\Models\SyncLog;use App\Common\Repositories\LogRepositorie;use App\Exceptions\ErrorCode;use GuzzleHttp\Client;use GuzzleHttp\Cookie\CookieJar;use GuzzleHttp\Cookie\SetCookie;use Illuminate\Support\Facades\Redis;class Feature{//地址private $apiHost;//账号private $username;//密码private $password;//cookie保存路径private $cookieJar;private $cookie;private $client;private $LogRepo;public function __construct(){$this->apiHost = '';$this->username = '';$this->password = '';$this->cookieJar = 'cookie/login.cookie';$this->LogRepo = new LogRepositorie();}/*** 获取句柄* @return Client*/public function getClient(){if (empty($client)) {$this->cookie = new CookieJar;$this->client = new Client(array('cookies' => $this->cookie));}return $this->client;}/*** 认证授权* @throws \GuzzleHttp\Exception\GuzzleException*/public function auth(){$retryCount = 3;//认证问题不通过3次重试$response = null;while ($retryCount > 0) {$retryCount--;try {$isAuth = false;try {//获取cookie和句柄$cookieContent = file_get_contents($this->cookieJar);$cookieObject = unserialize($cookieContent);//$client = new Client(array('cookies' => $cookieObject));$response = $client->request('GET', $this->apiHost . '/xxx');//先尝试请求某个要登录的接口$result = $this->loadResult($response);$this->client = $client;//如果成功则句柄和cookie有效$this->cookie = $cookieObject;return;} catch (\Exception $e) {$isAuth = true;}//判断是否需要登录if ($isAuth) {//使用登录接口$this->getClient();$result = $this->client->request('POST', $this->apiHost . '/login', ['timeout' => 30,'form_params' => ['username' => $this->username,'password' => $this->password,]]);//登录成功保存cookie$cookie = $this->cookie;$cookieContent = serialize($cookie);file_put_contents($this->cookieJar, $cookieContent);}$retryCount = 0;return;} catch (\Exception $e) {}}//抛异常}public function dataSearch(){$uri = '/xxx';//获取记录批次流水$serial_number = $this->LogRepo->getSerialNumber(['uri' => $uri]);//循环获取数据$flag = true;$pageSize = 500;$page = 1;$totalItems = 0;$orderArrayList = [];while ($flag) {$request = ['pageSize' => $pageSize,'page' => $page,];$request_type = 'post';$result = $this->request($uri, $request_type, $request, $serial_number);if (!empty($result['list'])) {$orderArrayList[] = $result['list'];} else {$totalItems = $result['totalItems'];$flag = false;}echo '共 ' . (ceil(($result['totalItems'] / $pageSize)) + 1) . " 页,第 " . $page . ' 页结束,' . date('Y-m-d H:i:s') . "\n";sleep(5);$page++;}$response = ['count' => count($orderArrayList),'data_list' => $orderArrayList,];return $response;}/*** 带cookie的请求方法* @param $uri* @param string $method* @param array $queryData* @param string $serial_number* @param string $resultType* @return false|mixed|string* @throws \GuzzleHttp\Exception\GuzzleException*/public function request($uri, $method = 'get', $queryData = [], $serial_number, $resultType = 'array'){//这里新增记录,为了后续的进度统计$syncLog = $this->LogRepo->addSyncLog(['uri' => $uri,'serial_number' => $serial_number,'request_type' => $method,'request' => $queryData,]);$syncLogId = $syncLog['id'];$this->auth();$result = $this->http($uri, $method, $queryData, [], $resultType);//更新同步记录的结果$this->LogRepo->updateSyncLog(['id' => $syncLogId], ['response' => $result,'status' => SyncLog::STATUS_WAIT_SYNC,'grab_time' => time(),]);return $result;}/*** 简单的http方法* @param $uri* @param string $method* @param array $queryData* @param array $headerData* @param string $resultType* @return false|mixed|string* @throws \GuzzleHttp\Exception\GuzzleException*/public function http($uri, $method = 'get', $queryData = [], $headerData = [], $resultType = 'array'){$url = $this->apiHost . $uri;$headers = ['Content-Type' => 'application/x-www-form-urlencoded'//'Content-Type' => 'application/json;charset=UTF-8'];if (is_array($headerData)) {$headers = array_merge($headers, $headerData);}$params = [];if (!empty($queryData) && is_array($queryData)) {if ($method == 'get') {$params['query'] = $queryData;} else {if ($headers['Content-Type'] == 'application/x-www-form-urlencoded') {$params['form_params'] = $queryData;} else {$params['json'] = $queryData;}}}if (!empty($headers) && is_array($headers)) {$params['headers'] = $headers;}$response = $this->client->request($method, $url, $params);$result = $this->loadResult($response);if (strtolower($resultType) == 'array') {return $result;} else if (strtolower($resultType) == 'json') {return json_encode($result, true);}}/*** 外部API返回处理* @param $response* @return mixed*/protected function loadResult($response){$response_code = $response->getStatusCode();$result = $response->getBody()->getContents();$result = json_decode($result, true);if (!isset($result['success']) || $result['success'] != true) {}return $result['data'];}}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。