Java如何解析html中的内容并保存到数据库
最近接到一个任务,需要爬取五级行政区划的所有数据,以及需要抓取的网站爬取了:行政区划-行政区划代码查询发现这个网站并不是通过接口请求的,直接返回了HTML代码,于是就看了一下Java是如何解析HTML中的内容的。
我选择使用jsoup来读取和解析html。我需要添加以下依赖项:
依赖项groupIdorg.jsoup/groupIdartifactIdjsoup/artifactIdversion1.8.3/version/dependency
jsoup是一个JavaHTML解析器,可以直接解析URL地址和HTML文本内容。它提供了一个非常省力的API,可以通过DOM、CSS和类似jquery的操作方法来检索和操作数据。它是在MIT许可下发布的。
jsoup的主要功能如下:
1.从URL、文件或字符串中解析HTML;
2.使用DOM或CSS选择器查找和检索数据;
3、操作HTML元素、属性、文本;
示例代码:
//获取htmlDocument的document对象doc=Jsoup.parse('');//获取页面下id='content'的标签Elementcontent=doc.getElementById('content');//获取页面下a标签的Elements链接=content.getElementsByTag('a');for(Elementlink:links){//获取a标签下href的属性值StringlinkHref=link.attr('href');//获取a标签下的文本内容StringlinkText=link.text();}
Elements对象提供了一系列类似DOM的方法来查找元素、提取和处理其中的数据。详情如下:
1.查找元素
getElementById(字符串ID)
getElementsByTag(字符串标签)
getElementsByClass(字符串类名)
getElementsByAttribute(Stringkey)
元素兄弟:siblingElements()、firstElementSibling()、lastElementSibling();nextElementSibling()、previousElementSibling()
Graph:父,子,子
2.元素数据
attr(Stringkey)获取属性
attr(Stringkey,Stringvalue)设置属性
attribute()获取所有属性
id()、className()和classNames()
text()获取文本内容
text(Stringvalue)设置文本内容
html()进入元素内部
HTMLhtml设置元素内的HTML内容
externalHtml()获取元素外部的HTML内容
data()获取数据内容
tag()和tagName()
3.操作HTML和文本
追加,追加
附加文本,附加文本
appendElement(字符串标签名),appendElement(字符串标签名)html(字符串值)
直接输入代码:
测试.java:
@Slf4j@SpringBootTestclass测试{@ResourceprivatePositionServicepositionService;/***爬取省市网站*/@Testpublicvoidtest2()throwsInterruptedException{//总共有五个级别for(inti=0;i5;i++){if(i==0){ListPositionEntitypositionEntities=PositionUtils.reqPosition(PositionUtils.URL_HEAD);savePosition(positionEntities,null,i);继续;ListPosition位置=positionService.findListByLevel(i);for(PositionparentPosition:个位置){ListPositionEntitypositionEntities=PositionUtils.reqPosition(String.format('%s%s%s',PositionUtils.URL_HEAD,ParentPosition.getSn(),PositionUtils.URL_TAIL));savePosition(positionEntities,parentPosition,i);/***错误地址信息*/privatevoidsavePosition(ListPositionEntitypositionEntities,PositionparentPosition,inti){for(PositionEntityEntity:positionEntities){Positionposition=newPosition();}position.setSn(entity.getCode());position.setFullInitials(PinyinUtils.strFirst2Pinyin((parentPosition!=null?parentPosition.getFullName():'')+entity.getName()));position.setFullName((parentPosition!=null?parentPosition.getFullName():'')+entity.getName());位置.setLevel(i+1);position.setName(entity.getName());位置.setOrderNumber(0);position.setPsn(parentPosition!=null?parentPosition.getSn():0L);长计数=positionService.countBySn(position.getSn());if(count==0){positionService.savePosition(position);}}}}
PositionService.java:
公共接口PositionService{voidsavePosition(Position位置);长countBySn(长sn);ListPositionfindListByLevel(整数级别);}
PositionServiceImpl.java:
@ServicepublicclassPositionServiceImpl扩展ServiceImplPositionMapper,Position实现PositionService{@OverridepublicvoidsavePosition(Positionposition){baseMapper.insert(position);}}@OverridepubliclongcountBySn(Longsn){returnbaseMapper.selectCount(newQueryWrapperPosition().lambda().eq(Position:getSn,sn));}@OverridepublicListPositionfindListByLevel(Integerlevel){returnbaseMapper.selectList(newQueryWrapperPosition().lambda().eq(Position:getLevel,level));}}
位置映射器.java:
@Repositorypublic接口PositionMapper扩展BaseMapperPosition{}
位置.java:
@Data@TableName('position')@EqualsAndHashCode()publicclassPosition实现Serialized{@TableId(type=IdType.AUTO)privateIntegerid;/***编码*/privateLongsn;/***高级地址编码*/privateLongpsn;/***名称*/privateString名称;/***缩写*/privateStringShortName;/***等级*/privateIntegerlevel;/***区号*/privateStringcode;/***邮政编码*/privateStringzip;/***拼音*/privateString拼写;/***拼音首字母*/privateStringpellFirst;/***完整地址名称*/privateStringfullName;/***地址全名拼音首字母*/privateStringfullInitials;/***排序*/privateIntegerorderNumber;}
位置映射器.xml:
?xml版本='1.0'编码='UTF-8'?DOCTYPE映射器PUBLIC'-//mybatis.org//DTDMapper3.0//EN'''映射器命名空间='com.wkf.workrecord.dao.PositionMapper'/mapper
PositionUtils.java:
公共类PositionUtils{公共最终静态字符串URL_HEAD='';publicfinalstaticStringURL_TAIL='__xingzhengquhua/';公共静态ListPositionEntityreqPosition(Stringurl)抛出InterruptedException{StringhtmlStr=HttpUtils.getRequest(url);//将字符串解析为Document对象Documentdoc=Jsoup.parse(htmlStr);//获取body元素并获取class='fc'的table元素Elementstable=doc.body().getElementsByAttributeValue('bgcolor','#C5D5C5');//获取tbody元素Elementschildren;孩子=表.first().children();//获取tr元素集合Elementstr=Children.get(0).getElementsByTag('tr');ListPositionEntity结果=newArrayList();//遍历tr元素,得到td元素,并打印for(inti=3;itr.size();i++){Elemente1=tr.get(i);元素td=e1。getElementsByTag('td');if(td.size()2){中断;字符串名称=td.get(0).getElementsByTag('td').first().getElementsByTag('a').text();字符串代码=td.get(1).getElementsByTag('td').first().getElementsByTag('a').text();if(CheckUtils.isEmpty(name)||CheckUtils.isEmpty(code)){继续;}result.add(newPositionEntity(name,Long.parseLong(code)));}//防止ip被阻塞Thread.sleep(10000);返回结果;}}
PinyinUtils.java:
publicclassPinyinUtils{privatefinalstaticHanyuPinyinOutputFormatformat=newHanyuPinyinOutputFormat();static{format.setCaseType(HanyuPinyinCaseType.LOWERCASE);format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);format.setVCharType(HanyuPinyinVCharType.WITH_V);}/***字符字符串转拼音**@paramstr*中文字符串*@paramfill*分隔符*@return返回中文拼音字符串*/publicstaticStringstr2Pinyin(Stringstr,Stringfill){if(null==str){returnnull;}}尝试{StringBuildersb=newStringBuilder();if(fill==null)fill='';booleanisCn=true;for(inti=0;istr.length();i++){charc=str.charAt(i);if(i0isCn){sb.append(fill);}if(c==''){sb.append(fill);}//1.判断c是否为中文if(c='\u4e00'c='\u9fa5'){isCn=true;String[]piyins=PinyinHelper.toHanyuPinyinStringArray(c,format);if(null==piyins||0=piyins.length){继续;}sb.append(piyins[0]);}else{//不是中文if(c='A'c='Z'){sb.append((char)(c+32));}else{sb.append(c);}isCn=false;}}returnsb.toString();}catch(BadHanyuPinyinOutputFormatCombinatione){e.printStackTrace();}returnnull;}/***拼音首字母**@paramstr*中文字符串*@return中文字符串的拼音首字母*/publicstaticStringstrFirst2Pinyin(Stringstr){if(null==str){returnnull;}try{StringBuildersb=newStringBuilder();for(inti=0;istr.length();i++){charc=str.charAt(i);//1.判断c是否为中文if(c='\u4e00'c='\u9fa5'){String[]piyins=PinyinHelper.toHanyuPinyinStringArray(c,format);if(null==piyins||0=piyins.length){继续;}sb.append(piyins[0].charAt(0));}else{//非中文if(c='A'c='Z'){sb.append((char)(c+32));}else{sb.append(c);}}}returnsb.toString();}catch(BadHanyuPinyinOutputFormatCombinatione){e.printStackTrace();}返回null;}}
watch和compute的区别前言watch和compute是vue实例对象中两个重要的属性。watch是一个监控属性,用于监控vue实例对象上的属性和方法的…
Vue中组件间通信的六大方法-总结方式一:props/$emit父组件向子组件传值通过一个例子,讲解父组件如何向子组件传值:如何获取父组件App.vue中的数据…
win11中如何删除已连接的蓝牙设备?win11系统连接的蓝牙设备有很多。其中一些没有使用,我想删除它们。如何删除蓝牙?我们来看看Win11中如何删除蓝牙设备.…
最近有朋友问我如何在Linux下设置交换文件。今天给大家带来Linux下设置交换文件的方法。希望对大家有所帮助。有需要的朋友可以去看一下.17-04-161.创…
vue3+vite项目下按需引入vant,报错无法解决导入解决方案在vue3+vite项目下按需引入vant报错Failedtoresolveimport解决方…
2024-05-17 10:36:43
2024-05-17 10:12:02
2024-05-17 09:42:02
2024-05-17 09:25:52
2024-05-17 09:12:12
大家好,今天小编关注到一个比较有意思的话题,就是关于电脑制版哪里学的问题,于是小…
大家好,今天小编关注到一个比较有意思的话题,就是关于洛阳技能培训机构烘焙的问题,…