1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > list的add方法 foreach循环添加map---List.add(map)(通过一个java爬虫案例说明)

list的add方法 foreach循环添加map---List.add(map)(通过一个java爬虫案例说明)

时间:2020-10-28 02:36:29

相关推荐

list的add方法  foreach循环添加map---List.add(map)(通过一个java爬虫案例说明)

案例:一个java爬虫程序

1.案例说明

做了一个爬取某程的旅游网站的java程序,程序主要爬取安庆酒店的某些相关信息。

材料准备:jsoup-1.8.1.jar(需要此架包的联系博主,有任何问题欢迎随时咨询

直接上代码:

package util;import java.io.BufferedReader;import java.io.InputStreamReader;import .URL;import .URLConnection;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import org.jsoup.Jsoup;import org.jsoup.nodes.Document;import org.jsoup.nodes.Element;import org.jsoup.select.Elements;public class CopyOfDataDownUtil {/*** * @param url* @param enconding* @return*/public static String getHtmlResourceByUrl(String url,String enconding){StringBuffer buffer=new StringBuffer();InputStreamReader isr=null;try {//建立网络链接URL urlOb=new URL(url);//打开网络链接URLConnection uc=urlOb.openConnection();//建立文件输入流isr=new InputStreamReader(uc.getInputStream(),enconding);//缓冲BufferedReader reader=new BufferedReader(isr);//建立临时文件String line=null;//开始读取源代码while(((line=reader.readLine())!=null)){//将临时文件保存到StringBufferbuffer.append(line+"\n");}} catch (Exception e) {e.printStackTrace();}finally {//防止空指针if(isr!=null)try {isr.close();} catch (Exception e) {e.printStackTrace();}} return buffer.toString();}//解析源代码 获取相应的数据public static List<HashMap<String,String>> getHotelInfo(String url,String encoding){//根据网址获取网址源代码String html=getHtmlResourceByUrl(url, encoding);//解析源代码Document document=Jsoup.parse(html);//获取hotel_list 盒子里面的容器Element element=document.getElementById("hotel_list");//拿到每一个酒店Elements elements=element.getElementsByClass("searchresult_info");List<HashMap<String, String>> maps=new ArrayList<HashMap<String,String>>();//拿到每一个酒店的名称,图片 描述 遍历for (Element el : elements) {HashMap<String, String> map=new HashMap<String, String>();//获取酒店的图片String imgSrc=el.getElementsByTag("img").attr("src");//获取酒店的描述String content=el.getElementsByClass("searchresult_htladdress").text();//获取酒店的名称String title=el.getElementsByTag("img").attr("alt");map.put("imgSrc", imgSrc);map.put("content", content);map.put("title", title);maps.add(map);}return maps;}public static void main(String[] args) {//得到一个list集合List<HashMap<String, String>>html=getHotelInfo("/hotel/anqing177#ctm_ref=ctr_hp_sb_lst", "utf-8");for (HashMap<String, String> hashMap : html) {String img=hashMap.get("imgSrc");String content=hashMap.get("content");String title=hashMap.get("title");System.out.println("酒店名称=="+title);System.out.println("酒店图片=="+img);System.out.println("酒店描述=="+content);System.out.println("==================");}}}

爬取结果展示:

酒店名称==安庆南翔邦臣大酒店酒店图片==//dimg13.c-/images/fd/hotel/g4/M00/4D/55/CggYHFZtNGOAcgEYAD_r23Wd2JU142_R_130_130.jpg酒店描述==宜秀区迎宾路2号,客运中心斜对面。 【 火车站区域】==================酒店名称==安庆国际大酒店酒店图片==//dimg12.c-/images/fd/hotel/g3/M0A/1F/C9/CggYG1YDNNCAGAPfAAMJyLEJA5I525_R_130_130.jpg酒店描述==大观区集贤北路2号,与菱湖北路交叉口。 【 火车站区域 经济开发区】==================酒店名称==安庆迎宾馆酒店图片==//dimg10.c-/images/hotel/12000/11647/2badfa77a5b54bbb830796843baf61e9_R_130_130.jpg酒店描述==迎江区同安路2号,近盛唐湾路。 【 火车站区域】==================酒店名称==安庆唯美·艾伦艺术酒店酒店图片==//dimg12.c-/images/200p0c00000063u5bC82A_R_130_130.jpg酒店描述==大观区集贤南路163号,近市府路。 【 市中心区域】==================酒店名称==7+1商务酒店(安庆沿江路店)酒店图片==//dimg10.c-/images/hotel/62000/61889/99e6cc62ed894c1e8f9f768e3ae04744_R_130_130.jpg酒店描述==迎江区沿江中路59号(三号码头),近龙山路。 【 市中心区域 经济开发区】==================酒店名称==如家快捷酒店(安庆迎江寺华中西路店)酒店图片==//dimg13.c-/images/200c0e0000007866w926B_R_130_130.jpg酒店描述==迎江区华中西路413号,近湖心南路。 【 市中心区域】==================酒店名称==安庆天域时代酒店酒店图片==//dimg13.c-/images/fd/hotel/g5/M04/1D/AF/CggYsFcPCziAaPi_AAFdyLV02mE016_R_130_130.jpg酒店描述==宜秀区中兴大道146号,近雷池路。 【 火车站区域】==================酒店名称==安庆温州国际大酒店酒店图片==//dimg11.c-/images/fd/hotel/g3/M08/68/C0/CggYGVYIQmmAIxGbABsXaFPnGhg218_R_130_130.jpg酒店描述==宜秀区元山路光彩四期四号综合楼4号楼,近龙眠山南路。 【 火车站区域】==================酒店名称==安庆天域花园酒店酒店图片==//dimg12.c-/images/hotel/122000/121831/19698142b05f464cabb92f86b5116b94_R_130_130.jpg酒店描述==迎江区龙眠山路158号,龙眠山路和振风大道交叉口。 【 东部新城】==================酒店名称==安庆尊悦酒店酒店图片==//dimg12.c-/images/hotel/66000/65569/64e0aaae605246bba5e152a42c39dcff_R_130_130.jpg酒店描述==迎江区人民路529号,市立医院旁。 【 市中心区域】==================酒店名称==安庆五千年文博园皖府国际大酒店酒店图片==//dimg12.c-/images/050000000rvv4FC7E_R_130_130.jpg酒店描述==高速路口前方500米(近人民东路)==================酒店名称==安庆英德利大酒店酒店图片==//dimg10.c-/images/fd/hotel/g3/M02/D3/8F/CggYGVZD8reAUr4VAAG1cJ1n_yY131_R_130_130.jpg酒店描述==宜秀区中兴大道122号,近余店路。 【 火车站区域】==================酒店名称==锦江之星(安庆人民路步行街店)酒店图片==//dimg11.c-/images/fd/hotel/g5/M0B/C5/53/CggYr1cz1FSANdsfAAVBOvwCOF4893_R_130_130.jpg酒店描述==迎江区人民路563号(肯德基楼上),江边外滩公园旁。 【 市中心区域】==================酒店名称==安庆东驰假日酒店酒店图片==//dimg10.c-/images/hotel/750000/749621/03da3ccb2f514557ac1c7bbfd79dd6cd_R_130_130.jpg酒店描述==宜秀区湖心北路107号,近山城花园。 【 火车站区域】==================酒店名称==安庆光彩假日大酒店酒店图片==//dimg10.c-/images/050000000ioy1F5D9_R_130_130.jpg酒店描述==宜秀区龙眠山南路与天柱山路交叉口,近客运中心站向南300米。 【 火车站区域】==================酒店名称==安庆双龙假日大酒店酒店图片==//dimg10.c-/images/hotel/100000/99590/5DA8FA64-DD6F-4DE6-BE19-6EF03496CC4F_R_130_130.jpg酒店描述==宜秀区开发区迎宾路1号,光彩大市场西大门对面。 【 火车站区域】==================酒店名称==安庆君怡精品酒店酒店图片==//dimg10.c-/images/fd/hotel/g3/M02/FB/00/CggYG1YXDXSAdblFAAF1pAI1G80650_R_130_130.jpg酒店描述==迎江区菱湖南路315号(安庆二中隔壁),安师院老校区斜对面,近宜城路。 【 市中心区域】==================酒店名称==安庆速8酒店(宜城路店)酒店图片==//dimg13.c-/images/200q0f0000007lyk4A5AF_R_130_130.jpg酒店描述==迎江区宜城路22号,汽车南站旁。 【 市中心区域】==================酒店名称==安庆元素酒店酒店图片==//dimg12.c-/images/hotel/108000/107691/14840d66a3de486c907691c8ed24d8ed_R_130_130.jpg酒店描述==迎江区人民路408号,市中心繁华路段,与建设路交叉口,步行街边。 【 市中心区域】==================酒店名称==喆啡酒店(安庆人民路步行街店)酒店图片==//dimg10.c-/images/200i050000000ilrm35B0_R_130_130.jpg酒店描述==迎江区人民路441号,近湖心南路。 【 市中心区域】==================酒店名称==安庆独秀国际大酒店酒店图片==//dimg11.c-/images/20010g000000865f601E6_R_130_130.jpg酒店描述==怀宁河滨路91号==================酒店名称==7天连锁酒店(安庆龙山路步行街店)酒店图片==//dimg12.c-/images/fd/hotel/g1/M01/D0/E9/CghzfVT9pKmAXUnqAAJ-ksYQb0Y132_R_130_130.jpg酒店描述==大观区龙山路129号,近孝肃路。 【 市中心区域】==================酒店名称==莫泰168(安庆菱湖南路莲湖公园店)酒店图片==//dimg12.c-/images/fd/hotel/g1/M03/0D/27/CghzflW7kSqATdy5AAM4TIUF_eM612_R_130_130.jpg酒店描述==迎江区菱湖南路219号,安庆市青少年宫隔壁。 【 市中心区域】==================酒店名称==安庆德克精品客房酒店图片==//dimg10.c-/images/t1/hotel/1018000/1017970/c866dc0badc846f7b0aa7214eb49d937_R_130_130.jpg酒店描述==大观区集贤南路2号图书城6-8,近中国农业银行。 【 市中心区域 经济开发区】==================酒店名称==安庆黄梅山庄酒店图片==//dimg12.c-/images/hotel/85000/84714/F385CC1E57A84010855E07F7D4FAE4FC_R_130_130.Jpg酒店描述==迎江区湖心中路9号,菱湖公园内。 【 市中心区域】==================

总结:最终的结果是好的,爬取成功。不过中间也遇到了很多大大小小的问题。下面会一一列举分析,有不到位的地方,欢迎批评。

2.问题分析(以下为问题出现的次序,第三个是重点)

2.1空指针问题

1.问题描述

起初刚把程序写完之后,一运行报了一个空指针异常。

2.问题分析

这个异常报在下面这行代码:

//错误写法HashMap<String, String> map=null;

大家知道问题是什么吗?报空指针异常的原因是定义的map没有初始化,应该改为下面这样:

//正确写法HashMap<String, String> map=new HashMap<String, String>();

3.问题总结

总结:map定义的时候必须正确初始化,因为集合不光要实例化,还要指定存放的数据的类型。

2.2爬取内容为空问题

1.问题描述

解决完了空指针异常再次运行程序出现了新问题:爬取的内容为空。

2.问题分析

爬取到的内容为空值。为什么会这样呢?看看代码感觉写的没问题呀!(这是程序员的第一大错觉)然后我就开始debug。发现在getHotelInfo方法中遍历每一个酒店的时候,取酒店图片,酒店描述,酒店名称的时候,这些变量的值都有,为什么到main方法中maps的值就为空了呢?代码如下:

//解析源代码 获取相应的数据public static List<HashMap<String,String>> getHotelInfo(String url,String encoding){//根据网址获取网址源代码String html=getHtmlResourceByUrl(url, encoding);//解析源代码Document document=Jsoup.parse(html);//获取hotel_list 盒子里面的容器Element element=document.getElementById("hotel_list");//拿到每一个酒店Elements elements=element.getElementsByClass("searchresult_info");List<HashMap<String, String>> maps=new ArrayList<HashMap<String,String>>();//拿到每一个酒店的名称,图片 描述 遍历//程序运行到这时里面的变量imgSrc content title map maps都有值for (Element el : elements) {HashMap<String, String> map=new HashMap<String, String>();//获取酒店的图片String imgSrc=el.getElementsByTag("img").attr("src");//获取酒店的描述String content=el.getElementsByClass("searchresult_htladdress").text();//获取酒店的名称String title=el.getElementsByTag("img").attr("alt");map.put("imgSrc", imgSrc);map.put("content", content);map.put("title", title);maps.add(map);}//运行到这时,maps为空导致main方法的html变量的值为空return maps;}//main方法public static void main(String[] args) {//得到一个list集合List<HashMap<String, String>> html=getHotelInfo("/hotel/anqing177#ctm_ref=ctr_hp_sb_lst", "utf-8");

看了好久的代码,也debug了好久,都没有发现有问题,我就纳闷了,这种时候是程序员最痛苦的时候,不过也是最增长经验时候。最后我看了看网页的源代码发现是我把div的class属性值给写错了。。。低级失误

//拿到每一个酒店//酒店的class属性值(这是后来修改过的)Elements elements=element.getElementsByClass("searchresult_info");

3.问题总结

总结:这种失误是很低级,为了避免这种失误一些关键的地方不要手敲,此时复制粘贴是最好的防错办法。

2.3list中添加map时前面的老值被新值覆盖

1.问题描述

改为上一个错误之后,运行结果也不是空值了,但是新的问题又来了:所以的酒店名称,图片,描述都是同一个。

2.问题分析

这是怎么回事呢?第一感觉是新值把老值给覆盖了。后来证明我的第一感觉是对的。foreach循环添加map—maps.add(map)的时候,由于没有每次都new map,导致每次foreeach都是把新值赋给了原来的引用地址,也就是说内存中是一个map,每次循环都只是修改了这个map的属性值,但是maps的map数量是正确的,只是这些map都是同一个map,所以所有的酒店信息都是一样的,但是酒店数量是正确的。

错误代码:(正确写法在下面)

//new list对象List<HashMap<String, String>> maps=new ArrayList<HashMap<String,String>>();//new 一个map对象//错误做法:这样内存中就只有一个map对象// 因为此时在foreach中一直修改的是同一个对象,每次循环都要创建对象HashMap<String, String> map=new HashMap<String, String>();//拿到每一个酒店的名称,图片 描述 遍历for (Element el : elements) {//获取酒店的图片String imgSrc=el.getElementsByTag("img").attr("src");//获取酒店的描述String content=el.getElementsByClass("searchresult_htladdress").text();//获取酒店的名称String title=el.getElementsByTag("img").attr("alt");map.put("imgSrc", imgSrc);map.put("content", content);map.put("title", title);maps.add(map);}

正确代码:

//new list对象List<HashMap<String, String>> maps=new ArrayList<HashMap<String,String>>();//拿到每一个酒店的名称,图片 描述 遍历for (Element el : elements) {//new 一个map对象//正确做法:在每一次循环中重新new一个map对象,这样内存中的值就不会存在老值覆盖新值的问题// 因为此时内存中就不是一直修改同一个对象,而是每次都有一个新的对象HashMap<String, String> map=new HashMap<String, String>();//获取酒店的图片String imgSrc=el.getElementsByTag("img").attr("src");//获取酒店的描述String content=el.getElementsByClass("searchresult_htladdress").text();//获取酒店的名称String title=el.getElementsByTag("img").attr("alt");map.put("imgSrc", imgSrc);map.put("content", content);map.put("title", title);maps.add(map);}

3.问题总结

总结:list.add加入了map的内存地址,不new的话会在list加入多条数据,同一个内存地址,就会导致所以的数据的值都是一样的,解决办法:每次创建一个新的对象

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。