基於Java的同花順股票數據爬蟲

問題來源

  • 今天與同窗聊天,得知他有個任務是抓取同花順網站上的股票數據,有點興趣,便作了相關實驗。

介紹

觀察

  • 瀏覽器:Firefox
  • 觀察現象:網頁中每次只展現一頁的數據,一頁20條數據。一般來講,爲了減輕瀏覽器的存儲壓力,後臺服務器通常只給前臺發送一頁的數據,數據的獲取須要前端發送請求
  • 尋找請求:爲了獲取某一頁數據對應的請求,點擊F12鍵,調出瀏覽器工具控制檯,並點擊到網絡專欄,同時清空界面中的全部請求,頁面以下:清空網絡請求後的界面
  • 點擊頁,發現請求,該請求方法爲GET,返回類型爲html,界面以下:圖片描述
  • 探索請求:發現該請求的返回類型爲html,爲了進一步探索該請求,將該請求的地址複製到瀏覽器地址欄中,打開頁面,發現這與主網站上的數據一致,可認爲該請求可獲取到股票數據。圖片描述
  • 尋找關係:一般來講,某一頁與請求的地址會有特定的聯繫。剛剛咱們請求的地址爲:http://q.10jqka.com.cn/index/...,發現其中的4正好爲咱們所點擊的頁數,這個時候頁數和請求地址的規律尋找出來了

實驗

  • 語言:Java
  • 工具:htmlunit,
<dependency>
            <groupId>net.sourceforge.htmlunit</groupId>
            <artifactId>htmlunit</artifactId>
            <version>2.35.0</version>
    </dependency>
  • 基本思想:瀏覽器模擬點擊
  • 源碼以下:
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.gargoylesoftware.htmlunit.BrowserVersion;
import com.gargoylesoftware.htmlunit.HttpMethod;
import com.gargoylesoftware.htmlunit.NicelyResynchronizingAjaxController;
import com.gargoylesoftware.htmlunit.Page;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.WebRequest;
import com.gargoylesoftware.htmlunit.html.HtmlAnchor;
import com.gargoylesoftware.htmlunit.html.HtmlButton;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.gargoylesoftware.htmlunit.html.HtmlPasswordInput;
import com.gargoylesoftware.htmlunit.html.HtmlTextInput;

public class HtmlUtil {
    WebClient webClient;
    //初始化
    public HtmlUtil(){
        webClient = new WebClient(BrowserVersion.CHROME);//新建一個模擬谷歌Chrome瀏覽器的瀏覽器客戶端對象
        webClient.getOptions().setThrowExceptionOnScriptError(false);//當JS執行出錯的時候是否拋出異常, 這裏選擇不須要
        webClient.getOptions().setThrowExceptionOnFailingStatusCode(false);//當HTTP的狀態非200時是否拋出異常, 這裏選擇不須要
        webClient.getOptions().setActiveXNative(false);
        webClient.getOptions().setCssEnabled(false);//是否啓用CSS, 由於不須要展示頁面, 因此不須要啓用
        webClient.getOptions().setJavaScriptEnabled(true); //很重要,啓用JS。有些網站要開啓!
        webClient.setAjaxController(new NicelyResynchronizingAjaxController());//很重要,設置支持AJAX
        webClient.getOptions().setTimeout(30000);
    }
    //獲取某個url的web客戶端
    public String htmlUnitUrl(String url, WebClient webClient) {  
        try {  
            WebRequest request = new WebRequest(new URL(url), HttpMethod.GET);  
            Map<String, String> additionalHeaders = new HashMap<String, String>();  
            additionalHeaders  
                    .put("User-Agent",  
                            "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.104 Safari/537.36");  
            additionalHeaders.put("Accept-Language", "zh-CN,zh;q=0.8");  
            additionalHeaders.put("Accept", "*/*");  
                        request.setAdditionalHeaders(additionalHeaders);  
            // 獲取某網站頁面  
            Page page = webClient.getPage(request);  
            return page.getWebResponse().getContentAsString();  
        } catch (Exception e) {  
           
        }  
        return null;  
    }  
    //爬取某網頁
    public void work(String url) {
        try {
            HtmlPage page = webClient.getPage(url);//打開網頁
            int pageCount = 177;
            for(int i=1;i<=pageCount;i++) {
                //當訪問速度過快時,後臺瀏覽器會禁止,在這裏可加入適當延遲的代碼
                /**
                *延遲執行的代碼
                */
                
                String content = htmlUnitUrl("http://q.10jqka.com.cn/index/index/board/all/field/zdf/order/desc/page/"+i+"/ajax/1/",webClient);
                if(content.contains("Nginx forbidden."))
                    return;
                else {
                     writeFile("F://測試//"+i+".html",content);
                    }
            }
           
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args){
        HtmlUtil demo=new HtmlUtil();
        String url = "http://q.10jqka.com.cn/";
        demo.work(url);
    }
    /**
     * 保存抓取的html到本地
     * @param path
     * @param content
     */
    public static boolean writeFile(String path,String content) {
    
         File file = new File(path);
         boolean isSuccess = true;
         System.out.println(path);
         // if file doesnt exists, then create it
         if (!file.exists()) {
            try {
                isSuccess = file.createNewFile();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                isSuccess = false;
            }
         }else {
             file.delete();
         }
        FileWriter fw;
        try {
            fw = new FileWriter(file.getAbsoluteFile());
            BufferedWriter bw = new BufferedWriter(fw);
            bw.write(content);
            bw.close();
            System.out.println("寫入成功.");
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            System.out.println("寫入失敗.");
            isSuccess = false;
        }
        return isSuccess;
    }
}

總結

  • 由於心存興趣,便作了相關的實驗,爲了方便,其中的部分代碼還借鑑了網上的源碼。因爲時間關係,以上代碼只是把數據所在的網頁抓取到本地,沒有進行解析。
  • 你們晚安~
相關文章
相關標籤/搜索