用php写爬虫去爬数据

Posted 段佳伟的小憩屋

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用php写爬虫去爬数据相关的知识,希望对你有一定的参考价值。

参考文档1
参考文档2
这里是我自己写的一个小需求

<?php
/**
采集http://www.959.cn/school,即时更新的最新的文章内容;每分钟采集一次。采集结束后实时入库并展示。
*/
header("Content-Type: text/html;charset=utf-8");
date_default_timezone_set(\'PRC\');
$con = mysqli_connect(\'127.0.0.1\', \'xxxxx\', \'xxxxx\', \'xxxxx\');
mysqli_set_charset($con,\'UTF8\');

// 日志位置
//把当前的最新一条文章的id.shtml的id 存入一个max.log的文件中,实时读取 实时更改
$log_path = \'/home/logs\';
if(!file_exists($log_path)){
        mkdir($log_path,0755,true);
}
$max_log = $log_path.\'/kecheng_max.log\';
$path = \'./img/\';
$max = file_get_contents($max_log) ? file_get_contents($max_log) : 4613925; //当前的最新一条文章的id.shtml的id

//记录日志
$message_log = $log_path.\'/kecheng_message.log\';

$now_max = 0; //当前网站实际的最新一条的文章的id.shtml的id
$url = "http://www.959.cn/school/kecheng/";//要爬取的网址
$res = file_get_contents("compress.zlib://".$url);//curl封装方法
//var_dump($con);die;
preg_match_all(\'/<h3>.*<\\/h3>/\',$res,$arr_all);//文章列表内容
//var_dump($arr_all[0]);
foreach($arr_all[0] as $k => $v){
	// 先去匹配a标签 如果不是a标签直接继续下一个
	preg_match_all(\'/<a href="(.*)">.*<\\/a>/\',$v,$v_all);
	if (empty($v_all[1])){// 不是a标签
		continue;
	}
	
	$title =  strip_tags($v_all[0][0]); //文章标题
	$href = $v_all[1][0];//url
	
	// 截取当前url的shtml前面的id
	$href_one = substr($href, strrpos($href, \'/\')+1);
	$href_id = substr($href_one, 0, strpos($href_one, \'.\'));
	
	if ($k === 0) {
        $now_max = $href_id;
    }

	if ($href_id <=  $max){ // 只爬大于保存的最大id的数据
		$max = file_put_contents($max_log, $now_max, LOCK_EX); // 爬完之后让maxid更新为最新的
		break;
	}
	
	// 获取标题缩略图
	preg_match_all(\'/<img src="(.*)" alt="\'.$title.\'" \\/>/\',$res,$title_img);
	$title_img_url = $title_img[1][0];
	if(!file_exists($path)){
		mkdir($path,0755,true);
	}
	$title_img = file_get_contents ("http:{$title_img_url}");
	$cover_img_name = microtime_float().\'.jpg\';
	file_put_contents($path.$cover_img_name, $title_img);
	$cover_img = \'/public/uploads/img/\'.date(\'Y/md\',time()).\'/\'.$cover_img_name; // 标题缩略图位置
	
	// 获取文章内容
	$article_res = file_get_contents("compress.zlib://".$href);
	//var_dump($article_res);die;
	$article_res = trimall($article_res);
	//var_dump($article_res);die;
	preg_match_all(\'/<div class="detail">(.*?)<\\/div>/\',$article_res,$article_all);//文章详情内容
	
	$text = $article_all[1][0]; // 文章内容
	//var_dump($text);die;
	
	//筛选图片 并下载到本地
	preg_match_all(\'/<img .*? src="(.*?)" .*? \\/>/\',$article_all[1][0],$img_all); //文章详情图片
	//preg_match_all(\'/<imgalt="创业项目"src="(.*?)"title="创业项目" \\/>/\',$article_all[0][0],$img_all); //文章详情图片
	//var_dump($img_all[1]);
	foreach($img_all[1] as $key => $value){
		$message_img = file_get_contents ("http:{$value}");
		$message_img_name = microtime_float().\'.jpg\';
		file_put_contents($path.$message_img_name, $message_img);
		
		$text = str_replace($value,\'/public/uploads/img/\'.date(\'Y/md\',time()).\'/\'.$message_img_name,$text);
	}
	// 去掉【如果还有什么问题点击留言咨询】 和  >>>>想了解更多创业资讯,点击咨询详情 和 其他的a标签
	$text = preg_replace("/<a[^>]*>(.*?)<\\/a>/is", "", $text);
	//var_dump($text);die;
	
	// 入库数据
	$cid = 2;// 1:行业资讯,2:创业故事
	$source = \'88加盟网\';
	$create_time = time();
	$update_time = time();
	
	// 入库前转码
	$title = mb_convert_encoding($title,\'UTF-8\');
	$text = mb_convert_encoding($text,\'UTF-8\');
	//var_dump($title, $text);
	
	// 插入数据库
	$sql = "insert into zs_message (cid, title, create_time, update_time, source, cover_img, text) values ($cid, \'$title\', $create_time, $update_time, \'$source\', \'$cover_img\', \'$text\')";
    $result = mysqli_query($con,$sql);
	
	if ($result) {
		$msg = "当前抓取的页面url为:{$href},入库sql为:{$sql},结果:入库成功";
	} else {
		$msg = "当前抓取的页面url为:{$href},入库sql为:{$sql},结果:入库失败";
	}
	file_put_contents($message_log, $msg, FILE_APPEND | LOCK_EX);
	file_put_contents($message_log, "\\n\\r", FILE_APPEND | LOCK_EX);
	
}

function microtime_float()
{
    list($usec, $sec) = explode(" ", microtime());
    return $sec.substr($usec,2,6);
}


function trimall($str){
    $qian=array("\\n","\\r");
    return str_replace($qian, \'\', $str);  
}

function curl_get_contents($url,$cookie=\'\',$referer=\'\',$timeout=300,$ishead=0) {
  $curl = curl_init();
  curl_setopt($curl, CURLOPT_RETURNTRANSFER,1);
  curl_setopt($curl, CURLOPT_FOLLOWLOCATION,1);
  curl_setopt($curl, CURLOPT_URL,$url);
  curl_setopt($curl, CURLOPT_TIMEOUT,$timeout);
  curl_setopt($curl, CURLOPT_USERAGENT,\'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36\');
  if($cookie)
  {
    curl_setopt( $curl, CURLOPT_COOKIE,$cookie);
  }
  if($referer)
  {
    curl_setopt ($curl,CURLOPT_REFERER,$referer);
  }
  $ssl = substr($url, 0, 8) == "https://" ? TRUE : FALSE;
  if ($ssl)
  {
    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
  }
  $res = curl_exec($curl);
  return $res;
  curl_close($curl);
}

爬虫主要的思路是:用正则去筛选我们爬取我们的页面,然后从列表页获取到的url,再一个个去爬取详情页的内容
注意事项:

  1. 如果用file_get_contens去获取内容的话,gzip压缩,会出现乱码的情况
file_get_contents("compress.zlib://".$url);

如是用的curl的话

function curl_get($url, $gzip=false){
        $curl = curl_init($url);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 10);
        if($gzip) curl_setopt($curl, CURLOPT_ENCODING, "gzip"); // 关键在这里
        $content = curl_exec($curl);
        curl_close($curl);
        return $content;
}

无论页面是否经过gzip压缩,上述代码都可以正常工作!
参考出处
2.在获取到页面后,在匹配之前,一定要先把字符串中的\\r\\n空格换行都去掉,在进行匹配,否则会出现匹配为空的情况

function trimall($str){
    $qian=array("\\n","\\r");
    return str_replace($qian, \'\', $str);  
}
 // 处理页面源码,多行变单行
   $htmlOneLine = preg_replace("/\\r|\\n|\\t/","",$html);

3.去掉文章中的超链接或者将锚文本,只保留文字,去掉链接,去掉加粗格式

$text = preg_replace("/<a[^>]*>(.*?)<\\/a>/is", "", $text);//去掉文章中的超链接
$str = preg_replace("/<a[^>]*>(.*?)<\\/a>/is", "$1", $str);//只保留文字

4.生成图片的路径和文件名(参考)

$cover_img_name = microtime_float().\'.jpg\';
$cover_img = \'/public/uploads/img/\'.date(\'Y/md\',time()).\'/\'.$cover_img_name;
function microtime_float()
{
    list($usec, $sec) = explode(" ", microtime());
    return $sec.substr($usec,2,6);
}

5.入库的时候,有可能会出现,存入的数据读出来全是???,或者乱码 要把页面设置为utf8,数据库设置为utf8

header("Content-Type: text/html;charset=utf-8");
date_default_timezone_set(\'PRC\');
$con = mysqli_connect(\'127.0.0.1\', \'xx\', \'xx\', \'xx\');
mysqli_set_charset($con,\'UTF8\');

// 入库前转码
$title = mb_convert_encoding($title,\'UTF-8\');
$text = mb_convert_encoding($text,\'UTF-8\');

以上是关于用php写爬虫去爬数据的主要内容,如果未能解决你的问题,请参考以下文章

别人的Python爬虫代码能读懂,自己却还是不能自由去爬?社群日报

爬虫使用urllib.request去爬取小说

学习爬虫的day03 (通过代理去爬去数据)

爬虫要违法了吗?小编告诉大家:守住规则,大胆去爬

抓取新闻网站:异步爬虫实现的流程和细节

程序人生 - Python爬虫要违法了吗?告诉大家:守住规则,大胆去爬