JF0 2019-11-29
这里是我自己写的一个小需求
<?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,再一个个去爬取详情页的内容
注意事项:
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); }
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');