最近在找房子,就写了个程序,爬取一下58房源
由于58的APP筛房子没有各种排序,不好找房子,没有我爱我家的APP写的好,但是我爱我家又要中介费
就写了个程序爬取导出58所有房源,然后一览众山小
步骤如下
下载使用Charles
使用方法
https://blog.csdn.net/forebe/article/details/98945139
手机连接上Charles后保证能抓数据之后
打开58APP 设置你搜的租房条件
然后再手机上一直往下拉 拉倒低
然后过滤请求
https://apphouse.58.com/api/list/chuzu/?focusActiveDict
接下来全选 右键保存到一个文件夹
然后随便创建一个项目 把代码贴进去 运行
运行代码
package com.songaw.pachong; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; /** * @author songanwei * @description todo * @date 2022/8/31 */ public class WubaPachong { public static void main(String[] args) { File dir=new File("/Users/mac/Desktop/58"); List<JSONObject> jsonList=new ArrayList<>(); if(dir.isDirectory()){ File[] jsonFiles=dir.listFiles(); if(jsonFiles!=null&&jsonFiles.length>0){ for(File jsonFile:jsonFiles){ String jsonStr=readFile(jsonFile); jsonStr=jsonStr.replaceAll("\n","").replaceAll("\t",""); if(jsonStr==null){ continue; } try{ JSONObject jsonObject=JSON.parseObject(jsonStr); jsonList.add(jsonObject); }catch (Exception e){ e.printStackTrace(); } } } } if(jsonList.size()>0){ exportPachong("58租房",jsonList); } } private static String readFile(File file){ String line=null; FileInputStream fis=null; try { fis = new FileInputStream(file); byte[] data = new byte[(int) file.length()]; fis.read(data); line = new String(data, StandardCharsets.UTF_8); }catch (Exception e){ return null; }finally { if(fis!=null) { try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } } return line; } public static void exportPachong(String title, List<JSONObject> excelMapList){ // 序号 抓取时间 发布平台 板块 子版块 榜单名字 榜单地址 第1个产品名字 第2个产品名字 第3个产品名字 第4个产品名字 第5个产品名字 第6个产品名字 第7个产品名字 第8个产品名字 第9个产品名字 第10个产品名字 Date now = new Date(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd"); String dateStr=sdf.format(now); List<Object[]> dataList = new ArrayList<Object[]>(); int count=0; for (int i = 0; i < excelMapList.size(); i++) { JSONObject jsonObject = excelMapList.get(i).getJSONObject("result"); JSONObject getListInfo=jsonObject.getJSONObject("getListInfo"); if(getListInfo==null){ continue; } JSONArray infolist=getListInfo.getJSONArray("infolist"); if(infolist==null){ continue; } for(int j=0;j<infolist.size();j++){ count++; JSONObject info=infolist.getJSONObject(j); List<Object> elementList=new ArrayList<>(); elementList.add(""+count); elementList.add(dateStr); elementList.add(info.get("title") == null ? "" : info.get("title").toString()); elementList.add(info.get("huxing") == null ? "" : info.get("huxing").toString()); elementList.add(info.get("area") == null ? "" : info.get("area").toString().replace("㎡","")); elementList.add(info.get("price") == null ? "" : info.get("price").toString().replace("元/月","")); elementList.add(info.get("date") == null ? "" : info.get("date").toString()); String tuijian=""; try { tuijian = info.getJSONObject("recommendReason").getString("text"); }catch (Exception e){ e.printStackTrace(); } elementList.add(tuijian); elementList.add(info.get("lastLocal") == null ? "" : info.get("lastLocal").toString()); String local_address=""; try { local_address = info.getJSONObject("distanceDict").getString("local_address"); }catch (Exception e){ e.printStackTrace(); } elementList.add(local_address); String louceng=""; String chaoxiang=""; String jingwei=""; try { louceng = info.getJSONObject("detailaction").getJSONObject("content").getJSONObject("preLoadInfo") .getJSONObject("result").getJSONArray("info").getJSONObject(5).getJSONObject("zf_titleinfo_area") .getJSONArray("base_info").getJSONObject(2).getString("title"); chaoxiang = info.getJSONObject("detailaction").getJSONObject("content").getJSONObject("preLoadInfo") .getJSONObject("result").getJSONArray("info").getJSONObject(5).getJSONObject("zf_titleinfo_area") .getJSONArray("base_info").getJSONObject(3).getString("title"); }catch (Exception e){ e.printStackTrace(); } elementList.add(louceng); elementList.add(chaoxiang); try { String xq_lat=info.getJSONObject("detailaction").getJSONObject("content").getJSONObject("preLoadInfo") .getJSONObject("result").getJSONArray("info").getJSONObject(13).getJSONObject("zf_simplemap_trip").getString("xq_lat"); String xq_lon=info.getJSONObject("detailaction").getJSONObject("content").getJSONObject("preLoadInfo") .getJSONObject("result").getJSONArray("info").getJSONObject(13).getJSONObject("zf_simplemap_trip").getString("xq_lon"); jingwei = xq_lat+","+xq_lon; }catch (Exception e){ e.printStackTrace(); } elementList.add(info.get("usedTages") == null ? "" : info.get("usedTages").toString()); elementList.add(jingwei); Object[] element =new String[elementList.size()]; for(int k=0;k<elementList.size();k++) { element[k]=elementList.get(k); } dataList.add(element); } } String[] rowName = {"序号", "抓取时间", "标题", "户型", "面积", "价格", "发布时间", "推荐内容", "地址1", "地址2", "楼层", "朝向", "Tag", "经纬度" }; try { String fileUrl=title+new SimpleDateFormat("yyyy年MM月dd日_HH").format(new Date())+".xls"; File file = new File("/tmp/"+fileUrl); HSSFWorkbook workbook; if(file.exists()) { workbook=new HSSFWorkbook(new FileInputStream(file)); workbook = PoiUtils.export2(workbook,title, rowName, dataList); }else{ workbook = PoiUtils.export(title, rowName, dataList); } // Excel的名字 FileOutputStream outputStream = new FileOutputStream(file); workbook.write(outputStream); System.out.println("抓取成功"); outputStream.close(); } catch (Exception e) { e.printStackTrace(); } } }
工具类
package com.songaw.pachong; import com.alibaba.fastjson.JSONObject; import org.apache.poi.hssf.usermodel.*; import org.apache.poi.hssf.util.CellRangeAddress; import org.apache.poi.hssf.util.HSSFColor; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; /** * @Description:excel导出工具类 * @Author: dk * @Date: 2020/1/14 9:49 */ public class PoiUtils { public static void exportPachong(String title, List<JSONObject> excelMapList,Call call){ // 序号 发布时间 抓取时间 发布平台 板块 子版块 品牌 内容地址 内容形式(图文/直播/视频) 标题 阅读数/曝光量/播放量 互动量(助力) 点赞数 评论数 收藏数 转发数 发布者昵称 发布者认证信息 发布者粉丝数 发布者个人主页点赞数 发布者关注数 String[] rowName = {"序号", "发布时间", "抓取时间", "发布平台", "板块", "子版块", "品牌", "内容地址", "内容形式(图文/直播/视频)", "标题", "阅读数/曝光量/播放量", "互动量(助力)", "点赞数", "评论数", "收藏数", "转发数", "发布者昵称", "发布者认证信息", "发布者粉丝数", "发布者个人主页点赞数", "发布者关注数"}; List<Object[]> dataList = new ArrayList<Object[]>(); for (int i = 0; i < excelMapList.size(); i++) { JSONObject jsonObject = excelMapList.get(i); Object[] element =call.call(i,jsonObject); dataList.add(element); } try { String fileUrl=title+new SimpleDateFormat("yyyy年MM月dd日_HH").format(new Date())+".xls"; File file = new File("/tmp/"+fileUrl); HSSFWorkbook workbook; if(file.exists()) { workbook=new HSSFWorkbook(new FileInputStream(file)); workbook = PoiUtils.export2(workbook,title, rowName, dataList); }else{ workbook = PoiUtils.export(title, rowName, dataList); } // Excel的名字 FileOutputStream outputStream = new FileOutputStream(file); workbook.write(outputStream); outputStream.close(); System.out.println("爬取完成"); } catch (Exception e) { e.printStackTrace(); } } abstract static class Call{ abstract Object[] call(int i,JSONObject jsonObject); } /** * excel导出数据 * * @param title 显示的导出表的标题 * @param rowName 导出表的列名 * @param dataList 表的内容 * @return */ public static HSSFWorkbook export(String title, String[] rowName, List<Object[]> dataList) throws Exception { HSSFWorkbook workbook = new HSSFWorkbook(); // 创建工作簿对象 HSSFSheet sheet = workbook.createSheet(title); // 创建工作表 // 产生表格标题行 HSSFRow rowm = sheet.createRow(0); HSSFCell cellTiltle = rowm.createCell(0); // sheet样式定义【getColumnTopStyle()/getStyle()均为自定义方法 - 在下面 - 可扩展】 HSSFCellStyle columnTopStyle = getColumnTopStyle(workbook);// 获取列头样式对象 HSSFCellStyle style = getStyle(workbook); // 单元格样式对象 sheet.addMergedRegion(new CellRangeAddress(0, 1, 0, (rowName.length - 1))); cellTiltle.setCellStyle(columnTopStyle); cellTiltle.setCellValue(title); // 定义所需列数 int columnNum = rowName.length; HSSFRow rowRowName = sheet.createRow(2); // 在索引2的位置创建行(最顶端的行开始的第二行) // 将列头设置到sheet的单元格中 for (int n = 0; n < columnNum; n++) { HSSFCell cellRowName = rowRowName.createCell(n); // 创建列头对应个数的单元格 cellRowName.setCellType(HSSFCell.CELL_TYPE_STRING); // 设置列头单元格的数据类型 HSSFRichTextString text = new HSSFRichTextString(rowName[n]); cellRowName.setCellValue(text); // 设置列头单元格的值 cellRowName.setCellStyle(columnTopStyle); // 设置列头单元格样式 } // 将查询出的数据设置到sheet对应的单元格中 for (int i = 0; i < dataList.size(); i++) { Object[] obj = dataList.get(i);// 遍历每个对象 HSSFRow row = sheet.createRow(i + 3);// 创建所需的行数 for (int j = 0; j < obj.length; j++) { HSSFCell cell = null; // 设置单元格的数据类型 cell = row.createCell(j, HSSFCell.CELL_TYPE_STRING); if (!"".equals(obj[j]) && obj[j] != null) { cell.setCellValue(obj[j].toString()); // 设置单元格的值 }else{ cell.setCellValue(""); } cell.setCellStyle(style); // 设置单元格样式 } } // 让列宽随着导出的列长自动适应 for (int colNum = 0; colNum < columnNum; colNum++) { int columnWidth = sheet.getColumnWidth(colNum) / 256; for (int rowNum = 0; rowNum < sheet.getLastRowNum(); rowNum++) { HSSFRow currentRow; // 当前行未被使用过 if (sheet.getRow(rowNum) == null) { currentRow = sheet.createRow(rowNum); } else { currentRow = sheet.getRow(rowNum); } if (currentRow.getCell(colNum) != null) { HSSFCell currentCell = currentRow.getCell(colNum); if (currentCell.getCellType() == HSSFCell.CELL_TYPE_STRING) { int length=0; try { if (currentCell != null && currentCell.getStringCellValue() != null) { length = currentCell.getStringCellValue().getBytes().length; } }catch (Exception e){ } if (columnWidth < length) { columnWidth = length; } } } } try { if (colNum == 0) { sheet.setColumnWidth(colNum, (columnWidth - 2) * 256); } else { sheet.setColumnWidth(colNum, (columnWidth + 4) * 256); } }catch (Exception e){ } } return workbook; } /** * excel导出数据 * * @param title 显示的导出表的标题 * @param rowName 导出表的列名 * @param dataList 表的内容 * @return */ public static HSSFWorkbook export2(HSSFWorkbook workbook,String title, String[] rowName, List<Object[]> dataList) throws Exception { HSSFSheet sheet = workbook.getSheet(title); // 创建工作表 // 产生表格标题行 // sheet样式定义【getColumnTopStyle()/getStyle()均为自定义方法 - 在下面 - 可扩展】 HSSFCellStyle columnTopStyle = getColumnTopStyle(workbook);// 获取列头样式对象 HSSFCellStyle style = getStyle(workbook); // 单元格样式对象 sheet.addMergedRegion(new CellRangeAddress(0, 1, 0, (rowName.length - 1))); // 定义所需列数 int columnNum = rowName.length; int lastRowNum= sheet.getLastRowNum(); // 将查询出的数据设置到sheet对应的单元格中 for (int i = 0; i < dataList.size(); i++) { Object[] obj = dataList.get(i);// 遍历每个对象 HSSFRow row = sheet.createRow(i +lastRowNum+1);// 创建所需的行数 for (int j = 0; j < obj.length; j++) { HSSFCell cell = null; // 设置单元格的数据类型 cell = row.createCell(j, HSSFCell.CELL_TYPE_STRING); if (!"".equals(obj[j]) && obj[j] != null) { cell.setCellValue(obj[j].toString()); // 设置单元格的值 } cell.setCellStyle(style); // 设置单元格样式 } } // 让列宽随着导出的列长自动适应 for (int colNum = 0; colNum < columnNum; colNum++) { int columnWidth = sheet.getColumnWidth(colNum) / 256; for (int rowNum = 0; rowNum < sheet.getLastRowNum(); rowNum++) { HSSFRow currentRow; // 当前行未被使用过 if (sheet.getRow(rowNum) == null) { currentRow = sheet.createRow(rowNum); } else { currentRow = sheet.getRow(rowNum); } if (currentRow.getCell(colNum) != null) { HSSFCell currentCell = currentRow.getCell(colNum); if (currentCell.getCellType() == HSSFCell.CELL_TYPE_STRING) { int length=0; try { if (currentCell != null && currentCell.getStringCellValue() != null) { length = currentCell.getStringCellValue().getBytes().length; } }catch (Exception e){ } if (columnWidth < length) { columnWidth = length; } } } } try { if (colNum == 0) { sheet.setColumnWidth(colNum, (columnWidth - 2) * 256); } else { sheet.setColumnWidth(colNum, (columnWidth + 4) * 256); } }catch (Exception e){ } } return workbook; } /** * 列头单元格样式 * * @param workbook * @return */ public static HSSFCellStyle getColumnTopStyle(HSSFWorkbook workbook) { // 设置字体 HSSFFont font = workbook.createFont(); // 设置字体大小 font.setFontHeightInPoints((short) 11); // 字体加粗 font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD); // 设置字体名字 font.setFontName("Courier New"); // 设置样式; HSSFCellStyle style = workbook.createCellStyle(); // 设置底边框 style.setBorderBottom(HSSFCellStyle.BORDER_THIN); // 设置底边框颜色 style.setBottomBorderColor(HSSFColor.BLACK.index); // 设置左边框 style.setBorderLeft(HSSFCellStyle.BORDER_THIN); // 设置左边框颜色 style.setLeftBorderColor(HSSFColor.BLACK.index); // 设置右边框 style.setBorderRight(HSSFCellStyle.BORDER_THIN); // 设置右边框颜色 style.setRightBorderColor(HSSFColor.BLACK.index); // 设置顶边框 style.setBorderTop(HSSFCellStyle.BORDER_THIN); // 设置顶边框颜色 style.setTopBorderColor(HSSFColor.BLACK.index); // 在样式用应用设置的字体 style.setFont(font); // 设置自动换行 style.setWrapText(false); // 设置水平对齐的样式为居中对齐 style.setAlignment(HSSFCellStyle.ALIGN_CENTER); // 设置垂直对齐的样式为居中对齐 style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER); return style; } /** * 列数据信息单元格样式 * * @param workbook * @return */ public static HSSFCellStyle getStyle(HSSFWorkbook workbook) { // 设置字体 HSSFFont font = workbook.createFont(); // 设置字体大小 // font.setFontHeightInPoints((short)10); // 字体加粗 // font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD); // 设置字体名字 font.setFontName("Courier New"); // 设置样式; HSSFCellStyle style = workbook.createCellStyle(); // 设置底边框 style.setBorderBottom(HSSFCellStyle.BORDER_THIN); // 设置底边框颜色 style.setBottomBorderColor(HSSFColor.BLACK.index); // 设置左边框 style.setBorderLeft(HSSFCellStyle.BORDER_THIN); // 设置左边框颜色 style.setLeftBorderColor(HSSFColor.BLACK.index); // 设置右边框 style.setBorderRight(HSSFCellStyle.BORDER_THIN); // 设置右边框颜色 style.setRightBorderColor(HSSFColor.BLACK.index); // 设置顶边框 style.setBorderTop(HSSFCellStyle.BORDER_THIN); // 设置顶边框颜色 style.setTopBorderColor(HSSFColor.BLACK.index); // 在样式用应用设置的字体 style.setFont(font); // 设置自动换行 style.setWrapText(false); // 设置水平对齐的样式为居中对齐 style.setAlignment(HSSFCellStyle.ALIGN_CENTER); // 设置垂直对齐的样式为居中对齐 style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER); return style; } }
效果:
我的个人首页http://www.songaw.com