php爬虫技术5


爬虫抓取方式

1. 接口
2. 网页
3. 心得

1. 接口

示例:

    $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_source_cat:来源分类表

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='来源分类表';

第三步:抓取数据,存储到数据库

    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);
            }
        }
    }

第四步:找寻新闻列表接口、或新闻列表规则

第五步:根据数据,创建数据库
news_list:来源新闻表

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='新闻列表';

第六步:抓取数据,存储到数据库

    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. 抓取心得