💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
# php爬虫技术4 --- ## 爬虫抓取方式 1. 接口 2. 网页 3. 心得 --- ### 1. 接口 * 很多网站是第三方平台,可以直接调用接口数据。 * 比如: * 腾讯开发平台:微信登录、微信支付。网址:open.tencent.com * 阿里巴巴开放平台:产品、物流、会员、搜索。网址:open.1688.com * 聚合数据:短信验证码、快递、天气、车辆违章。网址:www.juhe.cn * 我们做个聚合数据示例: * 手机号码归属地key:4d6cce531387deeedf359687fb04c163 * 全国天气预报key:abc4b64ae7656b460723402175a5650b > **示例:** ```php $url = "http://v.juhe.cn/weather/citys"; $params = array( "key" => "db741b7e6bcb5d461ce892c1f16040fd", ); $paramstring = http_build_query($params); $content = juheCurl($url, $paramstring); $result = json_decode($content, true); if ($result) { return_json(0,$result); } else { return_json(1,'接口出错'); } // json数据格式整理 function return_json($code,$data=array()){ if($code == 0){ $array = array( 'code' => 0, 'msg' => 'success', 'data' => $data ); }else{ $array = array( 'code' => $code, 'msg' => $data ); } echo json_encode($array); exit; } // 通过curl请求接口 function juheCurl($url, $params = false, $ispost = 0){ $httpInfo = array(); $ch = curl_init(); curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); // 默认值,让 cURL 自己判断使用哪个版本。 (强制使用 HTTP/1.1)。 curl_setopt($ch, CURLOPT_USERAGENT, 'JuheData'); // 在HTTP请求中包含一个"User-Agent: "头的字符串。 curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 60); // 在尝试连接时等待的秒数。设置为0,则无限等待。 curl_setopt($ch, CURLOPT_TIMEOUT, 60); // 设置超时限制防止死循环 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 要求结果保存到字符串中还是输出到屏幕上 curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); // 爬取重定向页面 if ($ispost) { curl_setopt($ch, CURLOPT_POST, true); // 发送一个常规的Post请求 curl_setopt($ch, CURLOPT_POSTFIELDS, $params); // Post提交的数据包 curl_setopt($ch, CURLOPT_URL, $url); // 设置URL } else { // GET请求,组装url if ($params) { curl_setopt($ch, CURLOPT_URL, $url.'?'.$params); } else { curl_setopt($ch, CURLOPT_URL, $url); } } $response = curl_exec($ch); // 运行cURL,请求URL,把结果复制给变量 if ($response === FALSE) { echo "cURL Error: " . curl_error($ch); //捕抓异常 return false; } $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); // 获取一个cURL连接资源句柄的信息 $httpInfo = array_merge($httpInfo, curl_getinfo($ch)); curl_close($ch); return $response; } ``` --- ### 2. 网页 * 网页抓取,我们拿新闻做案例:news.cyol.com * 新闻网站,我们一般不抓取热门,只会抓取分类和新闻列表,新闻内容 * 很多网站也是这样,比如淘宝网站,我们不可能抓取首页上的商品 * 没有规则的,抓取后,无法批量处理。而且推荐的商品,在列表里也会有这条商品的。 > 第一步:找寻新闻分类接口、或新闻分类规则 * zqbapp.cyol.com/zqzxapi/api.php?s=/Web/getTypeListCache > 第二步:根据数据,创建数据库 > news_source_cat:来源分类表 ```php CREATE TABLE `news_source_cat` ( `cat_id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '分类ID', `source_id` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '来源ID', `source_fid` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '来源父ID', `source_name` varchar(50) NOT NULL COMMENT '来源分类名', `source_status` tinyint(1) unsigned NOT NULL DEFAULT '1' COMMENT '来源状态 1开启 0禁用', `num` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '抓取次数', PRIMARY KEY (`cat_id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='来源分类表'; ``` > 第三步:抓取数据,存储到数据库 ```php require 'function.php'; $url = "https://zqbapp.cyol.com/zqzxapi/api.php?s=/Web/getTypeListCache"; // 获取到数据 $a = juheCurl($url); // 去除数据的开头括号 和 结束括号 $a = substr($a,1); $a = substr($a,0,strlen($a)-1); // json解析获取的数据 $b = json_decode($a,true); // 循环处理数据 foreach ($b['data'] as $v) { if($v['tid'] <= 0){ continue; }else{ setCatData($v); } } return true; function setCatData($a){ $data = array( 'source_id' => $a['tid'], 'source_fid'=> $a['pid'], 'source_name' => $a['cnname'] ); $ret = insert('news_source_cat',$data); if(empty($ret)){ return false; } if(!empty($a['childs'])){ foreach($a['childs'] as $v){ setCatData($v); } } } ``` > 第四步:找寻新闻列表接口、或新闻列表规则 * zqbapp.cyol.com/zqzxapi/api.php?s=/Web/getNewsListCache/tid/767/page/1 > 第五步:根据数据,创建数据库 > news_list:来源新闻表 ```php CREATE TABLE `news_list` ( `news_id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '新闻ID', `cat_id` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '本地分类ID', `source_id` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '来源ID', `source_nid` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '来源新闻ID', `title` varchar(500) NOT NULL COMMENT '标题', `title_md5` char(32) NOT NULL COMMENT '加密后的标题', `f_title` varchar(500) NOT NULL COMMENT '父标题', `type` tinyint(3) unsigned NOT NULL DEFAULT '1' COMMENT '类型 1文字新闻 2图文新闻 3联图新闻 4三连图 5普通新闻大图 6 视频 7 H5 8广告 9直播', `img` varchar(500) NOT NULL COMMENT '图片', `url` varchar(500) NOT NULL COMMENT '详情网址', `content` text NOT NULL COMMENT '新闻详情', PRIMARY KEY (`news_id`) ) ENGINE=MyISAM AUTO_INCREMENT=160 DEFAULT CHARSET=utf8 COMMENT='新闻列表'; ``` > 第六步:抓取数据,存储到数据库 ```php require 'function.php'; // 查询分类表,单条数据 $cat = find('news_source_cat','*','source_status=1','num'); for($i=1;$i<=5;$i++){ if($cat['source_fid'] == 676){ $url = 'https://zqbapp.cyol.com/zqzxapi/api.php?s=/Web/getNewsListCache/tid/'.$cat['source_id'].'/page/'.$i; }else{ $url = 'https://zqbapp.cyol.com/zqzxapi/api.php?s=/Web/typeHomePage/tid/'.$cat['source_id'].'/Page/'.$i; } // 获取到数据 $a = curl_data($url); // 去除数据的开头括号 和 结束括号 $a = substr($a,1); $a = substr($a,0,strlen($a)-1); // json解析获取的数据 $b = json_decode($a,true); // 循环处理数据 if($b['code'] == '200'){ if($cat['source_fid'] == 676){ foreach ($b['data'] as $v){ $ret = setListData($v); echo $ret; } }else{ foreach ($b['data']['typenews'] as $v){ $ret = setListData($v); echo $ret; } } } } function setListData($a){ // 赋值标题给新变量 $title = trim($a['title']); // 查询新闻是否已存在,存在进入下一条新闻抓取 $news = find('news_list','*','title_md5="'.md5($title).'"'); if($news){ return $a['nid'].'已存在,采集失败!<br/>'; } // 通过来源ID,查询本项目分类ID $cat = find('news_source_cat','*','source_id='.$a['tid']); // 接口的方式,无法得到新闻详情 /* * $url = 'https://zqbapp.cyol.com/zqzxapi/api.php?s=/News/newsinfo'; * $curl = curl_data($url,array('device'=>12,'nid'=>$a['nid']),1); */ // 抓取新闻详情url数据 $curl = curl_data($a['newsurl']); // 正则表达式 $pattem = '/<div class="news-content dd" id="news-content">(.*?) <\/div>/si'; // 截取需要的文章详情 $preg = preg_match($pattem,$curl,$matches); $content = $matches[1].'</div>'; // 把来源网站的图片标识,替换为HTML标识 $content = preg_replace('/data-original/','src',$content); $data = array( 'cat_id' => $cat['cat_id'], 'source_id' => $a['tid'], 'source_nid'=> $a['nid'], 'title' => $title, 'title_md5' => md5($title), 'f_title' => $a['outline'], 'type' => $a['type'], 'img' => $a['imgs'][0], 'url' => $a['newsurl'], 'content' => htmlspecialchars($content), ); $ret = insert('news_list',$data); if(empty($ret)){ return $a['nid'].'采集失败!<br/>'; } return $a['nid'].'采集成功!<br/>'; } ``` --- ### 3. 抓取心得 * 尽可能找到要来源的接口。 * 如果来源有app,尽可能先从app进行获取接口。 * 如果来源没有app,可以找找来源有没有手机网页版。 * 手机网页版,也是用ajax请求列表,列表也属于接口返回。 * 只能抓取pc网页版,尽可能把正则写简单些。 * 比如抓取新闻:1,匹配标题。2,匹配新闻时间。3,匹配详情。 * 如果新闻详情,内容有不对称的,可以在后台做处理功能。 * 新闻列表,都是可以翻页的。需要记得抓取页数。每次不要超过100条抓取。 * 如果有重复的新闻。可以在抓取时,对新闻标题,进行md5加密 * 加密后,匹配数据库里的加密标题。不要用标题进行匹配,因为字符串匹配不够准确。