使用php采集网页数据一般有多种方法,有时候会使用正则去采集页面,但是当我们需要采集的页面大并且多的话,会严重的浪费我们的cpu,这时候我们可以使用phpQuer来进行采集,不知道phpQuery的童鞋可以去看看这是东西

以采集 http://www.rsq111.com/goods.php?id=15663 这个网站为例

假设我们需要采集商品的 分类 名称 价格 货号 上架时间 商品图片 详情图片

1.首先下载phpQuery类  phpQuery.php

2.接下里我们可以新建一个cj.php类

单页面采集

<?php

header("Content-Type: text/html; charset=UTF-8");
require("phpQuery.php"); //引入类 //检测当前链接是否合法
$url = 'http://www.rsq111.com/goods.php?id=15663';
$header_info=getHeaders($url,true);
if ($header_info != ) {
die;
} phpQuery::newDocumentFile($url); //获取网页对象内容
   //pq() == $(this)
// 商品分类
$arr_check = pq(".breadcrumb");
foreach ($arr_check as $li) {
$cat = pq($li)->text();
}
$category = explode('>', $cat); //商品标题
$h1_check = pq("#name");
$title = pq($h1_check)->text(); //商品价格
$price_check = pq(".rmbPrice");
$shop_price = [];
foreach ($price_check as $li) {
$shop_price[] = pq($li)->text();
}
$shop_price = array_pop($shop_price);
$shop_price = explode(':', $shop_price);
$price = $shop_price[]; //商品参数
$prame_check = pq("#summary1 .dd");
$prame = [];
foreach ($prame_check as $li) {
$prame[] = pq($li)->text();
} $sn = $prame[];//货号
$brank = $prame[];//品牌
$time = $prame[];//上架时间 // 商品图片
$prame_photo_check = pq("#goods_gallery a");
$photo = [];
foreach ($prame_photo_check as $li) {
$src = 'http://www.rsq111.com/'.pq($li)->attr('href');//图片路径
//注释代码为保存图片路劲,下载图片到本地
$localSrc = 'w/'.md5($src).'.jpg';
// $stream = file_get_contents($src);
// file_put_contents($localSrc,$stream);
// pq($li)->attr('src',$localSrc);
$photo[] = $localSrc;
} //商品详情图片
$info_photo_check = pq(".detail-content img");
$info_photo = [];
foreach ($info_photo_check as $li) {
$src = 'http://www.rsq111.com/'.pq($li)->attr('src');
$localSrc = 'w/'.md5($src).'.jpg';
// $stream = file_get_contents($src);
// file_put_contents($localSrc,$stream);
// pq($li)->attr('src',$localSrc);
$info_photo[] = $localSrc;
} $data= [
'title' => $title,
'category1' => $category[],
'category2' => $category[],
'category3' => $category[],
'price' => $price,
'sn' => $sn,
'brank' => $brank,
'time' => $time,
'photo' => $photo,
'info_photo' =>$info_photo,
];
}
echo "<pre>";
print_r($data);

//检测url是否合法
function getHeaders($url,$data=FALSE){
$_headers = get_headers($url,);
if( !$data ){return $_headers;}
$curl = curl_init();
curl_setopt($curl,CURLOPT_URL,$url);//获取内容url
curl_setopt($curl,CURLOPT_HEADER,);//获取http头信息
curl_setopt($curl,CURLOPT_NOBODY,);//不返回html的body信息
curl_setopt($curl,CURLOPT_RETURNTRANSFER,);//返回数据流,不直接输出
curl_setopt($curl,CURLOPT_TIMEOUT,); //超时时长,单位秒
curl_exec($curl);
$rtn= curl_getinfo($curl,CURLINFO_HTTP_CODE);
curl_close($curl);
return $rtn;
}

这样的话就可以采集到这页面的数据了,但是如果我们需要采集的数据页面比较多,比如上万条数据的话,我们用这种方式速度会很慢

多页面采集

如果我们直接循环去获取页面的,这样每个页面都需要访问一次,并且抓取数据,耗时耗性能,这是我们可以有多种方案来优化提升速度

a.使用curl模拟多线程,将网页一次性全部抓取回来,保存到本地进行采集,避免了重复请求,造成的开销

b.使用swoole,创建多个线程,来进行采集,比如当我们去采集10个页面的时候,耗时10秒,这时候我们创建多个线程,同事去请求分配出去的url,则可以提升我们的速度

c.当然,如果我们对数据要求性低,我们可以借助第三方软件,比如八爪鱼,火车,这些工具,可以更加快速的采集到需要的数据

笔者在这里采用的是第一种方法,因为是windows环境,swoole的话,windows安装有点麻烦

我采用的是ajax轮询,每次10条,比如我们从商品id为1的数据开始采集

phpcj.php

<?php

//获取开始采集的id
$start_id = $_POST['start_id'];
$end_id = $start_id+; //每次加10条 if(empty($start_id) || empty($end_id)){
exit(json_encode(['status'=>,'msg'=>'参数不正确']));
}
$pdo = new PDO('mysql:host=数据库地址;dbname=数据库名','用户','密码',array(PDO::ATTR_PERSISTENT)); header("Content-Type: text/html; charset=UTF-8");
require("phpQuery.php");

//将要采集的地址全部循环出来
for ($i=$start_id; $i < $end_id; $i++) {
$urls[$i] = 'http://www.rsq111.com/goods.php?id='.$i;
}
//判断当前url是否合法,这里我判断的是第一条
$code = getHeaders(array_shift($urls),true);
if($code != ){
  //如果不合法,返回结束id,重新开始执行
exit(json_encode(['status'=>,'msg'=>'当前id无商品','end_id'=>$end_id]));
}
$save_to='test.txt'; // 把抓取的代码写入该文件
$st = fopen($save_to,'w+'); $mh = curl_multi_init();
foreach ($urls as $i => $url) {
$conn[$i] = curl_init($url);
curl_setopt($conn[$i], CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)");
curl_setopt($conn[$i], CURLOPT_HEADER ,);
curl_setopt($conn[$i], CURLOPT_CONNECTTIMEOUT,);
curl_setopt($conn[$i],CURLOPT_RETURNTRANSFER,true); // 设置不将爬取代码写到浏览器,而是转化为字符串
curl_multi_add_handle ($mh,$conn[$i]);
} do {
curl_multi_exec($mh,$active);
} while ($active); foreach ($urls as $i => $url) {
file_put_contents($save_to, '');
$data = curl_multi_getcontent($conn[$i]); // 获得爬取的代码字符串
file_put_contents($save_to, $data); //将抓取到的野蛮写入到文件中
$data = cj($i);
if ($data) {
$add[$i] = $data;
}
}
foreach ($urls as $i => $url) {
curl_multi_remove_handle($mh,$conn[$i]);
curl_close($conn[$i]);
} curl_multi_close($mh);
fclose($st); //将采集成功的数据存入数据库
$sql = '';
if(!empty($add))
{
foreach ($add as $key => $value) {
$title = str_replace("'","",$value['title']);
$category1 = $value['category1'];
$category2 = $value['category2'];
$category3 = $value['category3'];
$price = $value['price'];
$sn = $value['sn'];
$brank = $value['brank'];
$time = $value['time'];
$photo = $value['photo'];
$info_photo = $value['info_photo'];
$cj_id = $end_id; $sql[] = "('$title','$category1','$category2','$category3','$price','$sn','$brank','$time','$photo','$info_photo','$cj_id')"; }
$sqls =implode(',', $sql);
$add_sql = "INSERT into phpcj (title,category1,category2,category3,price,sn,brank,time,photo,info_photo,cj_id) VALUES ".$sqls;
$res = $pdo->exec($add_sql);
if(!$res) {
    //采集未成功,返回id,重新开始采集
exit(json_encode(['status'=>,'msg'=>'本次采集未成功..','start_id'=>$start_id]));
}else{
    //采集成功,将最后一条数据返回,用作下此次执行的开始id
exit(json_encode(['status'=>,'msg'=>'采集成功,正在进行循环采集..','end_id'=>$end_id]));
}
} //采集方法
function cj($i)
{
$url = 'http://www.***.com/test.txt'; //页面存取的文本路劲
phpQuery::newDocumentFile($url);
// 分类
$arr_check = pq(".breadcrumb");
foreach ($arr_check as $li) {
$cat = pq($li)->text();
}
if(empty($cat)){
return;
}
$category = explode('>', $cat); //标题
$h1_check = pq("#name");
$title = pq($h1_check)->text(); //价格
$price_check = pq(".rmbPrice");
$shop_price = [];
foreach ($price_check as $li) {
$shop_price[] = pq($li)->text();
}
$shop_price = array_pop($shop_price);
$shop_price = explode(':', $shop_price);
$price = $shop_price[]; //参数
$prame_check = pq("#summary1 .dd");
$prame = [];
foreach ($prame_check as $li) {
$prame[] = pq($li)->text();
} $sn = $prame[];//货号
if(count($prame) > ){
$brank = $prame[];//品牌
$time = $prame[];//上架时间
}else{
$brank = '无';
$time = $prame[];//上架时间
} // 商品图片
$prame_photo_check = pq("#goods_gallery a");
$photo = [];
foreach ($prame_photo_check as $li) {
$src = 'http://www.rsq111.com/'.pq($li)->attr('href');
// $localSrc = 'w/'.md5($src).'.jpg';
// $stream = file_get_contents($src);
// file_put_contents($localSrc,$stream);
// pq($li)->attr('src',$localSrc);
// $photo[] = $localSrc;
$photo[] = $src;
}
$photo =json_encode($photo); //商品详情图片
$info_photo_check = pq(".detail-content img");
$info_photo = [];
foreach ($info_photo_check as $li) {
$src = 'http://www.rsq111.com/'.pq($li)->attr('src');
// $localSrc = 'w/'.md5($src).'.jpg';
// $stream = file_get_contents($src);
// file_put_contents($localSrc,$stream);
// pq($li)->attr('src',$localSrc);
// $info_photo[] = $localSrc;
$info_photo[] = $src;
}
$info_photo = json_encode($info_photo);
 //如果商品没有三级分类,给他赋值为空
if(count($category) < ){
$category[] = '';
}
$data = [
'title' => $title,
'category1' => $category[],
'category2' => $category[],
'category3' => $category[],
'price' => $price,
'sn' => $sn,
'brank' => $brank,
'time' => $time,
'photo' => $photo,
'info_photo' =>$info_photo,
'cj_id' => $end_id,
];
return $data; } //判断url是否合法
function getHeaders($url,$data=FALSE){
$_headers = get_headers($url,);
if( !$data ){return $_headers;}
$curl = curl_init();
curl_setopt($curl,CURLOPT_URL,$url);//获取内容url
curl_setopt($curl,CURLOPT_HEADER,);//获取http头信息
curl_setopt($curl,CURLOPT_NOBODY,);//不返回html的body信息
curl_setopt($curl,CURLOPT_RETURNTRANSFER,);//返回数据流,不直接输出
curl_setopt($curl,CURLOPT_TIMEOUT,); //超时时长,单位秒
curl_exec($curl);
$rtn= curl_getinfo($curl,CURLINFO_HTTP_CODE);
curl_close($curl);
return $rtn;
}

