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中支持的爬蟲(chóng)框架有很多,比如WebMagic、Spider、Jsoup等。今天我們使用Jsoup來(lái)實(shí)現(xiàn)一個(gè)簡(jiǎn)單的爬蟲(chóng)程序。
?Jsoup擁有十分方便的api來(lái)處理html文檔,比如參考了DOM對(duì)象的文檔遍歷方法,參考了CSS選擇器的用法等等,因此我們可以使用Jsoup快速地掌握爬取頁(yè)面數(shù)據(jù)的技巧。
1)編寫(xiě)HTML頁(yè)面
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Insert title here</title>
</head>
<body>
<table>
<thead>
<tr>
<td>商品名字</td>
<td>商品圖片</td>
</tr>
</thead>
<tbody>
<tr>
<td class="pname">product1</td>
<td class="pimg"><img src="img/1.bmp"/></td>
</tr>
<tr>
<td class="pname">product2</td>
<td class="pimg"><img src="img/2.bmp"/></td>
</tr>
</tbody>
</table>
</body>
</html>
頁(yè)面中表格的商品信息是我們要爬取的數(shù)據(jù)。其中屬性pname類(lèi)的商品名稱(chēng),以及屬于pimg類(lèi)的商品圖片。
2)使用HttpClient讀取HTML頁(yè)面
HttpClient是一個(gè)處理Http協(xié)議數(shù)據(jù)的工具,使用它可以將HTML頁(yè)面作為輸入流讀進(jìn)java程序中。可以從http://hc.apache.org/下載HttpClient的jar包。
//獲得HttpClient對(duì)象
HttpClient httpClient=new DefaultHttpClient();
//定義要爬取數(shù)據(jù)的目標(biāo)頁(yè)面url
String url="http://localhost:8080/MyShop/shop.jsp";
//使用HttpGet對(duì)象綁定url
HttpGet httpGet=new HttpGet(url);
//訪問(wèn)url獲得響應(yīng)消息封裝在HttpResponse對(duì)象中
HttpResponse httpResponse=httpClient.execute(httpGet);
//entity中是響應(yīng)消息的實(shí)體
HttpEntity entity=httpResponse.getEntity();
//使用EntityUtils的toString獲得url指定頁(yè)面的字符串內(nèi)容,即html本身
String html=EntityUtils.toString(entity);
System.out.println(html);
3)使用Jsoup解析html字符串
通過(guò)引入Jsoup工具,直接調(diào)用parse方法來(lái)解析一個(gè)描述html頁(yè)面內(nèi)容的字符串來(lái)獲得一個(gè)Document對(duì)象。該Document對(duì)象以操作DOM樹(shù)的方式來(lái)獲得html頁(yè)面上指定的內(nèi)容。相關(guān)API可以參考Jsoup官方文檔:https://jsoup.org/cookbook/
下面我們使用Jsoup來(lái)獲取上述html中指定的商品名稱(chēng)和價(jià)格的信息。
//JSOUP解析頁(yè)面數(shù)據(jù),獲得Document對(duì)象
Document doc=Jsoup.parse(html);
//在Document對(duì)象的select方法中使用選擇器來(lái)獲得指定的元素,該選擇器與CSS及Jquery的選擇器相同。
Elements eles=doc.select("table tbody tr .pname");
Element ele=eles.get(0);
//獲得指定元素的文本內(nèi)容
System.out.println(ele.text());
Elements ele_imgs=doc.select("table tbody img");
//獲得指定元素的src屬性的值
String img_src=ele_imgs.get(0).attr("src");
System.out.println(img_src);
至此,我們已經(jīng)實(shí)現(xiàn)使用HttpClient+Jsoup爬取HTML頁(yè)面數(shù)據(jù)的功能。接下來(lái),我們讓效果更直觀一些,比如將爬取的數(shù)據(jù)存到數(shù)據(jù)庫(kù)中,將圖片存到服務(wù)器上。
1)保存普通數(shù)據(jù)到數(shù)據(jù)庫(kù)中
將爬取的數(shù)據(jù)封裝進(jìn)實(shí)體Bean中,并存到數(shù)據(jù)庫(kù)內(nèi)。
//將數(shù)據(jù)封裝到Javabean中
Product p=new Product();
p.setPid(UUID.randomUUID().toString());
p.setPname(ele.text());
p.setPimg(img_src);
//將存入數(shù)據(jù)庫(kù)中
ProductDao dao=new ProductDao();
try {
dao.addProduct(p);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//dao的操作
public void addProduct(Product p) throws SQLException {
QueryRunner qr=new QueryRunner(JDBCUtil.getDataSource());
String sql="insert into product values(?,?,?)";
qr.update(sql,p.getPid(),p.getPname(),p.getPimg());
}
2)保存圖片到服務(wù)器上
直接通過(guò)下載圖片的方式將圖片保存到服務(wù)器本地。
private void downloadImg(HttpServletRequest request,Product p) throws ClientProtocolException, IOException {
//獲得圖片的原url
String url="http://localhost:8080"+p.getPimg();
//使用HttpClient獲得圖片資源
HttpClient httpClient=new DefaultHttpClient();
HttpGet httpGet=new HttpGet(url);
HttpResponse httpResponse=httpClient.execute(httpGet);
//獲得請(qǐng)求的圖片資源的輸入流
InputStream is=httpResponse.getEntity().getContent();
//在服務(wù)器本地創(chuàng)建文件,用于接收?qǐng)D片
String img_name=p.getPimg().substring(p.getPimg().lastIndexOf("/")+1);
String realPath=request.getRealPath("/Download/"+img_name);
File dir=new File(request.getRealPath("/Download"));
if(!dir.exists()){
//如果文件夾不存在,則創(chuàng)建
dir.mkdirs();
}
//讀寫(xiě)數(shù)據(jù),保存圖片
File file=new File(realPath);
FileOutputStream fos=new FileOutputStream(file);
int b=0;
while((b=is.read())!=-1){
fos.write(b);
}
fos.close();
}
本案簡(jiǎn)單實(shí)現(xiàn)了使用HttpClient+Jsoup爬取網(wǎng)絡(luò)數(shù)據(jù),對(duì)于爬蟲(chóng)技術(shù)本身,還有很多值得深挖的地方,以后再為大家講解。
何配置一個(gè)從網(wǎng)頁(yè)爬去數(shù)據(jù)的java項(xiàng)目
用工具如myeclipse,可以新建項(xiàng)目,然后把java代碼放在src目錄下,把 html或者jsp頁(yè)面放到webroot目錄下,當(dāng)然可以自己新建目錄,js放的位置要看你html中自己引用的相對(duì)目錄是什么,jat包需要放在lib目錄下,如果開(kāi)發(fā)環(huán)境沒(méi)有部署tomcat,還得自己部署。
如果只是一個(gè)單純的java項(xiàng)目,只想讓java程序運(yùn)行,那就只需要安裝好jdk,就可以執(zhí)行java程序了。否則那就需要安裝tomcat或者其他的網(wǎng)絡(luò)應(yīng)用服務(wù)器,也就是jsp頁(yè)面。
枷鎖
如果不想借助myeclipse等集成環(huán)境,那可以在tomcat中自己建立項(xiàng)目目錄,一定放在root文件夾下,然后是web-inf,實(shí)在不會(huì)的話(huà)可以把你要部署的項(xiàng)目代碼什么的都粘貼上來(lái),會(huì)有人手把手教你如何部署。
sql文件是以字符串形式存在的,一般是用于生成初始化數(shù)據(jù)庫(kù)。如果是擴(kuò)展性好的程序,一般都有一個(gè)配置文件,說(shuō)明sql文件的路徑。然后在java代碼中,根據(jù)配置文件找到sql文件,以字符串形式打開(kāi),然后讀取字符串,作為sql語(yǔ)句執(zhí)行。這個(gè)過(guò)程不需要考慮會(huì)不會(huì)出錯(cuò),因?yàn)橥暾捻?xiàng)目都已經(jīng)做好了處理。
所以,sql文件應(yīng)該放到最初的位置不要?jiǎng)铀?,或者安裝說(shuō)明把它挪到應(yīng)該在的地方。
科技
爬取指定網(wǎng)站的數(shù)據(jù)de的java代碼
Package zy.crawl.hupu;
Import java.io.IOException;
Import zy.crawl.common.*;
Import java.util.ArrayList;
Import java.util.List;
Import org.apache.http.HttpEntity;
Import org.apache.http.HttpHost;
Import org.apache.http.HttpResponse;
Import org.apache.http.HttpStatus;
Import org.apache.http.client.HttpClient;
Import org.apache.http.client.methods.HttpGet;
Import org.apache.http.conn.params.ConnRoutePNames;
Import org.apache.http.impl.client.DefaultHttpClient;
Import org.apache.http.params.CoreConnectionPNames;
Import org.apache.http.util.EntityUtils;
Import org.jsoup.Jsoup;
Import org.jsoup.nodes.Document;
Import org.jsoup.nodes.Element;
Import org.jsoup.select.Elements;
Publicclass rawlHupu
{
Private List<NewsInfo>newsList=newArrayList<>();//用來(lái)存儲(chǔ)爬取的信息對(duì)象
Public StringGetHtml(Stringurl)//還方法是設(shè)置網(wǎng)絡(luò)鏈接,是固定的用法
{
Stringhtml=null;
HttpClient httpClient=new DefaultHttpClient();
術(shù)棧定義
一般來(lái)說(shuō)是指將N種技術(shù)互相組合在一起(N>1),作為一個(gè)有機(jī)的整體來(lái)實(shí)現(xiàn)某種目的或功能。也可以指掌握這些技術(shù)以及配合使用的經(jīng)驗(yàn)。
舉個(gè)例子:
開(kāi)發(fā)一個(gè)普通OA(辦公自動(dòng)化)系統(tǒng),我們使用了html+css+javascript+vue+ Spring Boot+Spring cloud+hibernate + Spring+rocket Mq+Redis+Es+linux+ mysql等等,這些技術(shù)加起來(lái)就可以稱(chēng)為技術(shù)棧。
互聯(lián)網(wǎng)公司的技術(shù)棧整體分為5大塊:前端、后端、中間件、運(yùn)維和工具。
下面就分別給大家解釋一下最重要的前端、后端運(yùn)用了哪些技術(shù),這些技術(shù)又能解決什么問(wèn)題。
前端技術(shù)棧
01
使用css3作為頁(yè)面的樣式控制
解決頁(yè)面渲染問(wèn)題。
02
使用Html5作為頁(yè)面結(jié)構(gòu)的標(biāo)簽語(yǔ)言
解決移動(dòng)端的頁(yè)面兼容性問(wèn)題。
03
使用seajs框架
解決項(xiàng)目中模塊開(kāi)發(fā)和加載的問(wèn)題。
04
使用使用Jquery前端js框架
解決方便操作頁(yè)面元素的問(wèn)題。
05
引用流行的前端插件實(shí)現(xiàn)業(yè)務(wù)需求
使用bootstrapValidator作為表單的驗(yàn)證插件
使用bootstrap進(jìn)行頁(yè)面的布局;
使用layer作為彈窗插件;
使用jQuery cxSelect 實(shí)現(xiàn)下拉列表的多級(jí)聯(lián)動(dòng);
使用bootstrap fileinput完成多文件的上傳;
使用icheck完成對(duì)多選框的美化;
使用百度ueditor解決復(fù)雜內(nèi)容編輯場(chǎng)景。
06
自定義業(yè)務(wù)插件抽取
主要解決系統(tǒng)導(dǎo)出使用的功能代碼重復(fù)性問(wèn)題。收藏功能;點(diǎn)贊功能;評(píng)論功能;留言功能;關(guān)注功能;頁(yè)面多處個(gè)人信息的設(shè)置;頁(yè)面多處商品頁(yè)面調(diào)起支付的功能;題庫(kù)的組卷系統(tǒng)中的試題欄。
后端技術(shù)棧
01
項(xiàng)目分層思想實(shí)現(xiàn)分布式架構(gòu)
Core層(中心、核心):與業(yè)務(wù)無(wú)關(guān),提供基礎(chǔ)的能力,比如:數(shù)據(jù)庫(kù)持久,redis緩存,http封裝,通用工具。統(tǒng)一的core項(xiàng)目,提供基礎(chǔ)的能力we-core-Db項(xiàng)目:mybatis的mapper的基礎(chǔ)上做了二次封裝;we-core-redis項(xiàng)目:基于jedis的基礎(chǔ)上做了二次封裝;we-core-web:存放一些與web環(huán)境下使用的工具類(lèi)和處理器;自定義web環(huán)境;使用的aop注解;統(tǒng)一的異常處理器;自定義分頁(yè)標(biāo)簽的。 base層(根基、基礎(chǔ)):該層中的項(xiàng)目有且只能代表一個(gè)真實(shí)存在而且能獨(dú)立存在的核心實(shí)體對(duì)應(yīng)的業(yè)務(wù)。 business層(業(yè)務(wù)邏輯層):業(yè)務(wù)層,解決多端,多項(xiàng)目公用的業(yè)務(wù)流程。 web層:為互聯(lián)網(wǎng)用戶(hù)提供對(duì)外服務(wù),在這層的每一個(gè)項(xiàng)目都有自己不被共享的業(yè)務(wù)。
02
抽取獨(dú)立服務(wù)實(shí)現(xiàn)服務(wù)共享
好多項(xiàng)目都會(huì)使用到很多相同的服務(wù),我們會(huì)把它抽取成獨(dú)立的項(xiàng)目,先以jar包的方式提供公用。 比如:短信服務(wù),郵件服務(wù),字典服務(wù),收藏服務(wù),關(guān)注服務(wù),訂單服務(wù),支付服務(wù)3. 基于jedis的基礎(chǔ)上做了二次封裝,實(shí)現(xiàn)java對(duì)redis的讀寫(xiě)。應(yīng)用場(chǎng)景: 整個(gè)項(xiàng)目使用統(tǒng)一的id生成策略。 使用緩存進(jìn)行存放freemark代碼片段的內(nèi)容,解決高頻查詢(xún)數(shù)據(jù)給服務(wù)器帶來(lái)的壓力。
03
使用maven進(jìn)行項(xiàng)目的管理
使用maven自定義骨架可以實(shí)現(xiàn)公司內(nèi)部創(chuàng)建項(xiàng)目模板化,減少大家創(chuàng)建項(xiàng)目時(shí)的時(shí)間,創(chuàng)建完就能使用;使用maven的聚合的特性實(shí)現(xiàn)多項(xiàng)目統(tǒng)一進(jìn)行構(gòu)建;使用maven繼承的特性實(shí)現(xiàn)同一項(xiàng)目的不同maven工程的相同配置問(wèn)題;使用maven的屬性我們可以使用自定義變量以及訪問(wèn)其他配置項(xiàng)值解決我們配置重復(fù)的問(wèn)題;使用maven幫助我們規(guī)范工程資源的的存放;使用maven的依賴(lài)特性可以解決我們,jar包之間的依賴(lài),排出依賴(lài)。;使用maven倉(cāng)庫(kù)的http代理可以實(shí)現(xiàn)讓maven幫助我們查找,下載所需的jar包,我們只需要指定依賴(lài)的gav;使用maven我們把公司自己的開(kāi)發(fā)的項(xiàng)目發(fā)布到nexus上供其他的項(xiàng)目使用。
04
使用nexus進(jìn)行內(nèi)網(wǎng)私服搭建
解決jar包重復(fù)下載的問(wèn)題; 解決公司內(nèi)部項(xiàng)目共享的問(wèn)題; maven倉(cāng)庫(kù)以外的jar包管理。
05
使用gitlab進(jìn)行項(xiàng)目的版本管理
解決團(tuán)隊(duì)多人協(xié)同開(kāi)發(fā)項(xiàng)目的問(wèn)題,我們團(tuán)隊(duì)制定了使用git開(kāi)發(fā)的規(guī)范流程。
06
使用jenkins/hudson實(shí)現(xiàn)項(xiàng)目的自動(dòng)化部署
解決項(xiàng)目自動(dòng)化構(gòu)建,發(fā)布,回滾等問(wèn)題;定時(shí)構(gòu)建及時(shí)發(fā)現(xiàn)項(xiàng)目中的問(wèn)題;實(shí)現(xiàn)一鍵發(fā)布縮短發(fā)布的時(shí)間;自動(dòng)構(gòu)建和發(fā)布的大致流程;從gitlab上拉取最新的代碼;使用maven進(jìn)行構(gòu)建項(xiàng)目;將構(gòu)建完成的項(xiàng)目使用scp復(fù)制到指定服務(wù)器中;并通過(guò)遠(yuǎn)程調(diào)用指定服務(wù)器的腳本進(jìn)行項(xiàng)目的發(fā)布。
07
使用mysql進(jìn)行數(shù)據(jù)存儲(chǔ)
這個(gè)不用多解釋。
08
使用Spring+SpringMvc+Mybitas
使用經(jīng)典的ssm作為平臺(tái)的MVC框架, 處理http請(qǐng)求,處理業(yè)務(wù)邏輯,訪問(wèn)數(shù)據(jù)庫(kù)。
09
使用hibernateValidator
實(shí)現(xiàn)后端接收到的參數(shù)進(jìn)行參數(shù)的合法性驗(yàn)證,像非空,最小,最大,范圍等。
10
使用spring mvc的攔截器
實(shí)現(xiàn)項(xiàng)目?jī)?nèi)的權(quán)限控制,比如:sso權(quán)限驗(yàn)證,角色的驗(yàn)證,支付的驗(yàn)證等。
11
使用spring mvc的AOP
實(shí)現(xiàn)多處相同代碼抽取出來(lái)使用AOP的方式進(jìn)行公用,比如:json視圖的固定格式返回。
12
使用logback
作為架構(gòu)的日志框架。
13
使用flying-saucer+itext+freemark
解決項(xiàng)目中pdf的應(yīng)用場(chǎng)景,比如:學(xué)生下載的準(zhǔn)考證,測(cè)試報(bào)告等。
14
使用JavaMail技術(shù)
實(shí)現(xiàn)郵件的發(fā)送服務(wù)。
15
使用TestNg+H2
實(shí)現(xiàn)進(jìn)行單元化測(cè)試,保證代碼質(zhì)量。
16
使用Cookie+Redis
實(shí)現(xiàn)平臺(tái)單點(diǎn)登錄。
17
實(shí)現(xiàn)SpringMvc提供
的HandlerExceptionResolver接口
使用spring提供HandlerExceptionResolver實(shí)現(xiàn)全站統(tǒng)一異常處理。 包括:業(yè)務(wù)異常,登錄超時(shí)異常,其他異常。
18
實(shí)現(xiàn)SpringMvc提供
的ServletContextAware接口
可以實(shí)現(xiàn)項(xiàng)目啟動(dòng)時(shí)添加一些操作。 初始化freemarker的配置; 初始化項(xiàng)目全局共享的靜態(tài)變量(域名,文件存儲(chǔ)目錄等)。
19
使用Quartz
實(shí)現(xiàn)定時(shí)任務(wù)處理。
20
使用網(wǎng)絡(luò)爬蟲(chóng)技術(shù)Jsoup
解決爬取其他網(wǎng)站的數(shù)據(jù)信息問(wèn)題。
21
使用Qdcode
解決生成二維碼的功能。
22
使用jsp的自定義標(biāo)簽
解決全站分頁(yè)的實(shí)現(xiàn)。
23
使用阿里的Druid
作為連接數(shù)據(jù)庫(kù)的連接池。
24
使用spring的Ioc容器解決對(duì)象的依賴(lài)注入
使用Ioc實(shí)現(xiàn)指定特定接口的實(shí)現(xiàn)類(lèi)以應(yīng)對(duì)業(yè)務(wù)實(shí)現(xiàn)的變化;使用ioc實(shí)現(xiàn)業(yè)務(wù)中需要的配置注入,防止參數(shù)值寫(xiě)死。
25
使用CXF或者Axis
實(shí)現(xiàn)通過(guò)WebService和第三方進(jìn)行對(duì)接。
26
結(jié)合自定義注解+反射
實(shí)現(xiàn)對(duì)方法訪問(wèn)的控制以及添加額外業(yè)務(wù)邏輯。
比如:個(gè)人信息在多個(gè)請(qǐng)求Controller中都需要填充。
27
使用Mybatis框架
解決數(shù)據(jù)持久化的問(wèn)題;引入開(kāi)源的:Mybatis的Mapper接口的方式實(shí)現(xiàn)支持單表的curd,避免寫(xiě)更多的重復(fù)代碼;引入pagehelper解決mybatis的分頁(yè)問(wèn)題;使用Mybatis的Interceptor實(shí)現(xiàn)sql的打印功能。
28
使用Jsp,Freemark
作為視圖層的處理技術(shù)。
29
使用Freemark+字符串替換實(shí)現(xiàn)自定義vt標(biāo)簽
自定義視圖標(biāo)簽主要為了解決像字典那種字段不斷需要跨表查詢(xún)的問(wèn)題。
30
自定義json視圖
自定義json視圖是為了實(shí)現(xiàn)規(guī)定json返回的統(tǒng)一格式。
31
使用El表達(dá)式和jstl標(biāo)簽庫(kù)
解決訪問(wèn)model中的數(shù)據(jù)以及頁(yè)面上顯示的邏輯處理。
32
使用自定義注解實(shí)現(xiàn)某些功能的標(biāo)注
在處理json返回值的時(shí)候可以在標(biāo)注一下@Void就表示不需要包裹; 在sso攔截權(quán)限的時(shí)候可以標(biāo)注一下方法是否需要攔截; 在多個(gè)Controller里都需要設(shè)置用戶(hù)信息到頁(yè)面的時(shí)候,我們可以利用Aop+Annotation的方式實(shí)現(xiàn)。
會(huì)用一種是入門(mén),全部會(huì)用是大神!
*請(qǐng)認(rèn)真填寫(xiě)需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。