spider(爬蟲)

spider(爬蟲)

推薦抓取工具:火車采集器\火車頭采集器

爬蟲抓取網(wǎng)頁

    //node 中http模塊,可以用來開啟服務(wù)器(http.createServer),也可以用來開啟客戶端(http.request)
    //網(wǎng)頁抓取核心代碼如下 --> server.js
    const http = require('http');
    const https = require('https');
    const urllib = require('url');
    const fs = require('fs');
    const pathlib = require('path');
    const assert = require('assert');
    /*
    封裝http.request,用來自動(dòng)分別http與https
    url --> 網(wǎng)址
    headers --> options需要的headers
    */
    function reqUrl(url,headers){
        //使用url模塊解析url,得到url對(duì)象
        let urlObj = urllib.parse(url);
        //用來獲取http或者h(yuǎn)ttps
        let httpMode = null;
        if(urlObj.protocol == 'http:'){
            httpMode=http;
        }else if(urlObj.protocol == 'https:'){
            httpMode=https;
        }else{
            console.log(urlObj.protocol);
            throw new Error('錯(cuò)誤');
        }
        //http.request的optios參數(shù)
        const options = {
            host:urlObj.host,//要爬取的網(wǎng)站
            path:urlObj.path,//要爬取的路徑
            header:headers//某些網(wǎng)站爬取需要的headers
        };
        //因http.request是個(gè)異步函數(shù),所以此處return一個(gè)promise
        return new Promise((resolve,reject)=>{
            //http.request,作為一個(gè)客戶端向服務(wù)端發(fā)起請(qǐng)求
            let req = httpMode.request(options,res=>{
                // res.statusCode作為訪問成功與否的標(biāo)準(zhǔn)
                if(res.statusCode>=200&&res.statusCode<300||res.statusCode==304){
                    let arr = [];
                    res.on('data',function (data){
                        arr.push(data);
                    });
                    res.on('end',function (){
                        let buffer = Buffer.concat(arr);
                        //接收處理結(jié)果交由resolve()
                        resolve({
                            statusCode:200,
                            body:      buffer,
                            headers:   res.headers
                        })
                    })
                //如果是301或者302,也是成功這是需要跳轉(zhuǎn)   
                }else if(res.statusCode==301||res.statusCode==302){
                    resolve({
                        statusCode:res.statusCode,
                        body:      null,
                        headers:   res.headers
                    })
                //出錯(cuò)了
                }else{
                reject({
                    statusCode:res.statusCode,
                    body:      null,
                    headers:   res.headers
                });
                }
            });
            //請(qǐng)求的時(shí)候就出錯(cuò)了,例如網(wǎng)址不存在
            req.on('error',err=>{
                console.log('error',err);
            });
            req.write('');
            //end()表示正式開始請(qǐng)求
            req.end();
        })
    }

    async function req(url){
        try{
            //循環(huán)處理多次301或者302的情況
            while(true){
                let {statusCode,body,headers} = await reqUrl(url);
                console.log(statusCode,body,headers);
                
                if(statusCode==200){
                    return {body,headers}//成功之后 退出循環(huán)
                }else{
                    //let {statusCode,body,headers:head} = await reqUrl(headers.location);
                    assert(headers.location);//此處使用斷言一定有此屬性
                    url=headers.location;//不成功將url重新賦值,繼續(xù)循環(huán)
                }
            }
        }catch(e){
            console.log('進(jìn)到catch',e);
        }
    }
    //因req是一個(gè)async函數(shù),所以此處也需要使用async函數(shù)接收數(shù)據(jù),此處使用了自調(diào)用函數(shù)
    (async ()=>{
        let {body,headers} = await req('http://www.tmall.com');
        fs.writeFile('spider',body,err=>{
            if(err){
                console.log('寫入失敗');
                
            }else{
                console.log('寫入完成');
                
            }
        })
    })()

jsdom.js

    原因:因爬蟲抓取的是html網(wǎng)頁,所以需要進(jìn)行數(shù)據(jù)解析,jsdom第三方模塊可以實(shí)現(xiàn)
    作用:將html反向解析成dom對(duì)象
    安裝:cnpm i jsdom -D
    使用:
        const JSDOM = require('jsdom').JSDOM;
        const fs=require('fs');
        fs.readFile('test.html', (err, buffer)=>{
            if(err){
                console.log('讀取失敗');
            }else{
                let html=buffer.toString();
                //創(chuàng)建jsdom對(duì)象,并將需要解析的對(duì)象傳參進(jìn)去
                let jsdom=new JSDOM(html);
                //獲取dom對(duì)象
                let document=jsdom.window.document;
                //創(chuàng)建$
                let $=document.querySelectorAll.bind(document);
                //按照J(rèn)S操作dom對(duì)象方式進(jìn)行操作即可
                let oTxt=$('input.txt1')[0];
                console.log(oTxt.value);
            }
        });

爬蟲抓取數(shù)據(jù)

1. 使用爬蟲抓取網(wǎng)頁;(此處以天貓手機(jī)網(wǎng)頁為例,部分網(wǎng)站數(shù)據(jù)應(yīng)該是抓取shr數(shù)據(jù))  
2. 使用jsdom對(duì)網(wǎng)頁進(jìn)行解析
3. 封裝存庫,繼續(xù)向下抓取,等等等操作
4. 詳見4-19.zip --> tmall_shouji_spider2.js
某些頁面編碼是gbk然而node本身不認(rèn)gbk編碼,所以buffer.toString('gbk')指定編碼的方法不可用,這里需要使用第三方gbk模塊;
cnpm i gbk -D
const gbk=require('gbk');
gbk.toString('utf-8',buffer);//使用gbk模塊將buffer編碼變成utf-8
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • Python版本管理:pyenv和pyenv-virtualenvScrapy爬蟲入門教程一 安裝和基本使用Scr...
    inke閱讀 35,576評(píng)論 7 93
  • 為什么要做爬蟲? 都說現(xiàn)在是"大數(shù)據(jù)時(shí)代",那數(shù)據(jù)從何而來? 企業(yè)產(chǎn)生的用戶數(shù)據(jù):百度指數(shù) http://inde...
    錦魚閱讀 1,036評(píng)論 0 0
  • 我們一般比較常用的爬蟲而且比較強(qiáng)大的框架。今天就簡(jiǎn)單的介紹一下爬蟲的框架--scrapy。首先去看一下他的架構(gòu)流程...
    Franckisses閱讀 431評(píng)論 0 0
  • QUANTAXIS 爬蟲部分 目前的QUANTAXIS爬蟲是用python的scrapy框架寫的,為了運(yùn)行Java...
    yutiansut閱讀 869評(píng)論 0 1
  • 我們?cè)趯懪老x的時(shí)候,首先要找到一個(gè)可以調(diào)用的URL來獲取服務(wù)器的資源。邏輯就是我們通過這個(gè)URL來發(fā)起請(qǐng)求。來獲取...
    Franckisses閱讀 1,599評(píng)論 0 0