这样我们完成了对页面的循环采集

前台代码,使用ajax循环请求(如果,使用服务器定时任务的话,需要注意,对采集不成功的判断,这块我是手动重新填写id,因为采集的因素不可控,也许对方页面错误,对方的数据库出错,但是我们依旧可以正常访问到,所以需要对采集不成功,或者对某个id一直进行采集时,我们要加时效性判断。如果超过多长时间,默认为当前数据采集不成功,则开始下一轮的采集,可以是当前id+1,或者其他规则,总之跳过这个id就可以)

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<input type="text" name="start_id" id="start_id" placeholder="采集开始id">
<!-- <input type="text" name="end_id" id="end_id" placeholder="采集结束id"> -->
<input type="button" id="btn" value="开始采集">
<h5 id="zhi"></h5>
<input type="text" id="ids" placeholder="采集返回成功条数">
</body>
</html>
<script type="text/javascript" src="./jquery.min.js"></script>
<script>
$('#btn').click(function(){
var startid = $('#start_id').val();
cj(startid)
}) function cj(startid)
{
var ids = $('#ids').val();
if (ids) {
startid = ids;
} $('#zhi').html('采集中...');
var urls = "http://wlkx.oeob.net/phpcj.php"
$.ajax({
type: "post",
url: urls,
dataType:'json',
data: {"start_id":startid},
success : function(res){
console.log(res)
$('#zhi').html('');
if(res.status == ){
$('#zhi').html(res.msg);
$('#ids').val(res.start_id);
}else{
$('#zhi').html(res.msg);
$('#ids').val(res.end_id);
setTimeout(cj,*);
} } });
} </script>

