Java爬蟲項目實戰(一)


目的:

        通過網絡爬蟲爬取中國最小粒度的區域維度信息,包括省(Province) 、市(City)、縣(County)、鎮(town)、村委會(village)

主網站鏈接:

           http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2015/index.html

主要jar包:              

          http://jsoup.org/packages/jsoup-1.8.1.jar

 之前一節我們說過java爬蟲從網絡上利用jsoup獲取網頁文本,也就是說我們可以有三種方法獲取html,一是根據url鏈接,而是從本地路徑獲取,三是通過字符串解析成html文檔

在這里,我們利用前兩種搭配使用:

  先看本地是否存在需要的網頁,如果不存在就通過url獲取並保存在本地(下次就可以不需要重新從網絡加載)

我們先建一個類叫做Html類,具體內容如下:

package Product;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;

import org.jsoup.*;
import org.jsoup.nodes.*;
import org.jsoup.select.*;
public class Html {
    
     //根據url從網絡獲取網頁文本
    public Document getHtmlTextByUrl(String url)
    {
        Document doc = null;
        try {
            //doc = Jsoup.connect(url).timeout(5000000).get();
            int i = (int) (Math.random()*1000); //做一個隨機延時,防止網站屏蔽
while(i!=0) 
{ i
--; }
doc
= Jsoup.connect(url).data("query", "Java")
.userAgent(
"Mozilla") .cookie("auth", "token")
.timeout(
300000) .post();
}
catch (IOException e)
{ e.printStackTrace();
try {
doc
= Jsoup.connect(url).timeout(5000000).get();
}
catch (IOException e1)
{
// TODO Auto-generated catch block e1.printStackTrace(); } }

return doc;
}

//根據本地路徑獲取網頁文本,如果不存在就通過url從網絡獲取並保存

public Document getHtmlTextByPath(String name,String url)
{
String path
= "D:/Html/" +name+".html";
Document doc
= null ;
File input
= new File(path);
String urlcat
= url;
try {
doc
= Jsoup.parse(input, "GBK");
if(!doc.children().isEmpty())
{
doc
=null; System.out.println("已經存在"); }
}
catch (IOException e)
{
System.out.println(
"文件未找到,正在從網絡獲取.......");
doc
= this.getHtmlTextByUrl(url);
//並且保存到本地
this.Save_Html(url, name); } return doc; } //此處為保存網頁的函數
//將網頁保存在本地(通過url,和保存的名字)
    public  void Save_Html(String url,String name) {
                  try {
                       name =  name+".html";
                     // System.out.print(name);
                     File dest = new File("D:/Html/" +name);//D:\Html
                      //接收字節輸入流
                      InputStream is;
                      //字節輸出流
                      FileOutputStream fos = new FileOutputStream(dest);
              
                     URL temp = new URL(url);
                     is = temp.openStream();
                 
                     //為字節輸入流加緩沖
                     BufferedInputStream bis = new BufferedInputStream(is);
                     //為字節輸出流加緩沖
                     BufferedOutputStream bos = new BufferedOutputStream(fos);
             
                     int length;
             
                     byte[] bytes = new byte[1024*20];
                     while((length = bis.read(bytes, 0, bytes.length)) != -1){
                         fos.write(bytes, 0, length);
                     }
         
                     bos.close();
                     fos.close();
                     bis.close();
                     is.close();
                 } catch (IOException e) {
                     e.printStackTrace();
                 }
             }
 
         

 



 這樣通過Html這個類,調用getHtmlTextByPath函數,傳入我們的鏈接和想要保存的名稱,接下就可以對這個網頁文本提取信息

並將整個網頁下載到我們的本地。

看到我們的網站是這樣的:

利用谷歌瀏覽右鍵檢查元素,我們注意觀察黃色標記的部分:

     

我們發現這些文本信息和超鏈接信息在tr 下的td下的a標簽內,利用我們的jsoup可以直接獲取到這些信息,詳情請看:

//根據元素屬性獲取某個元素內的elements列表
    public Elements getEleByClass(Document doc,String className)
    {
        Elements elements= null;    
elements = doc.select(className);//這里把我們獲取到的html文本doc,和工具class名,注意<tr class="provincetr">
return elements; //此處返回的就是所有的tr集合
}

我們在調用的時候,就直接把我們獲取的html文本,以及"tr.provincertr"作為參數傳入,在來解析tr集合內部的信息,

也就是td中兩個a標簽href和文本內容:比如href="12.html"  北京

代碼如下:

//獲取省 、市 、縣等的信息
    public ArrayList getProvince(String name,String url ,String type)
    {    ArrayList result= new ArrayList();
        //"tr.provincetr"
         String classtype = "tr."+type+"tr"; 
         //從網絡上獲取網頁
        // Document doc = this.getHtmlTextByUrl(url);
         //從本地獲取網頁,如果沒有則從網絡獲取
         Document doc2 = this.getHtmlTextByPath(name,url);
         System.out.println(name);
         if(doc2!=null){   
         Elements es =this.getEleByClass(doc2,classtype);  //tr的集合
        for(Element e : es)   //依次循環每個元素,也就是一個tr
        {
            if(e!=null){
            for(Element ec : e.children())  //一個tr的子元素td,td內包含a標簽
            {
                String[] prv = new String[4];   //身份的信息: 原來的url(當前url)  名稱(北京) 現在url(也就是北京的url)  類型(prv)省
                if(ec.children().first()!=null)
                {
                //原來的url
                prv[0]=url;  //就是參數url
                //身份名稱
                System.out.println(ec.children().first().ownText());
                prv[1]=ec.children().first().ownText();  //a標簽文本  如:北京
                //身份url地址
                //System.out.println(ec.children().first().attr("href"));
                //http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2015/index.html
                String ownurl=ec.children().first().attr("abs:href");  //北京的url
                //因為如果從本地取得話,會成為本地url,所以保留第一次從網絡上的url,保證url不為空
                if(ownurl.length()<10)
                {   connectOrcl c = new connectOrcl();
                    ownurl = c.selectOne(prv[1]); //從數據庫中取,這是另一個調用數據庫函數,根據名稱取url
                }
                prv[2]=ownurl;  //如:北京自己的url
                System.out.println(prv[2]);
                //級別
                prv[3]=type; //就是剛剛傳的類型,后面會有city 、county等
              //將所有身份加入list中    
                result.add(prv);}
            }}
        }    
    }
        return result;  //反回所有的省份信息集合,存數據庫,字段類型為: baseurl  name ownurl levelname(type) updatetime
    }

 

 

 

 java獲取本機的名稱和ip

//獲取本機名稱和IP
public
static void main(String[] args) { InetAddress ia=null; try { ia = ia.getLocalHost(); String localname=ia.getHostName(); String localip=ia.getHostAddress(); System.out.println("本機名稱是:"+ localname); System.out.println("本機的ip是 :"+localip); } catch (UnknownHostException e) { // TODO Auto-generated catch block e.printStackTrace(); } }

 

java獲取本機的屏幕分辨率,DPI,以及屏幕尺寸

  屏幕分辨率:比如1366*768

  DPI:意思是說一英寸多少個象素

  屏幕的物理尺寸:屏幕的物理大小還需要知道屏幕的dpi ,然后用象素除以dpi 就可以得到多少英寸了

//獲取電腦屏幕信息
public
static void getScreen() { Dimension screensize = Toolkit.getDefaultToolkit().getScreenSize(); int width = (int)screensize.getWidth(); int height = (int)screensize.getHeight(); System.out.println("寬的像素:"+width+"高的像素:"+height); //獲取屏幕的dpi int dpi = Toolkit.getDefaultToolkit().getScreenResolution(); System.out.println(dpi); //根據dpi和像素,可以計算物理尺寸 System.out.println("寬:"+width/dpi+"高:"+height/dpi); }

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM