在很多行業中,要對行業數據進行分類匯總,及時分析行業數據,對於公司未來的發展,有很好的參照和橫向對比。所以,在實際工作,我們可能要遇到數據采集這個概念,數據采集的最終目的就是要獲得數據,提取有用的數據進行數據提取和數據分類匯總。
很多人在第一次了解數據采集的時候,可能無從下手,尤其是作為一個新手,更是感覺很是茫然,所以,在這里分享一下自己的心得,希望和大家一起分享技術,如果有什么不足,還請大家指正。寫出這篇目的,就是希望大家一起成長,我也相信技術之間沒有高低,只有互補,只有分享,才能使彼此更加成長。
在網頁數據采集的時候,我們往往要經過這幾個大的步驟:
①通過URL地址讀取目標網頁②獲得網頁源碼③通過網頁源碼抽取我們要提取的目的數據④對數據進行格式轉換,獲得我們需要的數據。
這是一個示意圖,希望大家了解
了解了基本流程,下來,我以一個案例具體實現如何提取我們需要的數據,對於數據提取可以用正則表達式進行提取,也可以用httpclient+jsoup進行提取,此處,暫且不講解httpclient+jsou提取網頁數據的做法,以后會對httpclient+jsoup進行專門的講解,此處,先開始講解如何用正則表達式對數據進行提取。
我在這里找到一個網站:http://www.ic.NET.cn/userSite/publicQuote/quotes_list.PHP 我們要對里面的數據進行提取操作,我們要提取的最終結果是產品的型號、數量、報價、供應商,首先,我們看到這個網站整個頁面預覽
其次我們看網頁源碼結構:
上面源碼可以很清楚的可以看到整個網頁源碼結構,下來我們就對整個網頁數據進行提取
import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; public class HTMLPageParser { public static void main(String[] args) throws Exception { //目的網頁URL地址 getURLInfo("http://www.ic.net.cn/userSite/publicQuote/quotes_list.php","utf-8"); } public static List<Product> getURLInfo(String urlInfo,String charset) throws Exception { //讀取目的網頁URL地址,獲取網頁源碼 URL url = new URL(urlInfo); HttpURLConnection httpUrl = (HttpURLConnection)url.openConnection(); InputStream is = httpUrl.getInputStream(); BufferedReader br = new BufferedReader(new InputStreamReader(is,"utf-8")); StringBuilder sb = new StringBuilder(); String line; while ((line = br.readLine()) != null) { //這里是對鏈接進行處理 line = line.replaceAll("</?a[^>]*>", ""); //這里是對樣式進行處理 line = line.replaceAll("<(\\w+)[^>]*>", "<$1>"); sb.append(line); } is.close(); br.close(); //獲得網頁源碼 return getDataStructure(sb.toString().trim()); } static Pattern proInfo = Pattern.compile("<div>(.*?)</div>\\s*<div>(.*?)</div>\\s*<div>(.*?)</div>\\s*<div>(.*?)</div>\\s*<div>(.*?)</div>", Pattern.DOTALL); private static List<Product> getDataStructure(String str) { //運用正則表達式對獲取的網頁源碼進行數據匹配,提取我們所要的數據,在以后的過程中,我們可以采用httpclient+jsoup, //現在暫時運用正則表達式對數據進行抽取提取 String[] info = str.split("</li>"); List<Product> list = new ArrayList<Product>(); for (String s : info) { Matcher m = proInfo.matcher(s); Product p = null; if (m.find()) { p = new Product(); //設置產品型號 String[] ss = m.group(1).trim().replace(" ", "").split(">"); p.setProStyle(ss[1]); //設置產品數量 p.setProAmount(m.group(2).trim().replace(" ", "")); //設置產品報價 p.setProPrice(m.group(4).trim().replace(" ", "")); //設置產品供應商 p.setProSupplier(m.group(5).trim().replace(" ", "")); list.add(p); } } //這里對集合里面不是我們要提取的數據進行移除 list.remove(0); for (int i = 0; i < list.size(); i++) { System.out.println("產品型號:"+list.get(i).getProStyle()+",產品數量:"+list.get(i).getProAmount() +",產品報價:"+list.get(i).getProPrice()+",產品供應商:"+list.get(i).getProSupplier()); } return list; } } class Product { private String proStyle;//產品型號 private String proAmount;//產品數量 private String proPrice;//產品報價 private String proSupplier;//產品供應商 public String getProStyle() { return proStyle; } public void setProStyle(String proStyle) { this.proStyle = proStyle; } public String getProSupplier() { return proSupplier; } public void setProSupplier(String proSupplier) { this.proSupplier = proSupplier; } public String getProAmount() { return proAmount; } public void setProAmount(String proAmount) { this.proAmount = proAmount; } public String getProPrice() { return proPrice; } public void setProPrice(String proPrice) { this.proPrice = proPrice; } public Product() { } @Override public String toString() { return "Product [proAmount=" + proAmount + ", proPrice=" + proPrice + ", proStyle=" + proStyle + ", proSupplier=" + proSupplier + "]"; } }
好了,運行上面程序,我們得到下面的數據,就是我們要獲得的最終數據
獲得數據成功,這就是我們要獲得最終的數據結果,最后我要說的是,此處這個網頁算是比較簡單的,而且,網頁源碼可以看到源數據,並且此方式是以get方式進行數據提交,真正采集的時候,有些網頁結構比較復雜,可能會存在着源碼里面沒有我們所要提取的數據,關於這一點的解決方式,以后給大家進行介紹。還有,我在采集這個頁面的時候,只是采集了當前頁面的數據,它還有分頁的數據,關於這個我此處不做講解,只是提示一點,我們可以采用多線程對所有分頁的當前數據進行采集,通過線程一個采集當前頁面數據,一個進行翻頁動作,就可以采集完所有數據。
我們匹配的數據可能在項目實際開發中,要求我們對所提取的數據要進行數據儲存,方便我們下一次進行數據的查詢操作。