使用nodejs的puppeteer库爬取瓜子二手车网站
const puppeteer = require('puppeteer');
(async () => {
const fs = require("fs");
const rootUrl = 'https://www.guazi.com'
const workPath = './contents';
if (!fs.existsSync(workPath)) {
fs.mkdirSync(workPath)
}
const browser = await (puppeteer.launch({ headless: false }));
const page = await browser.newPage()
await page.setViewport({ width: 1128, height: 736 });
await page.setRequestInterception(true); // 拦截器
page.on('request', request => { //拦截图片
if (request.resourceType() === 'image')
request.abort();
else
request.continue();
});
await page.goto("https://www.guazi.com/fuzhou/buy")
const m_cityList = await page.evaluate(() => { // 获取所有城市
const elements = Array.from(document.querySelectorAll('.all-city dl'))
return elements.map(s => {
let dd = s.getElementsByTagName("dd").item(0)
let ddList = []
for (let i = 0; i < dd.getElementsByTagName("a").length; i++) {
ddList.push({
"cityName": dd.getElementsByTagName("a").item(i).innerHTML,
"url": dd.getElementsByTagName("a").item(i).getAttribute("href")
})
}
return ddList
})
})
//数组扁平化
const flattenNew = arr => arr.reduce((prev, next) => Object.prototype.toString.call(next) == '[object Array]' ? prev.concat(flattenNew(next)) : prev.concat(next), [])
const cityList = flattenNew(m_cityList)
console.log("城市列表爬取完毕")
await page.waitFor(2000 + Math.round(Math.random() * 100))
for (let i = 0; i < cityList.length; i++) {
await page.waitFor(1000 + Math.round(Math.random() * 100))
await page.goto(rootUrl + cityList[i].url)
console.log("跳转到" + cityList[i].cityName)
console.log("开始爬取" + cityList[i].cityName + "的所有二手车品牌")
try {
let brandList = await page.evaluate(() => { //品牌
let Array = []
const dl = document.querySelectorAll('.screen').item(0).getElementsByTagName("dl")
const div = dl.item(0).getElementsByTagName("dd").item(0).getElementsByTagName("div").item(1)
const ul = div.getElementsByTagName("ul")
for (let i = 0; i < ul.length; i++) {
let li = ul.item(i).getElementsByTagName("li")
for (let j = 0; j < li.length; j++) {
let a = li.item(j).getElementsByTagName("p").item(0).getElementsByTagName("a")
for (let k = 0; k < a.length; k++) {
Array.push({
"brand": a.item(k).innerHTML,
"url": a.item(k).getAttribute("href")
})
}
}
}
return Array
})
console.log(cityList[i].cityName + "的所有二手车品牌爬取完毕")
for (let j = 0; j < brandList.length; j++) {
console.log("开始爬取" + cityList[i].cityName + "-" + brandList[j].brand + "的所有车系")
await page.waitFor(1000 + Math.round(Math.random() * 100))
await page.goto(rootUrl + brandList[j].url)
try {
const carTypeList = await page.evaluate(() => { //车型
let Array = []
const dl = document.querySelectorAll('.screen').item(0).getElementsByTagName("dl")
const div = dl.item(1).getElementsByTagName("dd").item(0).getElementsByTagName("div").item(1)
const li = div.getElementsByTagName("ul").item(0).getElementsByTagName("li")
for (let j = 0; j < li.length; j++) {
let a = li.item(j).getElementsByTagName("p").item(0).getElementsByTagName("a")
for (let k = 0; k < a.length; k++) {
Array.push({
"carType": a.item(k).innerHTML.replace(/\s*/g, ""),
"url": a.item(k).getAttribute("href")
})
}
}
return Array
})
console.log(cityList[i].cityName + "-" + brandList[j].brand + "的所有车系爬取完毕")
for (let k = 0; k < carTypeList.length; k++) {
await page.waitFor(1000 + Math.round(Math.random() * 100))
console.log("开始爬取" + cityList[i].cityName + "-" + brandList[j].brand + "-" + carTypeList[k].carType + "的所有二手车")
let newUrl = rootUrl + carTypeList[k].url
pathArray = newUrl.split("/") //拿到第一页url,得到后面的页面的url
let urlArray = []
try {
await page.goto(newUrl)
const pageNum = await page.evaluate(() => { //获取总页数
let li = document.querySelectorAll("ul.pageLink").item(0).getElementsByTagName("li")
let liNum = li.length
return li.item(li.length - 2).getElementsByTagName("a").item(0).getElementsByTagName("span").item(0).innerHTML
})
for (let i = 1; i <= pageNum; i++) { //将所有的页面存入数组中
urlArray.push(newUrl.replace(new RegExp("/" + pathArray[pathArray.length - 1], 'g'), "/o" + i + "/" + pathArray[pathArray.length - 1]))
}
} catch (error) {
console.log(cityList[i].cityName + "-" + brandList[j].brand + "-" + carTypeList[k].carType + "的所有二手车列表爬取失败,该车型可能只有少量或者没有")
}
if (urlArray.length != 0) {
for (let i = 0; i < urlArray.length; i++) {
await page.goto(urlArray[i]);
const list = await page.evaluate(() => {
let carArray = []
let li = document.querySelectorAll("ul.carlist").item(0).getElementsByTagName("li")
for (let i = 0; i < li.length; i++) {
a = li.item(i).getElementsByTagName("a").item(0)
carArray.push({
"url": a.getAttribute("href"),
"imgUrl": a.getElementsByTagName("img").item(0).getAttribute("src"),
"carName": a.getElementsByTagName("h2").item(0).innerHTML,
"carData": (a.getElementsByTagName("div").item(0).innerHTML).replace(new RegExp('<span class="icon-pad">', 'g'), "").replace(new RegExp('</span>', 'g'), ""),
"price": a.getElementsByTagName("div").item(1).getElementsByTagName("p").item(0).innerHTML.replace(new RegExp('<span>', 'g'), "").replace(new RegExp('</span>', 'g'), "").replace(/\s*/g, "")
})
}
return carArray
})
await page.waitFor(500 + Math.round(Math.random() * 100))
console.log(list)
}
}else{
try {
const list = await page.evaluate(() => {
let carArray = []
let li = document.querySelectorAll("ul.carlist").item(0).getElementsByTagName("li")
console.log("该车型少量")
for (let i = 0; i < li.length; i++) {
a = li.item(i).getElementsByTagName("a").item(0)
carArray.push({
"url": a.getAttribute("href"),
"imgUrl": a.getElementsByTagName("img").item(0).getAttribute("src"),
"carName": a.getElementsByTagName("h2").item(0).innerHTML,
"carData": (a.getElementsByTagName("div").item(0).innerHTML).replace(new RegExp('<span class="icon-pad">', 'g'), "").replace(new RegExp('</span>', 'g'), ""),
"price": a.getElementsByTagName("div").item(1).getElementsByTagName("p").item(0).innerHTML.replace(new RegExp('<span>', 'g'), "").replace(new RegExp('</span>', 'g'), "").replace(/\s*/g, "")
})
}
return carArray
})
await page.waitFor(500 + Math.round(Math.random() * 100))
console.log(list)
} catch (error) {
console.log("该车型没有")
}
}
}
} catch (error) {
console.log(cityList[i].cityName + "-" + brandList[i].brand + "的所有车系爬取失败")
}
}
} catch (error) {
console.log(cityList[i].cityName + "二手车品牌爬取失败")
}
await page.waitFor(1000 + Math.round(Math.random() * 100))
}
})();
时间比较赶,先附上代码和运行截图

