const puppeteer = require('puppeteer');
(async () => {
const browser = await (puppeteer.launch({
//设置超时时间
timeout: 15000,
//如果是访问https页面 此属性会忽略https错误
ignoreHTTPSErrors: true,
// 打开开发者工具, 当此值为true时, headless总为false
devtools: false,
// 关闭headless模式, true不会打开浏览器 false会打开浏览器
headless: true
}));
const page = await browser.newPage();
await page.goto('https://xm.lianjia.com/ershoufang/pg1/');
/*最大页数*/
let max = 10;
/*爬数据*/
let all_result = [];
console.log('开始');
console.time('计时');
/*获取一页信息*/
const result = await page.evaluate(max => {
let data = [];
let _max = max||$('.house-lst-page-box a:nth-last-child(2)').html(); //获取最大页数
let elements = document.querySelectorAll('.sellListContent li'); //获取所有的li
for (var element of elements){ // 循环
let title = element.querySelector('.title a').innerHTML;
//抓取链接(href)属性
let url = element.querySelector('.noresultRecommend').href;
let xiaoqu = element.querySelector('.houseInfo a').innerHTML;
data.push({title,url,xiaoqu});
}
return {
data:data,
max:_max
};
},max);
max = result.max;
console.log('最大页数:'+max);
console.log(result.data);
console.log('当前页:1');
all_result = all_result.concat(result.data);
for (var i = 2; i <= max; i++) {
await page.goto('https://xm.lianjia.com/ershoufang/pg'+i+'/');
const result = await page.evaluate(() => {
let data = [];
let elements = document.querySelectorAll('.sellListContent li'); //获取所有的li
for (var element of elements){ // 循环
let title = element.querySelector('.title a').innerHTML;
//抓取链接(href)属性
let url = element.querySelector('.noresultRecommend').href;
let xiaoqu = element.querySelector('.houseInfo a').innerHTML;
data.push({title,url,xiaoqu});
}
return {
data:data,
};
});
console.log(result.data);
console.log('当前页:'+i);
all_result = all_result.concat(result.data);
}
console.timeEnd('计时');
console.time('处理数据时间');
console.log('处理数据开始');
let xiaoqu_count_array = [];
xiaoqu_count_array = dealData(all_result);
/*处理数据*/
function dealData(all_result) {
let xiaoqu_count = {};
let xiaoqu_count_array = [];
/*聚合*/
for (var i = all_result.length - 1; i >= 0; i--) {
var itme = all_result[i];
var _xiaoqu = itme.xiaoqu.replace(' ','');
xiaoqu_count[_xiaoqu] = xiaoqu_count[_xiaoqu]||0;
xiaoqu_count[_xiaoqu]++;
}
/*变成数组*/
for (x in xiaoqu_count){
xiaoqu_count_array.push({'name':x,'count':xiaoqu_count[x]});
}
return xiaoqu_count_array;
}
/*排序输出*/
function compare(propertyName) {
return function(object1, object2) {
var value1 = object1[propertyName];
var value2 = object2[propertyName];
if (value2 < value1) {
return 1;
} else if (value2 > value1) {
return -1;
} else {
return 0;
}
}
}
xiaoqu_count_array.sort(compare("count"));
console.log('xiaoqu_count_array_new');
console.log(xiaoqu_count_array[xiaoqu_count_array.length-1]);
console.log('处理数据结束');
console.timeEnd('处理数据时间');
})();
/*page.setViewport*/
/*设置视窗*/
/*viewport <Object>
width <number> 宽度,单位是像素
height <number> 高度,单位是像素
deviceScaleFactor <number> 定义设备缩放, (类似于 dpr)。 默认 1。
isMobile <boolean> 要不要包含meta viewport 标签。 默认 false。
hasTouch<boolean> 指定终端是否支持触摸。 默认 false
isLandscape <boolean> 指定终端是不是 landscape 模式。 默认 false。
返回: <Promise>*/
/*page.goto*/
/*到指定页面*/
/*url <string> 导航到的地址. 地址应该带有http协议, 比如 https://.
options <Object> 导航配置,可选值:
timeout <number> 跳转等待时间,单位是毫秒, 默认是30秒, 传 0 表示无限等待。可以通过page.setDefaultNavigationTimeout(timeout)方法修改默认值
waitUntil <string|Array<string>> 满足什么条件认为页面跳转完成,默认是 load 事件触发时。指定事件数组,那么所有事件触发后才认为是跳转完成。事件包括:
load - 页面的load事件触发时
domcontentloaded - 页面的 DOMContentLoaded 事件触发时
networkidle0 - 不再有网络连接时触发(至少500毫秒后)
networkidle2 - 只有2个网络连接时触发(至少500毫秒后)
referer <string> Referer header value. If provided it will take preference over the referer header value set by page.setExtraHTTPHeaders().
返回: <Promise<?Response>> Promise对象resolve后是主要的请求的响应。如果有多个跳转, resolve后是最后一次跳转的响应*/
/*page.screenshot*/
/*截屏*/
/*options <Object> 可选配置:
path <string> 截图保存路径。截图图片类型将从文件扩展名推断出来。如果是相对路径,则从当前路径解析。如果没有指定路径,图片将不会保存到硬盘。
type <string> 指定截图类型, 可以是 jpeg 或者 png。默认 'png'.
quality <number> 图片质量, 可选值 0-100. png 类型不适用。
fullPage <boolean> 如果设置为true,则对完整的页面(需要滚动的部分也包含在内)。默认是false
clip <Object> 指定裁剪区域。需要配置:
x <number> 裁剪区域相对于左上角(0, 0)的x坐标
y <number> 裁剪区域相对于左上角(0, 0)的y坐标
width <number> 裁剪的宽度
height <number> 裁剪的高度
omitBackground <boolean> 隐藏默认的白色背景,背景透明。默认不透明
encoding <string> 图像的编码可以是 base64 或 binary。 默认为“二进制”。
返回: <Promise<[Buffer|String]>> Promise对象,resolve后是截图的buffer
*/
/* await page.screenshot({
path: '4399.png',
type: 'png',
// quality: 100, 只对jpg有效
fullPage: true,
// 指定区域截图,clip和fullPage两者只能设置一个
// clip: {
// x: 0,
// y: 0,
// width: 1000,
// height: 40
// }
});*/
/*page.waitFor*/
/*页面等待,可以是时间、某个元素、某个函数*/
/*此方法根据第一个参数的不同有不同的结果:
如果 selectorOrFunctionOrTimeout 是 string,
那么认为是 css 选择器或者一个xpath, 根据是不是'//'开头, 这时候此方法是 page.waitForSelector 或 page.waitForXPath的简写
如果 selectorOrFunctionOrTimeout 是 function,
那么认为是一个predicate,这时候此方法是page.waitForFunction()的简写
如果 selectorOrFunctionOrTimeout 是 number,
那么认为是超时时间,单位是毫秒,返回的是Promise对象,在指定时间后resolve
否则会报错*/
主要用到了page的几个方法
后续数据简单处理了下,得到房源最多的小区。