node实现爬虫之遇到的坑

node实现爬虫之遇到的坑

1、需要的工具

1)superagent(超级代理):用来发送http请求,需要注意的是它发出的请求是异步的

安装方式:

npm install superagent 或者yarn add superagent

2)cheerio:用来将浏览器返回的结果转换为html文档,方便解析

安装:

npm install cheerio

2、实现过程

1、需求分析

本次爬虫需要爬取链家上的所有省份、城市及每个城市包含的区域信息

链接地址:https://www.lianjia.com/city/

2、导入所需文件

const express = require('express');

const app = express();

 const superagent = require('superagent');

 const cheerio = require('cheerio');

let url = 'https://www.lianjia.com/city/';//将要爬取的网站

如图:
在这里插入图片描述

3、开始发送请求

 //superagent可以发送get,post,put,delete,head请求
 superagent.get(url,(err,res)=>{
     if(err) console.log(err)
     //res.text及为浏览器返回的整个页面字符串
     getCity(res.text);

    })

superagent的使用详情

4、开始解析

1、使用cheerio解析
//将字符串使用cheerio.load解析为html文档,解析完成之后可以使用类似jQuery的语法获取元素内容
let $ = cheerio.load(res);
2、获取到需要取数据的标签
//获取到值以后使用each方法遍历
$('.city_list_ul .city_firstletter').each((item,ele)=>{}
3、取值
//使用$(ele).text()方法取得标签中的内容
/**
*如果需要取某个属性,比如a标签的herf属性值,则使用$(ele).attr('href')
*/
let city = {
    letter: $(ele).children('span').text(),
    provinces:[],
}
4、完整代码
let getCity =async (res)=>{
		//将字符串使用cheerio.load解析为html文档,解析完成之后可以使用类似jQuery的语法获取元素内容
        let $ = cheerio.load(res);
        //获取所有的省份列表
        $('.city_list_ul .city_firstletter').each((item,ele)=>{
            let promise;
            //定义所有省份信息
            let city = {
                letter: $(ele).children('span').text(),
                provinces:[],
            }
            //获取省份信息
            $(ele).siblings('.city_list').children('.city_province').each((item,ele)=>{
                //定义一个省份列表
               let province = {
                    tit:$(ele).children('.city_list_tit').text(),
                    cities:[]//放每个省份的城市列表
                };
                //获取城市列表
               $(ele).children('ul').children('li').each((_item,_ele)=>{
                   //定义城市信息列表
                    let cList = {
                        cName:$(_ele).text(),
                        url:$(_ele).children('a').attr('href'),
                        areas:[]
                    }
                    //获取每个城市的区域列表
                    promise = new Promise(async(resolve,reject)=>{
                        let res = await superagent.get(`${cList.url}/ershoufang/`);
                        let reslut = getAreas(res.text);
                        cList.areas=reslut;
                        //console.log(cList.cName)
                        province.cities.push(cList);
                        resolve('1')
                    })
                })
                promise.then((result)=>{
                     city.provinces.push(province);
                })
            })
            
            //将信息插入数据库
            promise.then((result)=>{
              	console.log(city)
            })
        })
    }
    //获取区域信息的方法
    let getAreas = (res)=>{
        let $ = cheerio.load(res);
        var area ;
        var areas = [];
        $('.position > dl:nth-child(2) > dd > div:nth-child(1) > div a').each((item,ele)=>{
                area = {
                name:$(ele).text(),
                url:$(ele).attr('href')
            }
            areas.push(area)
        })
        return areas;
    }

3、踩坑之旅

1、分析

因为当获取到城市信息后,再去获取该城市对应的区域信息,需要发送新的http请求,而该请求又是异步方法,所以会导致先执行了后续的程序(我将数据保存到了数据库,这时数据库中的区域信息为空),最后才拿到返回的区域信息

2、解决

将发送新请求的方法封装为一个promise对象,再与async和await结合

 promise = new Promise(async(resolve,reject)=>{
     let res = await superagent.get(`${cList.url}/ershoufang/`);
     let reslut = getAreas(res.text);
     cList.areas=reslut;
     //console.log(cList.cName)
     province.cities.push(cList);
     resolve('1')
 })

等到数据返回后再使用promise.then方法操作

promise.then((result)=>{
	city.provinces.push(province);
})
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值