使用phpQuery进行采集数据,模拟curl提升访问速度的更多相关文章

  1. js优化提升访问速度

    一.给JS文件减肥. 有的人为了给网站增加炫目效果,往往会使用一些JS效果代码,这在上个世纪似乎还很流行,对于现在来说,最好在用户体验确实需要的情况下,使用这些东西.至于希望给自己的JS文件减肥的童鞋 ...

  2. 使用Gzip压缩数据,加快页面访问速度

                 在返回的json数据量大时,启用Gzip压缩,可以提高传输效率.下面为Gzip压缩对json字符串压缩并输出到页面的代码. 一.代码 /** 向浏览器输出字符串响应数据,启用 ...

  3. [技巧篇]00.TrimFilter去掉jsp页面空白,提升访问速度

    最近感觉项目访问的速度有点慢,我就在网络中一顿搜索,发下了一个好东东,忍不住跟大家分享,希望大家可以试一试,确实有提升的空间啊!要求去除空白区.提取公用代码.减小页面. 胖先生乱搜之下,找到了Trim ...

  4. php中CURL实现模拟登录并采集数据

    在php中采集我们用的是简单的采集方式(例如file_get_contents)就无法做到了,但是如果想模拟登录用户并采集利用它就没办法了,我们可利用CURL函数来实现模拟登录并采集数据 这里要说一些 ...

  5. [PHP自动化-进阶]001.CURL模拟登录并采集数据

    引言:PHP可以通过libcurl实现模拟登录,提交数据,违法乱纪,烧杀抢虐等等事项. 简单说明一下"libcurl",补一下脑: libcurl目前支持http.https.ft ...

  6. php curl采集数据问题汇总

    1. 使用curl获取网页数据提示: "curl: (6) Could not resolve host: xxx.xxx.com ; Name or service not known&q ...

  7. php 模拟登陆(不带验证码)采集数据

    这里模拟表单登陆窗口 提交代码部分 1,生成session_id保存到 cookie $login_url = 'http://www.96net.com.cn/Login.php';$cookie_ ...

  8. OCM_第十三天课程:Section6 —》数据库性能调优 _结果缓存 /多列数据信息采集统计/采集数据信息保持游标有效

    注:本文为原著(其内容来自 腾科教育培训课堂).阅读本文注意事项如下: 1:所有文章的转载请标注本文出处. 2:本文非本人不得用于商业用途.违者将承当相应法律责任. 3:该系列文章目录列表: 一:&l ...

  9. asp.net 模拟CURL调用微信公共平台API 上传下载多媒体文

    近公司项目上在开发微信服务号的接口,需要给用户回复图片或语音或视频,这个时候就需要用到 上传下载多媒体文件接口,微信在这方面推荐采用的是开源函数库curl实现的,CURL项目包括很多版本,我主要测试的 ...

随机推荐

  1. Java实现 LeetCode 498 对角线遍历

    498. 对角线遍历 给定一个含有 M x N 个元素的矩阵(M 行,N 列),请以对角线遍历的顺序返回这个矩阵中的所有元素,对角线遍历如下图所示. 示例: 输入: [ [ 1, 2, 3 ], [ ...

  2. Java实现 LeetCode 27 移除元素

    27. 移除元素 给定一个数组 nums 和一个值 val,你需要原地移除所有数值等于 val 的元素,返回移除后数组的新长度. 不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额 ...

  3. Linux 文件特殊权限-Sticky BIT

    SBIT粘着位作用 只对目录有效 普通用户对该目录拥有w和x权限,即普通用户可以在此目录有写权限 如果没有粘着位,普通拥有写权限,就可以删除目录下所有文件,包括其他用户创建的文件,一旦有粘着位,只有r ...

  4. Maven发布Release到中心仓库历程记录(无个人域名)

    Maven发布Release到中心仓库历程记录(无个人域名) 前言 因为前段时间自己做了一个爬虫项目(地址),自己很希望分享到maven中心仓库上,感觉拥有自己的jar包令我兴奋,便开始了maven发 ...

  5. apollo与springboot集成实现动态刷新配置

    分布式apollo简介 Apollo(阿波罗)是携程框架部门研发的开源配置管理中心,能够集中化管理应用不同环境.不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限.流程治理等特性. 本 ...

  6. iOS-MapKit的使用笔记

    对于地图和定位,苹果公司提供给了两个框架: MapKit:用于地图展示 Core Location :用于地理定位 这次总结MapKit:       同样,在使用MapKit时首先要导入头文件: 与 ...

  7. jsp页面用DBHelper实现简单的登陆验证

    首先我们需要写一个简单的登陆页面login.jsp,然后用from表单提交给index.jsp页面.在index.jsp页面通过DBHelper连接数据库判断账号和密码,如果密码正确则显示登陆成功. ...

  8. 无监督LDA、PCA、k-means三种方法之间的的联系及推导

       \(LDA\)是一种比较常见的有监督分类方法,常用于降维和分类任务中:而\(PCA\)是一种无监督降维技术:\(k\)-means则是一种在聚类任务中应用非常广泛的数据预处理方法.    本文的 ...

  9. kafka能做什么?kafka集群配置 (卡夫卡 大数据)

    什么是Kafka 官网介绍: 几个概念: 详细介绍 : 操作kafka: kafka集群 消息测试 问题检测 什么是Kafka 官网介绍: ApacheKafka是一个分布式流媒体平台.这到底是什么意 ...

  10. CentOS7——初始化

    CentOS7--初始化 #禁止关闭显示器 archlinux wiki 提及的方法 echo -ne "\033[9;0]" >> /etc/issue # 重启,c ...