为什么要做数据采集??

我是一个做网站开发的程序员,做一个网站想要我的网站好看,网站内容 充 实,让网站更加漂亮。如果是我们
自己去录入数据,我们可能要去找 很多资料,还需要美工做很多的图片,这样的成本就会很高。
而且现在京东和淘宝商品数据非常的丰富,我们可以直接写一套数据采集器,直接把数据采集到本网站来使用。

下面直接上代码说明如何做采集

采集时要的参数

1.采集的地址。

这里是采集的jd的列表页,最好是列表页的最后一级分类如:http://list.jd.com/list.html?cat=12218,12222,12243
2.采集的数量。
采集的数量要小于翻页的数量,不然多了没有。

采集方法
/**
 * 京东数据的采集
 */
public function jd(){
    //采集的数量
    number=10;
    //采集的地址url='http://list.jd.com/list.html?cat=12218,12222,12243';
    //实例化采集的类
    jd= new jd_collect(number);
    //检查url是否有效
    is_url=jd->checkListUrl(url);
    if(is_url){
        //给类赋值采集的地址
        jd->readListPage(url);
        //获取列表页商品的详情页url
        list=jd->pickGoodsLinkFromList();
        //采集到的数据数组
        data=jd->collect();
        //分类的父级赋值
        parent_id=0;
        //分类id赋值cate_id=[0,0];
        //判断分类是否存在,添加
        foreach (data['cat'] ask=>v){cate_id[k]=GoodsCategory::getName(['name'=>v]);
            if(!cate_id[k]){
                parent_id=GoodsCategory::add([
                    'name'=>v,
                ]);
                cate_id[k]=&parent_id;
            }
        }
        //对商品进行添加
        foreach(data['item'] as v){id = Goods::add([
                'name'=>v['name'],
                'memo'=>v['name'],
                'sell_price'=>v['sell_price'],
                'cost_price'=>v['cost_price'],
                'market_price'=>v['market_price'],
                'sort'=>50,
                'img'=>v['img'][0],
                'list_img'=>v['img'][0],
                'small_img'=>v['img'][0],
                'store_num'=>100,
                'cate_id'=>cate_id[0],
                'cate_two_id'=>cate_id[1],
                'start_time'=>time(),
                'end_time'=>time()+100*24*60*60,
            ]);
           //对商品的图片进行添加
           foreach (v['img'] asimg){
               GoodsImg::add([
                   'goods_id'=>id,
                   'image'=>img,
                   'list_img'=>img,
                   'small_img'=>img,
               ]);
           }
        }
    }
}
京东数据采集的操作类
number=number;
        }
    }

    /**
     * @brief 检查列表url
     */
    public function checkListUrl(url)
    {
        return strpos(url,'http://list.jd.com/list.html?cat=') === false ? false : true;
    }

    /**
     * @brief 检查详情url
     */
    public function checkShowUrl(url)
    {
        return strpos(url,'http://item.jd.com') === false ? false : true;
    }

    /**
     * @brief 挑选分类
     * @return array 根据层次返回分类
     */
    public function pickCatFromList()
    {catExp = '@
(.+?)
@'; preg_match_all(catExp,this->listPageHtml,match); if(!isset(match[0])) { throw new Exception('页面缺少商品分类'); } foreach (match[1] asv){ data[]=strip_tags(v); } return data; } /** * @brief 挑选属性 * @return array 属性数据 */ public function pickAttributeFromList() {keyExp = '@
(.+?)
@'; $valueExp = '@
    (.+?)
@'; preg_match_all(keyExp,this->listPageHtml,matchKey); preg_match_all(valueExp,this->listPageHtml,matchValue); if(!isset(matchKey[1])) { throw new Exception('页面缺少商品属性名称'); } if(!isset(matchValue[1])) { throw new Exception('页面缺少商品属性数值'); } //过滤无用的数据 array_shift(matchKey[1]);//移除品牌 array_shift(matchKey[1]);//移除价格 array_shift(matchValue[1]);//移除价格attrData = array(); foreach(matchKey[1] askey => val) {attrData[trim(val,':')] = trim(strip_tags(strtr(matchValue[1][key],array('' => ','))),','); } returnattrData; } /** * @brief 挑选列表页面的商品连接 * @return array 商品详情的url */ public function pickGoodsLinkFromList() { linkExp =''; preg_match_all(linkExp,this->listPageHtml,match); if(!isset(match[1])) { throw new Exception('页面缺少商品详情连接'); } returnmatch[1]; } /** * @brief 获取商品名称从详情页面 * @return string 商品名字 */ public function pickGoodsNameFromShow() { $exp = '/

([^]*)/'; preg_match(exp,this->showPageHtml,match); if(!isset(match[0])) { throw new Exception('没有找到商品名称'); } return strip_tags(match[0]); } /** * @brief 获取商品名称从详情页面 * @return string 商品描述 */ public function pickGoodsMemoFromShow() {exp = "/
.*?/ism"; preg_match(exp,this->showPageHtml,match); if(!isset(match[0])) { throw new Exception('没有找到商品名称'); } return strip_tags(match[0]); } /** * @brief 获取商品价格从API * @paramidArray string 商品id数组,如:J_970602 * @return string 商品价格json */ public function getGoodsPriceFromAPI(idString) { //apiUrl = 'http://p.3.cn/prices/mgets?skuIds='.trim(idString,',');apiUrl='http://p.3.cn/prices/get?type=1&area=1_72_4137&pdtk=HxOK%2F%2B%2Fwpjlr75zX3szVoe%2BWRMfuWsRCxWZRS2x7B84nzLc1bJwTzqlQm2fSRjIk&pduid=844111226&pdpin=&pdbp=0&skuid='.trim(idString,',');result = file_get_contents(apiUrl);result = strtr(result,array('J_' => '')); return json_decode(result,true); } /** * @brief 获取商品属性从详情页面 * @return string 商品某属性 */ public function pickGoodsAttributeFromShow() { $exp = '@
    (.+?)
@s'; preg_match(exp,this->showPageHtml,match); returnthis->cacheAttrData=[]; if(!isset(match[1])) { throw new Exception('没有找到商品属性'); }match[1] = trim(strip_tags(strtr($match[1],array('
  • ' => '
  • ,')))); tempArray = explode(',',match[1]); attrArray = array();tmp = array(); foreach(tempArray askey => val) {tmp = explode(':',val);attrArray[tmp[0]] = trim(tmp[1]); } return this->cacheAttrData =attrArray; } /** * @brief 获取商品图片从详情页面 * @return array 商品的图片url */ public function pickGoodsImageFromShow() { $exp=''; preg_match_all(exp,this->showPageHtml,match); if(!isset(match[1]) || !is_array(match[1])) { throw new Exception('没有找到商品图片'); }jdImageServerPre = 'http://img13.360buyimg.com/n0/'; foreach(match[1] askey => val) {match[1][key] =jdImageServerPre.val; } returnmatch[1]; } /** * @brief 获取商品规格从详情页面 * @return array 商品的规格 array(规格名称=>规格值) */ public function pickGoodsSpecFromShow() { $exp = '@
  • .*?
  • @s'; preg_match_all(exp,this->showPageHtml,match);result = array(); if(isset(match[0]) &&match[0]) { foreach(match[0] askey => val) {val = trim(strip_tags(strtr(val,array('' => ','))),',');temp = explode(':',val); if(isset(temp[1])) { result[temp[0]] = temp[1]; } } } returnresult; } /** * @brief 获取商品详情从详情页面 * @return string 商品的详情数据 */ public function pickGoodsContentFromShow() { $exp = '@
    .*@s'; preg_match(exp,this->showPageHtml,match); if(!isset(match[0])) { throw new Exception('没有找到商品详情'); } return strtr(match[0],array('data-lazyload' => 'src')); } /** * @brief 获取商品重量 * @return string 商品重量 */ public function pickGoodsWeightFromShow() { if(!this->cacheAttrData) { this->pickGoodsAttributeFromShow(); } preg_match('@[d.]+@',this->cacheAttrData['商品毛重'],matchAttr); return isset(matchAttr[0]) ? matchAttr[0] : 0; } /** * @brief 获取商品计量单位 * @return string 计量单位 */ public function pickGoodsUnitFromShow() { if(!this->cacheAttrData) { this->pickGoodsAttributeFromShow(); } preg_match('@[d.]+(.*)@',this->cacheAttrData['商品毛重'],matchAttr); return isset(matchAttr[1]) ?matchAttr[1] : '千克'; } /** * @brief 开始采集商品 * @return array('cat' => '商品分类','attr' => '属性','item' => array( * 'goods_no' => '商品编号','up_time' => '上架时间','weight' => '重量','unit' => '计量单位','name' => '商品名字','price' => '商品价格','img' => array(商品图片),'content' => '商品详情','spec' => '商品规格','attr' => '商品属性' * )) */ public function collect() { result = array( 'cat' =>this->pickCatFromList(), // 'attr'=> this->pickAttributeFromList(), 'item'=> array() );goodsUrl = this->pickGoodsLinkFromList(); //取列表页商品的数量goodsUrl=array_slice(goodsUrl,0,this->number); foreach(goodsUrl askey => val) {showurl='http://item.jd.com/'.val.'.html';this->readShowPage(showurl); preg_match('@d+@',val,match);priceObj = this->getGoodsPriceFromAPI('J_'.match[0]); // attrData =this->pickGoodsAttributeFromShow(); result['item'][] = array( // 'goods_no' =>attrData['商品编号'], // 'up_time' => attrData['上架时间'], // 'weight' =>this->pickGoodsWeightFromShow(), // 'unit' => this->pickGoodsUnitFromShow(), 'name' =>this->pickGoodsNameFromShow(), 'sell_price' => priceObj[0]['p'], 'market_price' =>priceObj[0]['m'], 'cost_price' => priceObj[0]['op'], 'img' =>this->pickGoodsImageFromShow(), // 'content'=> this->pickGoodsContentFromShow(), // 'spec' =>this->pickGoodsSpecFromShow(), // 'attr' => attrData ); } returnresult; } }
    采集器抽象类
    checkListUrl(url) == false)
            {
                throw new Exception('URL不符合规范');
                exit;
            }
    
            if(!content = file_get_contents(url))
            {
                throw new Exception('没有采集到列表页面的html代码');
            }
    
            //转码GBK转换UTF-8this->listPageHtml = this->converContent(content);
        }
    
        /**
         * @brief 获取商品详情页面数据
         * @param url string 详情页面url
         */
        public function readShowPage(url)
        {
            if(this->checkShowUrl(url) == false)
            {
                throw new Exception('URL不符合规范');
                exit;
            }
    
            content = file_get_contents(url);
    
            //转码GBK转换UTF-8
            this->showPageHtml =this->converContent(content);
        }
    
        /**
         * @brief 字符串转码
         * @paramcontent string 要转换的字符串
         * @return string
         */
        public function converContent(content)
        {
            if(this->isUTF8(content) == false)
            {
                return iconv('GBK','UTF-8//IGNORE',content);
            }
            return content;
        }
        public function isUTF8(string)
        {
            e=mb_detect_encoding(string, array('UTF-8', 'GBK'));
            switch(e){
                case 'UTF-8' : //如果是utf8编码
                    return true;
                    break;
                case 'GBK': //如果是gbk编码
                    break;
            }
        }    /**
         * @brief 检查商品列表url的合法性
         * @paramurl string
         * @return boolean
         */
        abstract public function checkListUrl(url);
    
        /**
         * @brief 检查商品详情url的合法性
         * @paramurl string
         * @return boolean
         */
        abstract public function checkShowUrl($url);
    
        /**
         * @brief 采集商品信息
         * @return array
         */
        abstract public function collect();
    }
    

    我在本次采集的操作过程中遇到几个问题给总结下。

    • 注意采集来数据的页面的编码格式,要主相应的判断和转换

    • 注意正则的匹配。采集页面有可能调整对应的正则就需要重新。

    • 注意找出那一部分是页面加载的数据,那一部分是ajax加载过来的数据,要分清楚,不如是得不到数据的

    这里我们可以用火狐浏览器的firebug来查看,那些数据是可以用正则来匹配的

    图片.png
    • 不能用正则匹配的就需要用ajax的请求获得数据如商品详情页商品的价格

    这里获取数据的时间我们要注意下,我在做这里的时间第一次直接用http://p.3.cn/prices/mgets?skuIds= 就可以获取数据,但是后面京东需要验证菜返回数据所以我们可以复制firebug中的连接,进行请求就会有数据了。

    图片.png
    • 这里我做的商品页的商品详情数据没有找到获取的方法,如果有知道的请分享给我。

    推荐阅读更多精彩内容

    • Github标星 8K+,免费又好用的Redis客户端工具!
      最近在寻找一款免费又好用的Redis客户端工具,于是找到了AnotherRedisDesktopManager,界...
      梦想de星空阅读 325评论 0赞 7
    • 用python完成淘宝毫秒级抢单,助你秒杀淘宝折扣商品
      今天给大家提供一种思路,用Python实现秒杀订单,借用自动化方式完成最优解。 1 环境 操作系统:Windows...
      黑羽_692867294阅读 405评论 1赞 14
    • 教你用Python爬猫眼电影,简单网站却有 “多重思路” !
      猫眼电影作为爬虫的必备练手网站,相信每个人都试过吧? 那么这篇文章,我就再爬一次猫眼电影,而且用上正则和xpath...
      黑羽_692867294阅读 165评论 0赞 5
    • 24、比例问题
      有一些看似特别复杂的比例问题,其实可用直接计算比例的方法: 先看简单的例子【例1】某电器工作功耗为370瓦,待机状...
      垓下_阅读 28评论 0赞 0
    • FastAPI项目开发最佳实践
      最近FastAPI项目特别火,以下是我们项目组在用FastAPI开发时的总结的一些最佳实践以及一些代码规范,分享给...
      小餐包阅读 463评论 0赞 2

    文章来源于互联网,如有雷同请联系站长删除:PHP_京东数据采集

    发表评论