1. คำนำ
ฉันเคยพบปัญหาในที่ทำงานเมื่อเร็ว ๆ นี้ มีงานที่กำหนดเวลาในแบ็กเอนด์ ฉันต้องใช้ Java เพื่อตัดสินวันหยุดตามกฎหมายวันหยุดสุดสัปดาห์วันหยุดงาน ฯลฯ ทุกวัน ในความเป็นจริงมันเป็นไปไม่ได้ที่จะตัดสินวันหยุดตามกฎหมายของจีนผ่านตรรกะเพียงอย่างเดียวเพราะวันหยุดในประเทศอาจแตกต่างกันทุกปีและถูกกำหนดโดยเทียม
ดังนั้นคุณสามารถพึ่งพาวิธีอื่นเท่านั้นและยิ่งคุณคิดได้ว่ามีความน่าเชื่อถือมากขึ้นดังต่อไปนี้:
1. อินเทอร์เฟซเครือข่าย: ผู้ให้บริการข้อมูลบางรายจะให้บริการไม่ว่าจะเป็นค่าใช้จ่ายหรือสำหรับขีด จำกัด จำนวนครั้ง ฯลฯ เอฟเฟกต์ไม่เหมาะและความสามารถในการควบคุมไม่ดี ฉันไม่เคยลองเช่น:
https://www.juhe.cn/docs/api/id/177/aid/601
หรือ
http://apistore.baidu.com/apiworks/serviceDetail/1116.html
2. วิเคราะห์ข้อมูลหน้าเว็บออนไลน์และรับสถานการณ์วันหยุด: พึ่งพาเว็บเพจเว็บไซต์ที่แยกวิเคราะห์เป็นอย่างมากดังนั้นเมื่อเลือกเว็บไซต์คุณควรพบสิ่งที่น่าเชื่อถือกว่าเล็กน้อย
3. ตามกฎระเบียบระดับชาติเกี่ยวกับวันหยุดตามกฎหมายให้เข้าสู่ระบบทุกปีหากลูกค้าไม่กลัวปัญหา ยังค่อนข้างเชื่อถือได้
การสาธิตนี้จะเลือกอันที่สองที่จะนำไปใช้
2. ใช้ htmlunit เพื่อวิเคราะห์ข้อมูลหน้าเว็บออนไลน์เพื่อรับสถานการณ์วันหยุด
ในตอนแรกฉันใช้ JSOUP เพื่อแยกวิเคราะห์หน้าเว็บ แต่เอฟเฟกต์ไม่เหมาะ หากหน้าเว็บถูกสร้างขึ้นแบบไดนามิกฉันพบปัญหาต่าง ๆ กับ JSOUP ดังนั้นฉันจึงเปลี่ยนเป็น htmlunit โดยทั่วไปแล้ว HTMLUNIT ยังคงทรงพลังมากสามารถจำลองการทำงานของเบราว์เซอร์และเป็นที่รู้จักกันในชื่อการใช้งาน Open Source ของเบราว์เซอร์ Java
ก่อนอื่นไปที่เว็บไซต์อย่างเป็นทางการเพื่อดาวน์โหลดแพ็คเกจ JAR ที่เกี่ยวข้องและอ่านเอกสารที่เกี่ยวข้อง:
http://htmlunit.sourceforge.net/
หน้าเว็บที่ฉันวิเคราะห์ที่นี่คือ 3.6 ล้านปฏิทินต่อเนื่อง:
http://hao.360.cn/rili/
อินเทอร์เฟซปฏิทินมีดังนี้:
รูปแบบ HTML ที่แยกวิเคราะห์มีดังนี้:
ขั้นตอนการใช้งาน:
1. โหลดหน้า;
2. ลูปเพื่อรอให้หน้าโหลด (อาจมีบางหน้าแบบไดนามิกที่สร้างขึ้นโดยใช้ JavaScript);
3. พาร์ทเนื้อหา HTML ตามรูปแบบหน้าเว็บและแยกข้อมูลคีย์และเก็บไว้ในวัตถุที่ห่อหุ้ม
บันทึก:
1. ความยากลำบากอยู่ในการพิจารณาว่าจะใช้วันหยุดพักผ่อนและประเภทวันหยุด เนื่องจากหน้าต้นฉบับไม่ได้ระบุประเภทของวันหยุดสำหรับแต่ละวันตรรกะที่นี่จะต้องดำเนินการด้วยตัวเอง โปรดดูรหัสสำหรับรายละเอียด
2. เหตุผลสำหรับตัวแปรล่าสุด VocationName คือการป้องกันสถานการณ์ต่อไปนี้ (ความน่าจะเป็นของสถานการณ์นี้ต่ำมาก; PS: วิธีการจะต้องเรียกวันละครั้งก่อนที่ตัวแปรจะมีผล):
การใช้รหัส:
กำหนดชั้นเรียนวันที่จีน:
แพ็คเกจ com.pichen.tools.getDate; นำเข้า java.util.date; ชั้นเรียนสาธารณะ Chinadate {/*** เวลา Gregorian*/วันที่ส่วนตัว solardate;/*** วันจันทรคติ*/พยางค์ส่วนตัว lunar;/*** วันเกรกอเรียน "Non-non-raMation";/*** ไม่ว่าจะเป็นคลาส*/บูลีนส่วนตัว isworkflag = false; บูลีนส่วนตัว issaturday = false; บูลีนส่วนตัว issunday = false;/*** @return the solardate*/วันที่สาธารณะ getSolardate () {return solardate;}/*** @param = solardate;}/*** @return ดวงจันทร์*/สตริงสาธารณะ getLunar () {return lunar;}/*** @param lunar จันทรุเพื่อตั้ง*/โมฆะสาธารณะ setlunar (String lunar) {this.lunar = lunar;}/*** @return the solar โมฆะ setsolar (สตริงแสงอาทิตย์) {this.solar = solar;}/*** @return isvacation*/public boolean isvacation () {return isvacation;}/*** @param isvacation isvacation เพื่อตั้งค่า*/void setvacation VacationName*/Public String getVacationName () {return dacationName;}/*** @param วันหยุดพักผ่อนชื่อวันหยุดที่จะตั้งค่า*/โมฆะสาธารณะ setVacationName (สตริงวันหยุดพักผ่อน) {วันหยุดพักผ่อน = วันหยุด;}/*** @return isworkflag isworkflag เพื่อตั้งค่า*/โมฆะสาธารณะ setworkflag (บูลีน isworkflag) {this.isworkflag = isworkflag;}/*** @return issaturday*/บูลีนสาธารณะ issaturday () {return issaturday;}/*** @param {this.issaturday = issaturday;}/*** @return issunday*/public boolean issunday () {return issunday;}/*** @param issunday วันที่จะตั้งค่า*/โมฆะสาธารณะ setsunday (boolean issunday) แยกวิเคราะห์หน้าเว็บและโทรสาธิตพิมพ์รายละเอียดของเดือนนี้และรายละเอียดของวัน:
แพ็คเกจ com.pichen.tools.getDate; นำเข้า java.io.ioException; นำเข้า java.net.malformedurlexception; นำเข้า java.text.dateformat; นำเข้า java.text.parseException; นำเข้า java.Text.simpledateFormat; com.gargoylesoftware.htmlunit.failinghttpstatuscodeException; นำเข้า com.gargoylesoftware.htmlunit.webclient; นำเข้า com.gargoylesoftware.htmlunit.html.domnodelist; com.gargoylesoftware.htmlunit.html.htmlpage; คลาสสาธารณะหลัก {สตริงคงที่ส่วนตัว vocationName = ""; สตริงสาธารณะ getVocationName (domnodelist <htmlelement> htmlements, วันที่สตริง) SimpledateFormat ("yyyy/mm/dd"); date paramdate = dateformat.parse (วันที่); ถ้า (วันที่ใหม่ (). getTime ()> = paramdate.getTime ()) {pasttimeflag = true;} // ขั้นตอนแรก // jugde i ++) {องค์ประกอบ htmlelement = htmlelements.get (i); ถ้า (element.getAttribute ("class"). indexof ("วันหยุด")! =-1) {boolean hitflag = false; string votename = "" สำหรับ (; i <htmlelements.size () htmlelements.get (i); string lidate = elementtmp.getattribute ("วันที่"); รายการ <htmlelement> Lunar = elementtmp.getElementSbyattribute ("Span", "class", "Lunar"); String lanartext = lunar.get (0). วันปี ";} อื่นถ้า (lanartext.equals (" อีฟปีใหม่ ") || lanartext.equals (" เทศกาลฤดูใบไม้ผลิ ")) {voationname =" เทศกาลฤดูใบไม้ผลิ ";} ถ้า (lanartext.equals (" qingming ")) {voationname =" เทศกาลฤดูใบไม้ผลิ " "เทศกาลฤดูใบไม้ผลิ";} อื่นถ้า (lanartext.equals ("เทศกาลเรือมังกร")) {voationname = "เทศกาลเรือมังกร";} อื่นถ้า (lanartext.equals ("เทศกาลกลางฤดูใบไม้ร่วง") {voationname = "เทศกาลแห่งชาติ day ";} if (lidate.equals (วันที่)) {hitflag = true;} ถ้า (elementtmp.getattribute (" คลาส "). indexof (" วันหยุด ") ==-1) {break;}} ถ้า (hitflag == true &&! ล้มเหลว (ไม่ค่อย) รับจากชื่อเสียงล่าสุด (rst.equals ("")) {system.out.println ("คำเตือน: ไม่สามารถรับชื่อเสียงจากหน้า html"); // คุณสามารถตัดสินได้โดยกฎง่าย ๆ main.latestVocationName = rst;} return rst;} รายการสาธารณะ <chinadate> getCurrentDateInfo () {webClient webClient = null; รายการ <Chinadate> datelist = null; ลอง {dateformat dateformat = new SimpleDateFormat ("yyyy/mm/dd"); WebClient (); htmlPage หน้า = webClient.getPage ("http://hao.360.cn/rili/"); // รอ (int k = 0; k <60; k ++) {ถ้า (! page.getElementById ("m-date"). astext () วินาทีรอให้หน้าโหลด ... บางครั้งหน้าอาจไม่ถูกดึงออกมาไม่เสถียร () //thread.sleep(8000); องค์ประกอบ: htmlelements) {chinadate chinadate = ใหม่ chinadate (); รายการ <htmlelement> lunar = element.getElementSbyAttribute ("span", "class", "Lunar"); รายการ <htmlelement> solar = element.getEntEmentByAttribute ("Div" "Solar"); chinadate.setlunar (lunar.get (0) .Astext ()); chinadate.setsolar (Solar.get (0) .Astext ()); chinadate.setsolardate (dateformat.parse (Element.getAtattribute (" วันที่ "))); ถ้า (element.getAttribute (" คลาส "). indexof (" วันหยุด ")! =-1) {chinadate.setVacation (จริง); chinadate.setVacationName (this.getVocationName (htmlements, element.getAttribute ("วันที่")));} ถ้า (element.getAttribute ("คลาส"). indexof ("วันหยุดสุดสัปดาห์")! =-1 && element.getAttribute ("คลาส"). indexof ("สุดท้าย") ==-1) {chinadate.setsaturday (true); วันหยุดสุดสัปดาห์ ")! =-1) {chinadate.setsunday (จริง);} ถ้า (element.getAttribute (" คลาส ") indexof (" work ")! =-1) {chinadate.setworkflag (จริง);} อื่น ๆ ถ้า (chinadate.issaturday () ) {chinadate.setworkflag (true);} else {chinadate.setworkflag (เท็จ);} datelist.add (chinadate);}} catch (ยกเว้น e) {e.printstacktrace (); system.out.println ( ในที่สุด {webClient.close ();} ส่งคืน datelist;} public chinadate public getTodayInfo () {list <Cinadate> datelist = this.getCurrentDateInfo (); dateformat dateformat = new SimpleDateFormat ("yyyy/mm/dd"); Datelist) {if (dateformat.format (date.getSolardate ()). เท่ากับ (dateformat.format (วันที่ใหม่ ()))) {วันที่คืน;}} ส่งคืน chinadate ใหม่ ();} โมฆะสาธารณะ datelist = new main (). getCurrentDateInfo (); chinadate วันนี้ = new main (). getTodayInfo (); dateformat dateformat = ใหม่ simpledateFormat ("yyyy/mm/dd"); system.out.println ("รายละเอียดของเดือนนี้:"); Datelist) {system.out.println (dateformat.format (date.getSolardate ()) + "" date.getVacationName ());} system.out.println ("-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- "+Today.getLunar ()); System.out.println (" ปฏิทิน Gregorian: "+วันนี้ getSolar ()); System.out.println (" ชื่อวันหยุด: "+วันนี้ getVacationName (); system.out.println (" วันเสาร์: " "+Today.issunday ()); System.out.println (" อยู่ในช่วงวันหยุด: "+วันนี้. isvacation ()); system.out.println (" เป็นวันทำงาน: "+วันนี้. เรียกใช้โปรแกรมและผลลัพธ์ถูกต้อง: