使用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实现 蓝桥杯VIP 算法训练 快速排序

    import java.util.Scanner; public class 快速排序 { public static void main(String[] args){ Scanner sc=new ...

  2. Java实现 LeetCode 290 单词规律

    290. 单词规律 给定一种规律 pattern 和一个字符串 str ,判断 str 是否遵循相同的规律. 这里的 遵循 指完全匹配,例如, pattern 里的每个字母和字符串 str 中的每个非 ...

  3. Java实现蓝桥杯VIP算法训练 奇变的字符串

    试题 算法训练 奇变的字符串 资源限制 时间限制:1.0s 内存限制:256.0MB 问题描述 将一个字符串的奇数位(首位为第0位)取出,将其顺序弄反,再放回原字符串的原位置上. 如字符串" ...

  4. Java实现 洛谷 P1422 小玉家的电费

    import java.util.*; public class Main { public static void main(String[] args) { Scanner in = new Sc ...

  5. logrotate 如何执行日志按照大小切分

    说在最先的话,logrotate要设置按照文件大小来配置日志切分,需要通过三个东西. 1.配置logrotate 的配置文件 命名未任意文件,在启动的时候指定,例如/etc/weblog.conf 参 ...

  6. Python:三元表达式、列表推导式和生成器表达式

    三元表达式 语法格式 如下: 为真时的结果 if 判断条件 else 为假时的结果 例子 name = input('姓名>>: ') res = '请进' if name == '张三' ...

  7. 《ElasticSearch入门》一篇管够,持续更新

    一.顾名思义: Elastic:灵活的:Search:搜索引擎 二.官方简介: Elasticsearch是一个基于Lucene的搜索服务器.它提供了一个分布式多用户能力的全文搜索引擎,基于RESTf ...

  8. Linux 进程间通信(IPC)总结

    概述 一个大型的应用系统,往往需要众多进程协作,进程(Linux进程概念见附1)间通信的重要性显而易见.本系列文章阐述了 Linux 环境下的几种主要进程间通信手段. 进程隔离 进程隔离是为保护操作系 ...

  9. Asp.Net 五大对象及作用

    Connection(连接对象):与数据源建立连接. DataAdapter(适配器对象):对数据源执行操作并返回结果,在DataSet与数据源之间建立通信,将数据源中的数据写入DataSet中,或根 ...

  10. SpringMVC拦截器使用

    源码地址 拦截器interceptor 拦截器是URL请求的第一道门,所有请求会先经过拦截器interceptor,然后再进入controller: 下面,记录一种通过注解方法拦截所有需要登录才能发起 ...