使用php采集网页数据一般有多种方法,有时候东西以采集

优采云 发布时间: 2021-08-15 23:12

  使用php采集网页数据一般有多种方法,有时候东西以采集

  php采集网页数据的使用方式一般有很多种。有时我们使用正则去采集页面,但是当我们需要采集有一个很大很大的页面时,就会严重浪费我们的CPU。到时候我们可以用phpQuer来做采集。如果你不了解 phpQuery,你可以去看看这是什么。

  以采集此网站为例

  假设我们需要采集commodity category Name Price Item No Shelf Time Product Picture Detail Picture

  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 != 200) {

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[1];

//商品参数

$prame_check = pq("#summary1 .dd");

$prame = [];

foreach ($prame_check as $li) {

$prame[] = pq($li)->text();

}

$sn = $prame[0];//货号

$brank = $prame[1];//品牌

$time = $prame[2];//上架时间

// 商品图片

$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[1],

'category2' => $category[2],

'category3' => $category[3],

'price' => $price,

'sn' => $sn,

'brank' => $brank,

'time' => $time,

'photo' => $photo,

'info_photo' =>$info_photo,

];

}

echo "";

print_r($data);

//检测url是否合法

function getHeaders($url,$data=FALSE){

$_headers = get_headers($url,1);

if( !$data ){return $_headers;}

$curl = curl_init();

curl_setopt($curl,CURLOPT_URL,$url);//获取内容url

curl_setopt($curl,CURLOPT_HEADER,1);//获取http头信息

curl_setopt($curl,CURLOPT_NOBODY,1);//不返回html的body信息

curl_setopt($curl,CURLOPT_RETURNTRANSFER,1);//返回数据流,不直接输出

curl_setopt($curl,CURLOPT_TIMEOUT,30); //超时时长,单位秒

curl_exec($curl);

$rtn= curl_getinfo($curl,CURLINFO_HTTP_CODE);

curl_close($curl);

return $rtn;

}

  这种情况下,可以采集到这个页面的数据,但是如果我们需要更多的采集数据页面,比如几万条数据,这种方式会很慢

  多页采集

  如果我们直接循环获取页面,这样每个页面都需要访问一次,并且爬取数据,费时费力,这就是我们可以有多种方案来优化速度。

  一个。使用curl模拟多线程,一次性抓取所有网页,保存在本地给采集,避免重复请求带来的开销

  B.使用 swoole 创建多个线程来执行采集。比如我们去采集10个页面,需要10秒。这时候我们创建了多个线程,同事请求分发。网址,你可以提高我们的速度

  c.当然,如果我们对数据要求不高,可以使用第三方软件,比如优采云、优采云,这些工具可以采集更快的拿到需要的数据

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

  我使用 ajax 轮询,一次 10 个。比如我们从产品id为1采集

  的数据开始

  phpcj.php

  php

//获取开始采集的id

$start_id = $_POST['start_id'];

$end_id = $start_id+10; //每次加10条

if(empty($start_id) || empty($end_id)){

exit(json_encode(['status'=>0,'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 != 200){

  //如果不合法,返回结束id,重新开始执行

exit(json_encode(['status'=>1,'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 ,0);

curl_setopt($conn[$i], CURLOPT_CONNECTTIMEOUT,60);

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'=>0,'msg'=>'本次采集未成功..','start_id'=>$start_id]));

}else{

    //采集成功,将最后一条数据返回,用作下此次执行的开始id

exit(json_encode(['status'=>1,'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[1];

//参数

$prame_check = pq("#summary1 .dd");

$prame = [];

foreach ($prame_check as $li) {

$prame[] = pq($li)->text();

}

$sn = $prame[0];//货号

if(count($prame) > 2){

$brank = $prame[1];//品牌

$time = $prame[2];//上架时间

}else{

$brank = '无';

$time = $prame[1];//上架时间

}

// 商品图片

$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) < 3){

$category[3] = '';

}

$data = [

'title' => $title,

'category1' => $category[1],

'category2' => $category[2],

'category3' => $category[3],

'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,1);

if( !$data ){return $_headers;}

$curl = curl_init();

curl_setopt($curl,CURLOPT_URL,$url);//获取内容url

curl_setopt($curl,CURLOPT_HEADER,1);//获取http头信息

curl_setopt($curl,CURLOPT_NOBODY,1);//不返回html的body信息

curl_setopt($curl,CURLOPT_RETURNTRANSFER,1);//返回数据流,不直接输出

curl_setopt($curl,CURLOPT_TIMEOUT,30); //超时时长,单位秒

curl_exec($curl);

$rtn= curl_getinfo($curl,CURLINFO_HTTP_CODE);

curl_close($curl);

return $rtn;

}

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

  前台代码,使用ajax循环请求(如果使用服务器定时任务,需要注意,对于采集不成功的判断,本节我手动重新填id,因为采集因素不可控,可能是对方页面错了,对方数据库错了,但是我们还是可以正常访问的,所以需要把采集失败或者把采集保留在某个id上,需要加上时效判断。超过多久,默认是当前数据采集不成功,那么下一轮采集就会开始,可以是当前id+1,或者其他规则,反正跳过这个id)

  "en">

"UTF-8">

Document

"text" name="start_id" id="start_id" placeholder="采集开始id">

"button" id="btn" value="开始采集">

"zhi">

"text" id="ids" placeholder="采集返回成功条数">

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线