只能抓取靜態(tài)的頁(yè)面源代碼,因?yàn)楹芏嗍录蜆邮绞莿?dòng)態(tài)綁定和執(zhí)行的,所以不可能獲取到執(zhí)行完后的代碼的。
賓川ssl適用于網(wǎng)站、小程序/APP、API接口等需要進(jìn)行數(shù)據(jù)傳輸應(yīng)用場(chǎng)景,ssl證書未來(lái)市場(chǎng)廣闊!成為成都創(chuàng)新互聯(lián)的ssl證書銷售渠道,可以享受市場(chǎng)價(jià)格4-6折優(yōu)惠!如果有意向歡迎電話聯(lián)系或者加微信:18980820575(備注:SSL證書合作)期待與您的合作!
public
String
getHtmlContent(String
htmlurl)
{
URL
url;
String
temp;
StringBuffer
sb
=
new
StringBuffer();
try
{
url
=
new
URL(htmlurl);
BufferedReader
in
=
new
BufferedReader(new
InputStreamReader(url.openStream(),
"gbk"));
while
((temp
=
in.readLine())
!=
null)
{
sb.append(temp);
}
in.close();
}
catch
(final
MalformedURLException
me)
{
me.getMessage();
}
catch
(final
IOException
e)
{
e.printStackTrace();
}
return
sb.toString();
}
根據(jù)java網(wǎng)絡(luò)編程相關(guān)的內(nèi)容,使用jdk提供的相關(guān)類可以得到url對(duì)應(yīng)網(wǎng)頁(yè)的html頁(yè)面代碼。
針對(duì)得到的html代碼,通過(guò)使用正則表達(dá)式即可得到我們想要的內(nèi)容。
比如,我們?nèi)绻氲玫揭粋€(gè)網(wǎng)頁(yè)上所有包括“java”關(guān)鍵字的文本內(nèi)容,就可以逐行對(duì)網(wǎng)頁(yè)代碼進(jìn)行正則表達(dá)式的匹配。最后達(dá)到去除html標(biāo)簽和不相關(guān)的內(nèi)容,只得到包括“java”這個(gè)關(guān)鍵字的內(nèi)容的效果。
從網(wǎng)頁(yè)上爬取圖片的流程和爬取內(nèi)容的流程基本相同,但是爬取圖片的步驟會(huì)多一步。
需要先用img標(biāo)簽的正則表達(dá)式匹配獲取到img標(biāo)簽,再用src屬性的正則表達(dá)式獲取這個(gè)img標(biāo)簽中的src屬性的圖片url,然后再通過(guò)緩沖輸入流對(duì)象讀取到這個(gè)圖片url的圖片信息,配合文件輸出流將讀到的圖片信息寫入到本地即可。
1. 你可以選擇用Java代碼來(lái)找到整個(gè)網(wǎng)頁(yè)的html代碼,如下
(注意在處理網(wǎng)頁(yè)方面的內(nèi)容時(shí),需要導(dǎo)入htmlparser包來(lái)支持)
import org.htmlparser.util.ParserException;
import org.htmlparser.visitors.HtmlPage;
import org.htmlparser.Parser;
import org.htmlparser.filters.HasAttributeFilter;
import org.htmlparser.util.NodeList;
public class htmlmover {
public static void main(String[] args){
NodeList rt= getNodeList("");
System.out.println(rt.toHtml());
}
public static NodeList getNodeList(String url){
Parser parser = null;
HtmlPage visitor = null;
try {
parser = new Parser(url);
parser.setEncoding("GBK");
visitor = new HtmlPage(parser);
parser.visitAllNodesWith(visitor);
} catch (ParserException e) {
e.printStackTrace();
}
NodeList nodeList = visitor.getBody();
return nodeList;
}
}
以上代碼,public static NodeList getNodeList(String url) 為主體
傳入需要分析網(wǎng)頁(yè)的 url(String類型),返回值是網(wǎng)頁(yè)Html節(jié)點(diǎn)List(Nodelist類型)
這個(gè)方法我沒有什么要說(shuō)的,剛開始的時(shí)候沒看懂(沒接觸過(guò)),后來(lái)用了幾次也懂點(diǎn)皮毛了
注意: parser.setEncoding("GBK"); 可能你的工程編碼格式是UTF-8,有錯(cuò)誤的話需要改動(dòng)
運(yùn)行該程序
2.通過(guò)瀏覽器工具直接查看 IE是按F12 (剛開始沒發(fā)現(xiàn)這個(gè)方法,于是傻乎乎地找上面的代碼)
分析你所獲得的html代碼讓人眼花繚亂,不要緊,找到自己需要趴取的內(nèi)容,找到它上下文有特征的節(jié)點(diǎn)
!--中行牌價(jià) 開始--
div id="sw01_con1"
table width="655" border="0" cellspacing="0" cellpadding="0" class="hgtab"
thead
tr
th width="85" align="center" class="th_l"交易幣種/th
th width="80" align="center"交易單位/th
th width="130" align="center"現(xiàn)價(jià)(人民幣)/th
th width="80" align="center"賣出價(jià)/th
th width="100" align="center"現(xiàn)匯買入價(jià)/th
th width="95" align="center"現(xiàn)鈔買入價(jià)/th
/tr
/thead
tbody
tr align="center"
td 英鎊/td
td100/td
td992.7/td
td1001.24/td
td993.26/td
td class="no"962.6/td
/tr
tr align="center" bgcolor="#f2f3f4"
td 港幣/td
td100/td
td81.54/td
td82.13/td
td81.81/td
td class="no"81.16/td
/tr
tr align="center"
td 美元/td
td100/td
td635.49/td
td639.35/td
td636.8/td
td class="no"631.69/td
/tr
tr align="center" bgcolor="#f2f3f4"
td 瑞士法郎/td
td100/td
td710.89/td
td707.78/td
td702.14/td
td class="no"680.46/td
/tr
tr align="center"
td 新加坡元/td
td100/td
td492.45/td
td490.17/td
td486.27/td
td class="no"471.25/td
/tr
tr align="center" bgcolor="#f2f3f4"
td 瑞典克朗/td
td100/td
td93.66/td
td93.79/td
td93.04/td
td class="no"90.17/td
/tr
tr align="center"
td 丹麥克朗/td
td100/td
td116.43/td
td115.59/td
td114.67/td
td class="no"111.13/td
/tr
tr align="center" bgcolor="#f2f3f4"
td 挪威克朗/td
td100/td
td110.01/td
td109.6/td
td108.73/td
td class="no"105.37/td
/tr
!--{2011-10-01 23:16:00}--
/tbody
/table
/div
!--中行牌價(jià) 結(jié)束--
大家可以看到這是一段很有規(guī)律,書寫非常規(guī)范的Html代碼(這只是第一部分,中行牌價(jià),可以想像,接下來(lái)還會(huì)有并列的 相似的3部分)
大家想截取這些節(jié)點(diǎn)中的數(shù)據(jù)
以下代碼仍需導(dǎo)入htmlparser Java支持包
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.htmlparser.Node;
import org.htmlparser.NodeFilter;
import org.htmlparser.Parser;
import org.htmlparser.util.NodeList;
import org.htmlparser.util.ParserException;
public class Currencyrate {
public static void main(String[] args){
String url="";
ArrayListString rt= getNodeList(url);
for (int i = 0; i rt.size(); i++){
System.out.println(rt.get(i));
}
}
public static ArrayListString getNodeList(String url){
final ArrayListString result=new ArrayListString();
Parser parser = null;
NodeList nodeList=null;
try {
parser = new Parser(url);
parser.setEncoding("GBK");
nodeList = parser.parse(
new NodeFilter(){
@Override
public boolean accept(Node node){
Node need=node;
if(getStringsByRegex(node.getText())){
for(int i=0;i6;i++){
result.add(need.toPlainTextString()); need=need.getPreviousSibling().getPreviousSibling();
}
return true;
}
return false;
}
}
);
}catch (ParserException e) {
e.printStackTrace();
}
return result;
}
public static boolean getStringsByRegex(String txt) {
String regex="td class=\"no\"";
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(txt);
if (m.find()){
return true;
}
return false;
}
}
廢話不多說(shuō),
public static ArrayListString getNodeList(String url) 主要方法
parser.setEncoding("GBK"); 需要注意,代碼編碼格式
nodeList = parser.parse(
new NodeFilter(){
@Override
public boolean accept(Node node){
}
}
);
nodelist是html節(jié)點(diǎn)的列表,現(xiàn)在使用NodeFilter ( 節(jié)點(diǎn)過(guò)濾器 )實(shí)例, 重載NodeFilter類中的accept()方法
在parser這個(gè)Parser類訪問整個(gè)html頁(yè)面的時(shí)候,每遇到一個(gè)html節(jié)點(diǎn),就會(huì)訪問這個(gè)
accept()方法,返回True的話就會(huì)將這個(gè)節(jié)點(diǎn) 放進(jìn)nodelist中,否則就不會(huì)將這個(gè)節(jié)點(diǎn)放進(jìn)去。這個(gè)就是NodeFilter功能。
代碼段一獲取整個(gè)html頁(yè)面時(shí)候 parser.visitAllNodesWith(visitor); 就是獲取所有節(jié)點(diǎn)
所以現(xiàn)在我們要趴取網(wǎng)頁(yè)上的內(nèi)容,只要告訴accept()這個(gè)方法,哪些節(jié)點(diǎn)要放進(jìn)nodelist去,即 遇到哪些節(jié)點(diǎn)需要返回true。
于是
public boolean accept(Node node){
Node need=node;
if(getStringsByRegex(node.getText())){
for(int i=0;i6;i++){
result.add(need.toPlainTextString()); need=need.getPreviousSibling().getPreviousSibling();
}
return true;
}
return false;
}
Parser類在遇到節(jié)點(diǎn),就把這個(gè)節(jié)點(diǎn)拿過(guò)去問accept(),于是accept()方法分析,如果滿足getStringsByRegex(node.getText())就要了
接下來(lái)分析getStringsByRegex(),只剩下最后一步了,大家堅(jiān)持??!
String regex="td class=\"no\"";
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(txt);
if (m.find()){
return true;
}
return false;
}
大家可以發(fā)現(xiàn)我們索要的每一段都是
tr align="center"
td 英鎊/td
td100/td
td992.7/td
td1001.24/td
td993.26/td
td class="no"962.6/td
/tr
所以只要找到td class="no"這個(gè)節(jié)點(diǎn)就行了,我們用正則表達(dá)式去比較
String regex="td class=\"no\""; 這個(gè)是比較標(biāo)準(zhǔn)(正則表達(dá)式 td class=”no” 其中兩個(gè)引號(hào)需要作為轉(zhuǎn)義字符來(lái)表示 成\“ )
變量txt是我們傳過(guò)去的需要比較的節(jié)點(diǎn)的node.getText(),如果符合的話m.find就是true,于是getStringsByRegex()返回true,說(shuō)明這個(gè)節(jié)點(diǎn)就是我們所需要的哪些節(jié)點(diǎn),于是
for(int i=0;i6;i++){
result.add(need.toPlainTextString()); need=need.getPreviousSibling().getPreviousSibling();
}
每一段html,6個(gè)為一組,先是962.6,然后是993.26,1001.24,992.7,100,英鎊分別被add進(jìn)result這個(gè)ArrayListString中去,返回,這個(gè)ArrayList裝的就是我們需要抓取的數(shù)據(jù)
大家可以把我們所獲得的String數(shù)據(jù)數(shù)出來(lái)試試看,是不是我們需要的順序,main()函數(shù)獲得ArrayListString,就可以顯示到我們所需要的Java widget上去了
網(wǎng)絡(luò)爬蟲是一個(gè)自動(dòng)提取網(wǎng)頁(yè)的程序,它為搜索引擎從萬(wàn)維網(wǎng)上下載網(wǎng)頁(yè),是搜索引擎的重要組成。傳統(tǒng)爬蟲從一個(gè)或若干初始網(wǎng)頁(yè)的URL開始,獲得初始網(wǎng)頁(yè)上的URL,在抓取網(wǎng)頁(yè)的過(guò)程中,不斷從當(dāng)前頁(yè)面上抽取新的URL放入隊(duì)列,直到滿足系統(tǒng)的一定停止條件。
java實(shí)現(xiàn)網(wǎng)頁(yè)源碼獲取的步驟:
(1)新建URL對(duì)象,表示要訪問的網(wǎng)址。如:url=new URL("");
(2)建立HTTP連接,返回連接對(duì)象urlConnection對(duì)象。如:urlConnection = (HttpURLConnection)url.openConnection();
(3)獲取相應(yīng)HTTP 狀態(tài)碼。如responsecode=urlConnection.getResponseCode();
(4)如果HTTP 狀態(tài)碼為200,表示成功。從urlConnection對(duì)象獲取輸入流對(duì)象來(lái)獲取請(qǐng)求的網(wǎng)頁(yè)源代碼。
通過(guò)Java代碼實(shí)現(xiàn)對(duì)網(wǎng)頁(yè)數(shù)據(jù)進(jìn)行指定抓取方法思路如下:
在工程中導(dǎo)入Jsoup.jar包
獲取網(wǎng)址url指定HTML或者文檔指定的body
獲取網(wǎng)頁(yè)中超鏈接的標(biāo)題和鏈接
獲取指定博客文章的內(nèi)容
獲取網(wǎng)頁(yè)中超鏈接的標(biāo)題和鏈接的結(jié)果
如果代碼能力不是很好的話可以借助一些軟件去抓取新聞的字段
把數(shù)據(jù)抓取下來(lái)以后可以選擇存入數(shù)據(jù)庫(kù)當(dāng)中
需要去重的話,在Java的集合框架中就有HashSet和HashMap可以對(duì)數(shù)據(jù)去重
使用帶Hash的集合時(shí)一定要注意,如果是存放自定義的對(duì)象一定要重寫equals方法和HashCode方法