Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
注于Java領(lǐng)域優(yōu)質(zhì)技術(shù)號(hào),歡迎關(guān)注
作者:銀河1號(hào)
一個(gè)優(yōu)秀且經(jīng)驗(yàn)豐富的Java開(kāi)發(fā)人員的特點(diǎn)之一是對(duì)API的廣泛了解,包括JDK和第三方庫(kù)。我花了很多時(shí)間學(xué)習(xí)API,特別是在閱讀Effective Java 3rd Edition之后,Joshua Bloch建議如何使用現(xiàn)有的API進(jìn)行開(kāi)發(fā),而不是為常用的東西寫(xiě)新的代碼。
在本文中,我將分享一些Java開(kāi)發(fā)人員應(yīng)該熟悉的最有用和最重要的庫(kù)和API。但是,我沒(méi)有包含框架,例如Spring和Hibernate,因?yàn)樗鼈兎浅S忻揖哂刑囟üδ堋?/p>
總的來(lái)說(shuō),我在日常項(xiàng)目包含了有用的庫(kù),包括Log4j日志庫(kù),Jackson JSON解析庫(kù),以及JUnit和Mockito等單元測(cè)試API。如果需要在項(xiàng)目中使用,則在項(xiàng)目的classpath包含這些JAR,也可以使用Maven進(jìn)行依賴管理。
當(dāng)你使用Maven進(jìn)行依賴管理時(shí),它會(huì)自動(dòng)下載這些庫(kù),包括它們所依賴的庫(kù),稱為傳遞依賴。
例如,如果你下載Spring Framework,它還將下載Spring所依賴的所有其他JAR,例如Log4j。
你可能沒(méi)注意到,但有正確版本的JAR是一個(gè)令人頭疼的問(wèn)題。如果是錯(cuò)誤的JAR版本,那么你將遇到 ClassNotFoundException, NoClassDefFoundError或 UnsupportedClassVersionError。
這是我收集的一些有用的第三方庫(kù),Java開(kāi)發(fā)可以使用它們?cè)趹?yīng)用中來(lái)完成許多有用的功能。要使用這些庫(kù),Java開(kāi)發(fā)人員應(yīng)該熟悉它,這就是本文的重點(diǎn)。如果你覺(jué)得有用,你可以研究該庫(kù)并使用它。
日志庫(kù)非常常見(jiàn),因?yàn)樵诿總€(gè)項(xiàng)目中都需要它們。它們是服務(wù)器端應(yīng)用最重要的東西,因?yàn)槿罩局环旁诳梢钥吹綉?yīng)用程序當(dāng)前運(yùn)行時(shí)情況的地方。盡管JDK附帶了自己的日志庫(kù),但還有更好的替代方案,例如Log4j,SLF4j和LogBack。
Java開(kāi)發(fā)人員應(yīng)該熟悉日志庫(kù)的優(yōu)缺點(diǎn),并且知道 為什么使用SLF4j比普通Log4j更好。
在當(dāng)今的Web服務(wù)和物聯(lián)網(wǎng)領(lǐng)域,JSON已成為將信息從客戶端傳送到服務(wù)器的首選協(xié)議。他們已經(jīng)替換XML成為在獨(dú)立平臺(tái)間傳輸信息的最佳方式。
遺憾的是,JDK沒(méi)有JSON庫(kù)。但是,有許多優(yōu)秀的第三方庫(kù)允許你解析和創(chuàng)建JSON消息,如Jackson和Gson。
Java Web開(kāi)發(fā)人員應(yīng)該熟悉這些庫(kù)中的至少一個(gè)。如果你想了解有關(guān)Jackson和JSON的更多信息,我建議你看看 Udemy的課程JSON with the Java API。
單元測(cè)試是將普通開(kāi)發(fā)人員與優(yōu)秀開(kāi)發(fā)人員區(qū)分開(kāi)來(lái)的最重要的事情。程序員經(jīng)常有理由不寫(xiě)單元測(cè)試,但逃避寫(xiě)單元測(cè)試的最常見(jiàn)的借口是缺乏常用單元測(cè)試庫(kù)的經(jīng)驗(yàn)和知識(shí),包括JUnit,Mockito和PowerMock。
我在2018年有一個(gè)目標(biāo)就是提高我對(duì)單元測(cè)試和集成測(cè)試庫(kù)的了解,比如JUnit 5,Cucumber,Robot框架和一些其他的。
我還在Udemy注冊(cè)了 JUnit and Mockito Crash Course 。即使你了解JUnit和單元測(cè)試的基礎(chǔ)知識(shí),可能也希望更新并進(jìn)階自己的知識(shí)。
Java開(kāi)發(fā)人員可以使用幾個(gè)很好的通用第三方庫(kù),比如Apache Commons和Google Guava。我總是在我的項(xiàng)目中包含這些庫(kù),因?yàn)樗鼈兒?jiǎn)化了很多功能。
正如Joshua Bloch在Effective Java中所說(shuō)的那樣,重復(fù)造輪子是沒(méi)有意義的。我們應(yīng)該更偏向于使用久經(jīng)考驗(yàn)的庫(kù)而不是時(shí)不時(shí)自己來(lái)實(shí)現(xiàn)。
對(duì)Java開(kāi)發(fā)人員來(lái)說(shuō),熟悉Google Guava和Apache Commons庫(kù)是件好事。
我不喜歡JDK的一點(diǎn)是他們對(duì)HTTP支持的缺乏。雖然你可以使用java.net包中的類建立HTTP連接 ,但使用開(kāi)源的第三方庫(kù)(如Apache HttpClient和HttpCore)并不容易或不能無(wú)縫結(jié)合。
雖然JDK 9帶來(lái)了HTTP 2.0的支持和更好的HTTP支持,但我強(qiáng)烈建議所有Java開(kāi)發(fā)人員熟悉流行的HTTP客戶端庫(kù),包括HttpClient和HttpCore。
你還可以查看此文章What's New in Java 9 - Modules and More以了解有關(guān)JDK 9對(duì)HTTP 2支持的更多信息。
有許多XML解析庫(kù),包括Xerces,JAXB,JAXP,Dom4j和Xstream。Xerces2是Apache Xerces下一高性能版本,完全兼容的XML解析器。這個(gè)新版本的Xerces引入了Xerces Native Interface(XNI),這是一個(gè)完整的框架,用于構(gòu)建非常模塊化且易于編程的解析器組件和配置。
Apache Xerces2解析器是XNI的參考實(shí)現(xiàn),但是其他解析器組件,配置和解析器可以使用Xerces Native Interface編寫(xiě)。Dom4j是另一個(gè)適用于Java應(yīng)用程序的靈活XML框架。如果你想了解有關(guān)Java中XML解析的更多信息,建議你查看Udemy 上的 Java Web Services and XML 在線課程。
信不信由你 - 所有現(xiàn)實(shí)世界的應(yīng)用程序都必須以某種形式與Microsoft Office進(jìn)行交互。許多應(yīng)用程序需要提供在Excel中導(dǎo)出數(shù)據(jù)的功能,如果必須從Java應(yīng)用程序執(zhí)行相同操作,則需要Apache POI API。
這是一個(gè)非常豐富的庫(kù),允許你 從Java程序讀取和寫(xiě)入XLS文件。你可以看到該鏈接(http://www.java67.com/2014/09/how-to-read-write-xlsx-file-in-java-apache-poi-example.html),以獲取在核心Java應(yīng)用程序中讀取Excel文件的工作示例。
如果你正在編寫(xiě)生成代碼或與字節(jié)碼交互的框架,那么你需要一個(gè)字節(jié)碼庫(kù)。
它們?cè)试S你讀取和修改應(yīng)用程序生成的字節(jié)碼。Java世界中一些流行的字節(jié)碼庫(kù)是javassist和Cglib Nodep。
Javassist(Java programming assistant)使Java字節(jié)碼操作變得非常簡(jiǎn)單。它是一個(gè)用于在Java中編輯字節(jié)碼的類庫(kù)。ASM是另一個(gè)有用的字節(jié)碼編輯庫(kù)。如果你不熟悉字節(jié)碼,我建議你查看Introduction to Java Programmers以了解有關(guān)它的更多信息。
如果你正在從Java應(yīng)用程序與數(shù)據(jù)庫(kù)交互但不使用數(shù)據(jù)庫(kù)連接池庫(kù),那么你將丟失一些內(nèi)容。
由于在運(yùn)行時(shí)創(chuàng)建數(shù)據(jù)庫(kù)連接需要花費(fèi)時(shí)間并使請(qǐng)求處理速度變慢,因此始終建議使用數(shù)據(jù)庫(kù)連接庫(kù)。一些流行的是Commons Pool和DBCP。
在Web應(yīng)用程序中,它的Web服務(wù)器通常提供這些功能,但在核心Java應(yīng)用程序中,你需要將這些連接池庫(kù)包含在類路徑中以使用數(shù)據(jù)庫(kù)連接池。
如果你想了解有關(guān)JDBC和Web應(yīng)用程序中的連接池的更多信息,我建議你查看Udemy 中的JSP, Servlet, and JDBC for Beginners課程。
與日志記錄和數(shù)據(jù)庫(kù)連接類似,消息傳遞也是許多現(xiàn)實(shí)世界Java應(yīng)用程序的常見(jiàn)功能。
Java提供的JMS,Java Messaging Service不屬于JDK。對(duì)于此組件,你需要包含一個(gè)單獨(dú)的組件 jms.jar。
同樣,如果你正在使用第三方消息傳遞協(xié)議(如Tibco RV),則需要使用第三方JAR tibrv.jar 放在應(yīng)用程序類路徑中。
與Microsoft Excel類似,PDF庫(kù)是另一種普遍存在的格式。如果你需要在應(yīng)用程序中支持PDF功能,例如 導(dǎo)出數(shù)據(jù)到PDF文件,則可以使用iText和Apache FOP庫(kù)。
兩者都提供有用的PDF相關(guān)功能,但iText更豐富,更好。請(qǐng)參閱此處以了解有關(guān)iText的更多信息。
在Java 8之前,JDK的數(shù)據(jù)和時(shí)間庫(kù)有很多缺陷,因?yàn)樗鼈儾皇蔷€程安全的,不可變的,并且容易出錯(cuò)。許多Java開(kāi)發(fā)人員依靠JodaTime來(lái)實(shí)現(xiàn)他們的日期和時(shí)間要求。
從JDK 8開(kāi)始,沒(méi)有理由使用Joda,因?yàn)槟阍贘DK 8的新日期和時(shí)間API中獲得了所有功能,但如果你使用的是較舊的Java版本,那么JodaTime是一個(gè)值得學(xué)習(xí)的庫(kù)。
如果你想了解有關(guān)新的日期和時(shí)間API的更多信息,我建議你查看Udemy上的What's new in Java 8課程。它提供了Java 8所有重要功能的精彩概述,包括日期和時(shí)間API。
盡管JDK擁有豐富的集合庫(kù),但仍有一些第三方庫(kù)提供了更多選項(xiàng),例如Apache Commons集合,Goldman Sachs集合,Google集合和Trove。
Trove庫(kù)特別有用,因?yàn)樗鼮镴ava提供了高速的常規(guī)和原始集合。
FastUtil是另一個(gè)類似的API。它通過(guò)提供特定類型的映射,集合,列表和優(yōu)先級(jí)隊(duì)列來(lái)擴(kuò)展Java集合框架,較小的內(nèi)存占用,快速訪問(wèn)和插入; 它還提供大型(64位)數(shù)組,集和列表,以及用于二進(jìn)制和文本文件快速實(shí)用的I / O類。
javax.mail和Apache Commons Email都提供了一個(gè)用于從Java發(fā)送電子郵件的API 。它建立在JavaMail API的基礎(chǔ)之上,旨在簡(jiǎn)化它。
與JSON和XML類似,HMTL是我們?cè)S多人必須處理的另一種常見(jiàn)格式。值得慶幸的是,我們有JSoup,它極大地簡(jiǎn)化了在Java應(yīng)用程序中使用HTML的過(guò)程。
你不僅可以使用JSoup解析HTML,還可以創(chuàng)建HTML文檔
它提供了一個(gè)非常方便的API,用于提取和操作數(shù)據(jù),使用DOM,CSS和類似jquery的方法。JSoup實(shí)現(xiàn)了WHATWG HTML5規(guī)范,并將HTML解析到同一個(gè)DOM,就像現(xiàn)代瀏覽器一樣。
Apache Commons Codec軟件包包含各種格式的簡(jiǎn)單編碼器和解碼器,如Base64和Hexadecimal。
除了這些廣泛使用的編碼器和解碼器之外,編解碼器包還維護(hù)一組語(yǔ)音編碼實(shí)用程序。
我真的很喜歡像H2這樣的內(nèi)存數(shù)據(jù)庫(kù),你可以將它嵌入你的Java應(yīng)用程序中。它們非常適合測(cè)試SQL腳本和運(yùn)行需要數(shù)據(jù)庫(kù)的單元測(cè)試。但是,H2并不是唯一的DB,你也可以選擇Apache Derby和HSQL。
存在一些很好的JDBC擴(kuò)展庫(kù),可以使調(diào)試更容易,比如P6spy。
這是一個(gè)庫(kù),可以無(wú)縫地?cái)r截和記錄數(shù)據(jù)庫(kù)數(shù)據(jù),而無(wú)需對(duì)應(yīng)用程序進(jìn)行代碼更改。你可以使用它們來(lái)記錄SQL查詢及其計(jì)時(shí)。
例如,如果你在代碼中使用PreparedStatment和CallableStatement,則這些庫(kù)可以記錄一次完全調(diào)用的參數(shù)和執(zhí)行所花費(fèi)的時(shí)間。
如果你想了解有關(guān)JDBC的更多信息,可以查看JDBC for Beginners。
Google Protocol Buffers是一種以高效可擴(kuò)展的格式編碼結(jié)構(gòu)化數(shù)據(jù)的方法。它是Java序列化的更豐富,更好的替代品。我強(qiáng)烈建議有經(jīng)驗(yàn)的Java開(kāi)發(fā)人員學(xué)習(xí)Google Protobuf。你可以查看此文章以了解有關(guān)Google協(xié)議緩沖區(qū)的更多信息 。
一些有用的網(wǎng)絡(luò)庫(kù)是Netty和Apache MINA。如果你正在編寫(xiě)需要執(zhí)行底層網(wǎng)絡(luò)任務(wù)的應(yīng)用程序,請(qǐng)考慮使用這些庫(kù)。如果你想了解有關(guān)Java網(wǎng)絡(luò)編程的更多信息,請(qǐng)查看 Java Network Programming - TCP/IP Socket Programming。
這些就是對(duì)于每個(gè)Java開(kāi)發(fā)人員都應(yīng)該使用的一些有用的庫(kù)。Java的世界是浩瀚無(wú)窮的,你會(huì)發(fā)現(xiàn)數(shù)不勝數(shù)的庫(kù)用于做不同的事情。
如果你想用Java做任何事情,很可能你會(huì)找到一個(gè)如何實(shí)現(xiàn)的庫(kù)。與往常一樣,Google是你找到有用的Java庫(kù)的最好朋友,但你也可以查看Maven中央存儲(chǔ)庫(kù),找到適合你手頭任務(wù)的一些有用的庫(kù)。
點(diǎn)擊英文原文鏈接
html轉(zhuǎn)為pdf的組件有很多,但是還沒(méi)有哪一款能達(dá)到這個(gè)效果,其只要原因是wkhtmltopdf使用webkit網(wǎng)頁(yè)渲染引擎開(kāi)發(fā)的用來(lái)將 html轉(zhuǎn)成 pdf的工具,可以跟多種腳本語(yǔ)言進(jìn)行集成來(lái)轉(zhuǎn)換文檔。但是就使用簡(jiǎn)便性來(lái)說(shuō)還是itext等組件占據(jù)優(yōu)勢(shì),如果你要轉(zhuǎn)換格式有比較高的要求,那么wkhtmltopdf絕對(duì)是不二之選!
下載路徑
官網(wǎng)地址 wkhtmltopdf.org/
github地址 github.com/wkhtmltopdf…
使用方法
java調(diào)用demo
public class HtmlToPdfInterceptor extends Thread { private InputStream is; public HtmlToPdfInterceptor(InputStream is){ this.is = is; } public void run(){ try{ InputStreamReader isr = new InputStreamReader(is, "utf-8"); BufferedReader br = new BufferedReader(isr); String line = null; while ((line = br.readLine()) != null) { System.out.println(line.toString()); //輸出內(nèi)容 } }catch (IOException e){ e.printStackTrace(); } }}public class HtmlToPdf { //wkhtmltopdf在系統(tǒng)中的路徑 private static final String toPdfTool = "D:\wkhtmltopdf\bin\wkhtmltopdf.exe"; /** * html轉(zhuǎn)pdf * @param srcPath html路徑,可以是硬盤(pán)上的路徑,也可以是網(wǎng)絡(luò)路徑 * @param destPath pdf保存路徑 * @return 轉(zhuǎn)換成功返回true */ public static boolean convert(String srcPath, String destPath){ File file = new File(destPath); File parent = file.getParentFile(); //如果pdf保存路徑不存在,則創(chuàng)建路徑 if(!parent.exists()){ parent.mkdirs(); } StringBuilder cmd = new StringBuilder(); cmd.append(toPdfTool); cmd.append(" "); cmd.append(" --header-line");//頁(yè)眉下面的線 cmd.append(" --header-center 這里是頁(yè)眉這里是頁(yè)眉這里是頁(yè)眉這里是頁(yè)眉 ");//頁(yè)眉中間內(nèi)容 //cmd.append(" --margin-top 30mm ");//設(shè)置頁(yè)面上邊距 (default 10mm) cmd.append(" --header-spacing 10 ");//(設(shè)置頁(yè)眉和內(nèi)容的距離,默認(rèn)0) cmd.append(srcPath); cmd.append(" "); cmd.append(destPath); boolean result = true; try{ Process proc = Runtime.getRuntime().exec(cmd.toString()); HtmlToPdfInterceptor error = new HtmlToPdfInterceptor(proc.getErrorStream()); HtmlToPdfInterceptor output = new HtmlToPdfInterceptor(proc.getInputStream()); error.start(); output.start(); proc.waitFor(); }catch(Exception e){ result = false; e.printStackTrace(); } return result; } public static void main(String[] args) { HtmlToPdf.convert("https://my.oschina.net/papio/blog/835645", "d:/wkhtmltopdf.pdf"); }}復(fù)制代碼
wkhtmltopdf 參數(shù)詳解
wkhtmltopdf [OPTIONS]... <input file> [More input files] <output file>常規(guī)選項(xiàng) --allow <path> 允許加載從指定的文件夾中的文件或文件(可重復(fù)) --book* 設(shè)置一會(huì)打印一本書(shū)的時(shí)候,通常設(shè)置的選項(xiàng) --collate 打印多份副本時(shí)整理 --cookie <name> <value> 設(shè)置一個(gè)額外的cookie(可重復(fù)) --cookie-jar <path> 讀取和寫(xiě)入的Cookie,并在提供的cookie jar文件 --copies <number> 復(fù)印打印成pdf文件數(shù)(默認(rèn)為1) --cover* <url> 使用HTML文件作為封面。它會(huì)帶頁(yè)眉和頁(yè)腳的TOC之前插入 --custom-header <name> <value> 設(shè)置一個(gè)附加的HTTP頭(可重復(fù)) --debug-javascript 顯示的javascript調(diào)試輸出 --default-header* 添加一個(gè)缺省的頭部,與頁(yè)面的左邊的名稱,頁(yè)面數(shù)到右邊,例如: --header-left '[webpage]' --header-right '[page]/[toPage]' --header-line --disable-external-links* 禁止生成鏈接到遠(yuǎn)程網(wǎng)頁(yè) --disable-internal-links* 禁止使用本地鏈接 --disable-javascript 禁止讓網(wǎng)頁(yè)執(zhí)行JavaScript --disable-pdf-compression* 禁止在PDF對(duì)象使用無(wú)損壓縮 --disable-smart-shrinking* 禁止使用WebKit的智能戰(zhàn)略收縮,使像素/ DPI比沒(méi)有不變 --disallow-local-file-access 禁止允許轉(zhuǎn)換的本地文件讀取其他本地文件,除非explecitily允許用 --allow --dpi <dpi> 顯式更改DPI(這對(duì)基于X11的系統(tǒng)沒(méi)有任何影響) --enable-plugins 啟用已安裝的插件(如Flash --encoding <encoding> 設(shè)置默認(rèn)的文字編碼 --extended-help 顯示更廣泛的幫助,詳細(xì)介紹了不常見(jiàn)的命令開(kāi)關(guān) --forms* 打開(kāi)HTML表單字段轉(zhuǎn)換為PDF表單域 --grayscale PDF格式將在灰階產(chǎn)生 --help Display help --htmldoc 輸出程序HTML幫助 --ignore-load-errors 忽略claimes加載過(guò)程中已經(jīng)遇到了一個(gè)錯(cuò)誤頁(yè)面 --lowquality 產(chǎn)生低品質(zhì)的PDF/ PS。有用縮小結(jié)果文檔的空間 --manpage 輸出程序手冊(cè)頁(yè) --margin-bottom <unitreal> 設(shè)置頁(yè)面下邊距 (default 10mm) --margin-left <unitreal> 將左邊頁(yè)邊距 (default 10mm) --margin-right <unitreal> 設(shè)置頁(yè)面右邊距 (default 10mm) --margin-top <unitreal> 設(shè)置頁(yè)面上邊距 (default 10mm) --minimum-font-size <int> 最小字體大小 (default 5) --no-background 不打印背景 --orientation <orientation> 設(shè)置方向?yàn)闄M向或縱向 --page-height <unitreal> 頁(yè)面高度 (default unit millimeter) --page-offset* <offset> 設(shè)置起始頁(yè)碼 (default 1) --page-size <size> 設(shè)置紙張大小: A4, Letter, etc. --page-width <unitreal> 頁(yè)面寬度 (default unit millimeter) --password <password> HTTP驗(yàn)證密碼 --post <name> <value> Add an additional post field (repeatable) --post-file <name> <path> Post an aditional file (repeatable) --print-media-type* 使用的打印介質(zhì)類型,而不是屏幕 --proxy <proxy> 使用代理 --quiet Be less verbose --read-args-from-stdin 讀取標(biāo)準(zhǔn)輸入的命令行參數(shù) --readme 輸出程序自述 --redirect-delay <msec> 等待幾毫秒為JS-重定向(default 200) --replace* <name> <value> 替換名稱,值的頁(yè)眉和頁(yè)腳(可重復(fù)) --stop-slow-scripts 停止運(yùn)行緩慢的JavaScripts --title <text> 生成的PDF文件的標(biāo)題(第一個(gè)文檔的標(biāo)題使用,如果沒(méi)有指定) --toc* 插入的內(nèi)容的表中的文件的開(kāi)頭 --use-xserver* 使用X服務(wù)器(一些插件和其他的東西沒(méi)有X11可能無(wú)法正常工作) --user-style-sheet <url> 指定用戶的樣式表,加載在每一頁(yè)中 --username <username> HTTP認(rèn)證的用戶名 --version 輸出版本信息退出 --zoom <float> 使用這個(gè)縮放因子 (default 1) 頁(yè)眉和頁(yè)腳選項(xiàng)--header-center* <text> (設(shè)置在中心位置的頁(yè)眉內(nèi)容) --header-font-name* <name> (default Arial) (設(shè)置頁(yè)眉的字體名稱)--header-font-size* <size> (設(shè)置頁(yè)眉的字體大小)--header-html* <url> (添加一個(gè)HTML頁(yè)眉,后面是網(wǎng)址)--header-left* <text> (左對(duì)齊的頁(yè)眉文本)--header-line* (顯示一條線在頁(yè)眉下)--header-right* <text> (右對(duì)齊頁(yè)眉文本)--header-spacing* <real> (設(shè)置頁(yè)眉和內(nèi)容的距離,默認(rèn)0)--footer-center* <text> (設(shè)置在中心位置的頁(yè)腳內(nèi)容) --footer-font-name* <name> (設(shè)置頁(yè)腳的字體名稱) --footer-font-size* <size> (設(shè)置頁(yè)腳的字體大小default 11)--footer-html* <url> (添加一個(gè)HTML頁(yè)腳,后面是網(wǎng)址)--footer-left* <text> (左對(duì)齊的頁(yè)腳文本)--footer-line* 顯示一條線在頁(yè)腳內(nèi)容上)--footer-right* <text> (右對(duì)齊頁(yè)腳文本)--footer-spacing* <real> (設(shè)置頁(yè)腳和內(nèi)容的距離)./wkhtmltopdf --footer-right '[page]/[topage]' http://www.baidu.com baidu.pdf./wkhtmltopdf --header-center '報(bào)表' --header-line --margin-top 2cm --header-line http://192.168.212.139/oma/ oma.pdf表內(nèi)容選項(xiàng)中 --toc-depth* <level> Set the depth of the toc (default 3) --toc-disable-back-links* Do not link from section header to toc --toc-disable-links* Do not link from toc to sections --toc-font-name* <name> Set the font used for the toc (default Arial) --toc-header-font-name* <name> The font of the toc header (if unset use --toc-font-name) --toc-header-font-size* <size> The font size of the toc header (default 15) --toc-header-text* <text> The header text of the toc (default Table Of Contents) --toc-l1-font-size* <size> Set the font size on level 1 of the toc (default 12) --toc-l1-indentation* <num> Set indentation on level 1 of the toc (default 0) --toc-l2-font-size* <size> Set the font size on level 2 of the toc (default 10) --toc-l2-indentation* <num> Set indentation on level 2 of the toc (default 20) --toc-l3-font-size* <size> Set the font size on level 3 of the toc (default 8) --toc-l3-indentation* <num> Set indentation on level 3 of the toc (default 40) --toc-l4-font-size* <size> Set the font size on level 4 of the toc (default 6) --toc-l4-indentation* <num> Set indentation on level 4 of the toc (default 60) --toc-l5-font-size* <size> Set the font size on level 5 of the toc (default 4) --toc-l5-indentation* <num> Set indentation on level 5 of the toc (default 80) --toc-l6-font-size* <size> Set the font size on level 6 of the toc (default 2) --toc-l6-indentation* <num> Set indentation on level 6 of the toc (default 100) --toc-l7-font-size* <size> Set the font size on level 7 of the toc (default 0) --toc-l7-indentation* <num> Set indentation on level 7 of the toc (default 120) --toc-no-dots* Do not use dots, in the toc輪廓選項(xiàng) --dump-outline <file> 轉(zhuǎn)儲(chǔ)目錄到一個(gè)文件 --outline 顯示目錄(文章中h1,h2來(lái)定) --outline-depth <level> 設(shè)置目錄的深度(默認(rèn)為4)頁(yè)腳和頁(yè)眉 * [page] 由當(dāng)前正在打印的頁(yè)的數(shù)目代替 * [frompage] 由要打印的第一頁(yè)的數(shù)量取代 * [topage] 由最后一頁(yè)要打印的數(shù)量取代 * [webpage] 通過(guò)正在打印的頁(yè)面的URL替換 * [section] 由當(dāng)前節(jié)的名稱替換 * [subsection] 由當(dāng)前小節(jié)的名稱替換 * [date] 由當(dāng)前日期系統(tǒng)的本地格式取代 * [time] 由當(dāng)前時(shí)間,系統(tǒng)的本地格式取代
作者:曹元
鏈接:https://juejin.im/post/6856547881873047559
來(lái)源:掘金
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處。
一篇我們介紹了如何解析CSV和JSON數(shù)據(jù):如何解析互聯(lián)網(wǎng)數(shù)據(jù):CSV和JSON篇,今天我們將介紹如何解析HTML和XML數(shù)據(jù)。
今天的介紹能夠幫助你輕而易舉地從網(wǎng)頁(yè)中(比如下面的中航電子的2017年一季度交易數(shù)據(jù))提取自己想要的數(shù)據(jù):
準(zhǔn)備
在Python中可以解析html和xml數(shù)據(jù)的軟件包很多,今天我們介紹的是lxml,先安裝:
$ pip install lxml
如果不熟悉pip的使用,可以參考另一篇文章:如何管理python軟件包。
解析HTML數(shù)據(jù)
首先,回顧一下HTML的一些基本概念:
標(biāo)簽/tag:比如<html>, <h1>, <head>...一般成對(duì)出現(xiàn),例如開(kāi)始標(biāo)簽<html>和結(jié)束標(biāo)簽</html>
元素/element:開(kāi)始標(biāo)簽到結(jié)束標(biāo)簽整段代碼,標(biāo)簽對(duì)之間的即為內(nèi)容(content)
屬性/attribute:標(biāo)簽可擁有key=value形式的屬性,比如<div class="header">...</div>
簡(jiǎn)單地理解,HTML網(wǎng)頁(yè)就是由一組元素構(gòu)成的一個(gè)集合。另外,大多數(shù)HTML標(biāo)簽是可以嵌套的,因此元素可以包含一系列子元素。有了這些概念做基礎(chǔ),我們將能夠很容易理解軟件包lxml的使用。實(shí)際上,在lxml里面,每個(gè)HTML元素對(duì)應(yīng)一個(gè)lxml.html.HtmlElement對(duì)象,該對(duì)象提供一組標(biāo)準(zhǔn)的方法取訪問(wèn)包含在該元素內(nèi)部的數(shù)據(jù),比如屬性、內(nèi)容和子元素等。
例子
考察下面的鏈接,它提供中航電子在2017年第一季度的交易數(shù)據(jù),我們打算從里面提取一些數(shù)據(jù):
>>> url = "http://quotes.money.163.com/trade/lsjysj_600372.html?year=2017&season=1"
先把該網(wǎng)頁(yè)爬取下來(lái):
>>> import urllib2
>>> rsp = urllib2.urlopen(url).read()
>>> print rsp[0:15]
<!DOCTYPE html>
將字符串rsp轉(zhuǎn)換成HtmlElement對(duì)象:
>>> from lxml import html
>>> doc = html.document_fromstring(rsp)
>>> type(doc)
<class 'lxml.html.HtmlElement'>
>>> doc.tag
'html'
所以其實(shí)doc就是一個(gè)html元素,它包含一些元素,比如head, body, link, div...
比如,如果你想提取該網(wǎng)頁(yè)里面所有的鏈接(links):
>>> links = [ link for link in doc.iterlinks() ]
>>> len(links)
106
>>> links[0]
(<Element link at 0x1029179f0>, 'href', 'http://img1.cache.netease.com/f2e/finance/gegu/s.1064000.css', 0)
>>> links[0][2]
'http://img1.cache.netease.com/f2e/finance/gegu/s.1064000.css'
如果你想查看元素直接包含哪些子元素,可以調(diào)用getchildren()方法:
>>> doc.getchildren()
[<Element head at 0x10299a0a8>, <Element body at 0x10299a470>]
對(duì)嵌套很深的元素,如果熟悉xpath表達(dá)式,最直接的辦法是調(diào)用xpath(...)方法:
>>> [ td.text for td in doc.xpath('/html/body/div[2]/div[4]/table/tr[1]/td')]
['2017-03-31', '19.02', '19.50', '19.02', '19.30', '0.36', '1.90', '102,212', '19,747', '2.53', '0.58']
此外,還可以通過(guò)find, findall, find_class, get_element_by_id等方法查找目標(biāo)元素,比如:
>>> [ td.text for td in doc.findall('./body/div[2]/div[4]/table/tr[1]/td')]
['2017-03-31', '19.02', '19.50', '19.02', '19.30', '0.36', '1.90', '102,212', '19,747', '2.53', '0.58']
如果元素有屬性,提取屬性值也很方便,比如:
>>> form = doc.forms[0]
>>> form.tag
'form'
>>> form.attrib
{'action': '/trade/lsjysj_600372.html', 'id': 'date'}
>>> form.keys()
['id', 'action']
>>> form.get('action')
'/trade/lsjysj_600372.html'
>>> form.items()
[('id', 'date'), ('action', '/trade/lsjysj_600372.html')]
'>>> form.form_values()
[('year', '2017'), ('season', '1')]
>>> form.method
'GET'
做為一個(gè)完整的例子,下面的腳本就是爬取中航電子在2017年第一季度的數(shù)據(jù):
輸出效果:
(test) $ head -3 600372.csv
日期;開(kāi)盤(pán)價(jià);最高價(jià);最低價(jià);收盤(pán)價(jià);漲跌額;漲跌幅(%);成交量(手);成交金額(萬(wàn)元);振幅(%);換手率(%)
2017-03-31;19.02;19.50;19.02;19.30;0.36;1.90;102,212;19,747;2.53;0.58
2017-03-31;19.02;19.50;19.02;19.30;0.36;1.90;102,212;19,747;2.53;0.58
解析xml數(shù)據(jù)
xml的格式和HTML類似,也是由標(biāo)簽構(gòu)成的,但是要比HTML文件簡(jiǎn)單許多,看下面的xml文件片段處理:
>>> xmlstr="""\
... <target name="run" depends="jar">
... <java fork="true" classname="${main-class}">
... <classpath>
... <path refid="classpath"/>
... <path refid="application"/>
... </classpath>
... </java>
... </target>"""
>>> from lxml import etree
第一步是獲取根節(jié)點(diǎn):
>>> root = etree.fromstring(xmlstr)
>>> root.tag
'target'
如果要提取節(jié)點(diǎn)屬性:
>>> root.items()
[('name', 'run'), ('depends', 'jar')]
>>> root.keys()
['name', 'depends'
>>> root.get("name")
'run'
>>> root.values()
['run', 'jar']
可以使用find, xpath等方法去獲取和查找子節(jié)點(diǎn):
>>> java = root.find("./java")
>>> java.tag
'java'
>>> java.keys()
['fork', 'classname']
>>> [ path.get("refid") for path in root.xpath("http://path")]
['classpath', 'application']
lxml軟件的功能很強(qiáng)大,如果有興趣進(jìn)一步了解,可以查看官方文檔:
http://lxml.de/index.html
今天就寫(xiě)這么,歡迎大家留言、評(píng)論和關(guān)注。
*請(qǐng)認(rèn)真填寫(xiě)需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。