自用Java爬蟲工具JAVA-CURL已開源

項目地址: https://github.com/rockswang/...
中央倉庫: https://mvnrepository.com/art...html

簡介

CUrl類是以命令行工具CUrl爲參考,使用標準Java的HttpURLConnection實現的Http工具類。java

特色

  • 基於標準Java運行庫的Http類實現,源碼兼容級別爲1.6,適用性普遍,可用於服務端、Android等Java環境
  • 代碼精簡緊湊,僅一個1000餘行的Java源文件,無任何外部依賴,可不用Maven直接源碼級重用
  • 徹底兼容CUrl命令行工具的經常使用開關,可直接做爲命令行工具替代之
  • 支持全部HTTP Method,支持多文件上傳
  • 經過ThreadLocal解決了標準Java中Cookie只能全局保存的問題,可每線程獨立維護Cookie
  • 可將線程中保存的Cookies序列化保存,方便創建Cookies池
  • 支持HTTP認證,支持HTTPS,可啓用/忽略證書安全
  • 支持每鏈接代理,支持需認證的HTTP/HTTPS代理
  • 跳轉行爲可控制,可獲取到每步跳轉的應答頭信息
  • 支持編程自定義應答解析器
  • 支持失敗重試,可編程自定義可重試異常

支持的參數

參數名 快捷方法 說明
--compressed 請求以gzip壓縮應答數據(但需服務器端支持)
--connect-timeout timeout 鏈接超時時間,單位秒,默認0,即永不超時
-b, --cookie cookie 從文件/IO對象/參數字符串中讀取Cookie
-c, --cookie-jar cookieJar Cookie輸出到文件/IO對象
-d, --data, --data-ascii data 添加post數據,若是屢次使用,則使用'&'鏈接,後添加的表單項鍵值對會覆蓋以前的<br/>若是data以'@'開頭,則後面部分做爲文件名,數據由該文件讀入,且刪除文件中的回車換行
--data-raw 同"--data",但不對'@'特殊處理
--data-binary 同"--data",但讀入文件時不刪除回車換行字符
--data-urlencode data(data,charset) 同"--data",但對數據進行Url-Encode,能夠在此選項後面附加字符集,好比"--data-urlencode-GBK"<br/>若是參數值首字符爲'=':對'='後面的字符串總體進行Url-Encode* 若是參數值中包含'=':將字符串拆分爲以'&'分割的鍵值對,鍵值對用'='分割,對鍵值對中全部的值進行Url-Encode<br/>若是參數值中不包含'=':<br/>--若是字符串中不包含'@',則對字符串總體進行Url-Encode<br/>--若是字符串中包含'@'則以'@'分割字符串,'@'後面爲輸入文件名,則從該文件中讀取文本並進行Url-Encode,'@'前面部分爲鍵<br/>--如'@'爲第一個字符,則文件中讀出的文本總體進行Url-Encode
-D, --dump-header dumpHeader 輸出最後一步跳轉的應答頭到給定的文件/IO對象
-F, --form form 發起文件上傳,添加一個文件或表單項<br/>-如參數值首字母爲'@'或'<'則從指定的文件讀取數據進行上傳。'@'和'<'的區別在於,'@'的文件內容做爲文件附件上傳,'<'的文件內容做爲普通表單項的值<br/>-不然參數值做爲普通表單項的值
--form-string form(formString) 發起文件上傳,添加1個非文件表單項,注意此方法不對'@'進行特殊處理
-G, --get 強制使用GET方法
-H, --header header 添加一個請求頭行,語法爲:<br/>-"Host: baidu.com": 添加/設定一行普通請求頭鍵值對<br/>-"Accept:": 刪除給定請求頭<br/>-"X-Custom-Header;": 添加/設定一個值爲空的自定義請求頭
-I, --head 使用HEAD方法請求
-k, --insecure insecure 忽略HTTPS證書安全檢查
-L, --location location 自動跟隨跳轉(默認不開啓)
-m, --max-time timeout 傳輸超時時間,單位秒,默認0,即永不超時
-o, --output output 指定輸出文件/IO對象,默認stdout,即"-"
-x, --proxy proxy 設定代理服務器
-U, --proxy-user 設定代理服務器登陸信息
-e, --referer 設定Referer請求頭內容
--retry retry 設定重試次數,默認0
--retry-delay retry 設定兩次重試之間的延遲,單位秒,默認0
--retry-max-time retry 設定最長重試總時間,單位秒,默認0,即永不超時
-s, --silent 設定靜默模式,即屏蔽全部輸出
--stderr stderr 設定stderr的輸出文件/IO對象,默認stdout
-u, --user 設定服務器登陸信息
--url CUrl, url 設定請求地址,本CUrl庫不支持多url請求
-A, --user-agent 設定"User-Agent"請求頭內容
-X, --request 指定HTTP請求方法
--x-max-download 傳輸達到給定字節數(非精確)後放棄下載
--x-tags 設定額外的鍵值對信息,存儲在當前CUrl實例中,用於在編程中傳遞額外參數

例子

例1:POST表單提交
public void httpPost() {
        CUrl curl = new CUrl("http://httpbin.org/post")
                .data("hello=world&foo=bar")
                .data("foo=overwrite");
        curl.exec();
        assertEquals(200, curl.getHttpCode());
    }
例2:經過Fiddler代理(抓包工具)訪問HTTPS站點
public void insecureHttpsViaFiddler() {
        CUrl curl = new CUrl("https://httpbin.org/get")
                .proxy("127.0.0.1", 8888) // Use Fiddler to capture & parse HTTPS traffic
                .insecure();  // Ignore certificate check since it's issued by Fiddler
        curl.exec();
        assertEquals(200, curl.getHttpCode());
    }
例3:上傳多個文件,一個內存文件,一個物理文件
public void uploadMultipleFiles() {
        CUrl.MemIO inMemFile = new CUrl.MemIO();
        try { inMemFile.getOutputStream().write("text file content blabla...".getBytes()); } catch (Exception ignored) {}
        CUrl curl = new CUrl("http://httpbin.org/post")
                .form("formItem", "value") // a plain form item
                .form("file", inMemFile)           // in-memory "file"
                .form("image", new CUrl.FileIO("D:\\tmp\\a2.png")); // A file in storage
        curl.exec();
        assertEquals(200, curl.getHttpCode());
    }
例4:模擬手機瀏覽器上的AJAX請求,添加自定義請求頭
public void customUserAgentAndHeaders() {
        String mobileUserAgent = "Mozilla/5.0 (Linux; U; Android 8.0.0; zh-cn; KNT-AL10 Build/HUAWEIKNT-AL10) " 
                + "AppleWebKit/537.36 (KHTML, like Gecko) MQQBrowser/7.3 Chrome/37.0.0.0 Mobile Safari/537.36";
        Map<String, String> fakeAjaxHeaders = new HashMap<String, String>();
        fakeAjaxHeaders.put("X-Requested-With", "XMLHttpRequest");
        fakeAjaxHeaders.put("Referer", "http://somesite.com/fake_referer");
        CUrl curl = new CUrl("http://httpbin.org/get")
                .opt("-A", mobileUserAgent) // simulate a mobile browser
                .headers(fakeAjaxHeaders)   // simulate an AJAX request
                .header("X-Auth-Token: xxxxxxx"); // other custom header, this might be calculated elsewhere
        curl.exec();
        assertEquals(200, curl.getHttpCode());
    }
例5:多線程併發請求,線程間Cookies相互獨立
public void threadSafeCookies() {
        final CountDownLatch count = new CountDownLatch(3);
        final CUrl[] curls = new CUrl[3];
        for (int i = 3; --i >= 0;) {
            final int idx = i;
            new Thread() {
                public void run() {
                    CUrl curl = curls[idx] = new CUrl("http://httpbin.org/get")
                            .cookie("thread" + idx + "=#" + idx);
                    curl.exec();
                    count.countDown();
                }
            }.start();
        }
        try { count.await(); } catch (Exception ignored) {} // make sure all requests are done
        assertEquals(200, curls[0].getHttpCode());
        assertEquals("thread0=#0", deepGet(curls[0].getStdout(jsonResolver, null), "headers.Cookie"));
        assertEquals("thread1=#1", deepGet(curls[1].getStdout(jsonResolver, null), "headers.Cookie"));
        assertEquals("thread2=#2", deepGet(curls[2].getStdout(jsonResolver, null), "headers.Cookie"));
    }
例6:編程自定義應答解析器,使用JSoup解析HTML
private CUrl.Resolver<Document> htmlResolver = new CUrl.Resolver<Document>() {
        @SuppressWarnings("unchecked")
        @Override
        public Document resolve(int httpCode, byte[] responseBody) throws Throwable {
            String html = new String(responseBody, "UTF-8");
            return Jsoup.parse(html);
        }
    };

    public void customResolver() {
        CUrl curl = new CUrl("http://httpbin.org/html");
        Document html = curl.exec(htmlResolver, null);
        assertEquals(200, curl.getHttpCode());
        assertEquals("Herman Melville - Moby-Dick", html.select("h1:first-child").text());
    }
例7:做爲命令行工具使用,請求內容參考例4
java -jar java-curl-1.2.0.jar https://httpbin.org/get ^
    -x 127.0.0.1:8888 -k ^
    -A "Mozilla/5.0 (Linux; U; Android 8.0.0; zh-cn; KNT-AL10 Build/HUAWEIKNT-AL10) AppleWebKit/537.36 (KHTML, like Gecko) MQQBrowser/7.3 Chrome/37.0.0.0 Mobile Safari/537.36" ^
    -H "Referer: http://somesite.com/fake_referer" ^
    -H "X-Requested-With: XMLHttpRequest" ^
    -H "X-Auth-Token: xxxxxxx"
相關文章
相關標籤/搜索