有兴趣的可以 看一下项目地址
https://gitee.com/xu_hui_hong/nodejs_puppeteer_guazi2
使用nodejs的puppeteer库爬取瓜子二手车网站的更多相关文章
- Python——爬取瓜子二手车
# coding:utf8 # author:Jery # datetime:2019/5/1 5:16 # software:PyCharm # function:爬取瓜子二手车 import re ...
- python爬虫学习之使用BeautifulSoup库爬取开奖网站信息-模块化
实例需求:运用python语言爬取http://kaijiang.zhcw.com/zhcw/html/ssq/list_1.html这个开奖网站所有的信息,并且保存为txt文件和excel文件. 实 ...
- Python scrapy框架爬取瓜子二手车信息数据
项目实施依赖: python,scrapy ,fiddler scrapy安装依赖的包: 可以到https://www.lfd.uci.edu/~gohlke/pythonlibs/ 下载 pywi ...
- nodejs中使用cheerio爬取并解析html网页
nodejs中使用cheerio爬取并解析html网页 转 https://www.jianshu.com/p/8e4a83e7c376 cheerio用于node环境,用法与语法都类似于jquery ...
- 一起学爬虫——使用xpath库爬取猫眼电影国内票房榜
之前分享了一篇使用requests库爬取豆瓣电影250的文章,今天继续分享使用xpath爬取猫眼电影热播口碑榜 XPATH语法 XPATH(XML Path Language)是一门用于从XML文件中 ...
- python爬虫学习(三):使用re库爬取"淘宝商品",并把结果写进txt文件
第二个例子是使用requests库+re库爬取淘宝搜索商品页面的商品信息 (1)分析网页源码 打开淘宝,输入关键字“python”,然后搜索,显示如下搜索结果 从url连接中可以得到搜索商品的关键字是 ...
- Python 爬取所有51VOA网站的Learn a words文本及mp3音频
Python 爬取所有51VOA网站的Learn a words文本及mp3音频 #!/usr/bin/env python # -*- coding: utf-8 -*- #Python 爬取所有5 ...
- scrapy爬取西刺网站ip
# scrapy爬取西刺网站ip # -*- coding: utf-8 -*- import scrapy from xici.items import XiciItem class Xicispi ...
- Python开发爬虫之BeautifulSoup解析网页篇:爬取安居客网站上北京二手房数据
目标:爬取安居客网站上前10页北京二手房的数据,包括二手房源的名称.价格.几室几厅.大小.建造年份.联系人.地址.标签等. 网址为:https://beijing.anjuke.com/sale/ B ...
随机推荐
- 用STM32的UART实现DMX512
写在最前面: DMX512(digital multiplex) 其实就是主机向从机整包单向广播发送的协议(protocol),从机自取所需. 一.链接拓扑(network topology) 根据后 ...
- 2017-ACM南宁网络赛
In this problem, we will define a graph called star graph, and the question is to find the minimum d ...
- HDU2859
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2859 AC思路:(思路来源于kuangbin,甚至做法也跟kuangbin大同小异,所以可以将本文看成 ...
- 必会技能!Docker助你快速上手玩转HBase!
前言:本文主要讲述了如何使用Docker快速上手HBase,省去繁杂的安装部署环境,直接上手,小白必备.适合HBase入门学习及简单代码测试. 1. Docker 安装 参考地址: https://y ...
- [PHP学习教程 - 系统]002.模拟守护进程(Daemon)-程序永远在后台运行
引言:如何模拟那些自动轮循的服务,像守护进程(Daemon)那样,可以一直执行,永不停歇呢! Come on! Do it! Do! Do! Do!.... 使用接口: int ignore_user ...
- for循环结构的使用
/* for循环格式: for(①初始化条件; ②循环条件 :③迭代部分){ //④循环体 } 执行顺序:①-②-④-③---②-④-③-----直至循环条件不满足 退出当前循环 * */ publi ...
- C#线程 使用线程
第三部分 使用线程 基于事件的异步模式 基于事件的异步模式(EAP)提供了一种简单的方法,通过这些方法,类可以提供多线程功能,而使用者无需显式启动或管理线程.它还提供以下功能: 合作取消模型 工作人员 ...
- 解决pip._vendor.urllib3.exceptions.ReadTimeoutError: HTTPSConnectionPool(host='files.pythonhosted.org', port=443): Read timed out.问题
国内的其他镜像源清华大学 https://pypi.tuna.tsinghua.edu.cn/simple/阿里云 http://mirrors.aliyun.com/pypi/simple/中国科技 ...
- MySQL 可重复读,差点就我背上了一个 P0 事故!
小黑黑的碎碎念 哎,最近有点忙,备考复习不利,明天还要搬家,好难啊!! 本想着这周鸽了,但是想想还是不行,爬起来,更新一下,周更可不能断.偷懒一下,修改一下之前的一篇历史文章,重新发布一下. P0 事 ...
- 网络编程-TCP长连接和短连接
TCP是一个面向连接的协议.无论哪一方向另一方发送数据之前,都必须先在双方之间建立一条连接.下面会介绍一个TCP连接是如何建立的以及通信结束后是如何终止的. 一.TCP连接的建立与终止 1.1 建立连 ...