<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 495,comments - 227,trackbacks - 0
    http://www.aneasystone.com/archives/2015/12/java-and-http-using-proxy.html

    在上一篇博客《模擬 HTTP 請求》中,我們分別介紹了兩種方法來進行 HTTP 的模擬請求:HttpURLConnectionHttpClient ,到目前為止這兩種方法都工作的很好,基本上可以實現(xiàn)我們需要的 GET/POST 方法的模擬。對于一個爬蟲來說,能發(fā)送 HTTP 請求,能獲取頁面數(shù)據(jù),能解析網(wǎng)頁內(nèi)容,這相當于已經(jīng)完成 80% 的工作了。只不過對于剩下的這 20% 的工作,還得花費我們另外 80% 的時間 :-)

    在這篇博客里,我們將介紹剩下 20% 的工作中最為重要的一項:如何在 Java 中使用 HTTP 代理,代理也是爬蟲技術(shù)中的重要一項。你如果要大規(guī)模的爬別人網(wǎng)頁上的內(nèi)容,必然會對人家的網(wǎng)站造成影響,如果你太拼了,就會遭人查封。要防止別人查封我 們,我們要么將自己的程序分布到大量機器上去,但是對于資金和資源有限的我們來說這是很奢侈的;要么就使用代理技術(shù),從網(wǎng)上撈一批代理,免費的也好收費的 也好,或者購買一批廉價的 VPS 來搭建自己的代理服務(wù)器。關(guān)于如何搭建自己的代理服務(wù)器,后面有時間的話我再寫一篇關(guān)于這個話題的博客。現(xiàn)在有了一大批代理服務(wù)器之后,就可以使用我們這 篇博客所介紹的技術(shù)了。

    一、簡單的 HTTP 代理

    我們先從最簡單的開始,網(wǎng)上有很多免費代理,直接上百度搜索 “免費代理” 或者 “HTTP 代理” 就能找到很多(雖然網(wǎng)上能找到大量的免費代理,但它們的安全性已經(jīng)有很多文章討論過了,也有專門的文章對此進行調(diào)研的,譬如這篇文章,我在這里就不多作說明,如果你的爬蟲爬取的信息并沒有什么特別的隱私問題,可以忽略之,如果你的爬蟲涉及一些例如模擬登錄之類的功能,考慮到安全性,我建議你還是不要使用網(wǎng)上公開的免費代理,而是搭建自己的代理服務(wù)器比較靠譜)。

    1.1 HttpURLConnection 使用代理

    HttpURLConnection 的 openConnection() 方法可以傳入一個 Proxy 參數(shù),如下:

    1
    2
    3
    Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", 9876));
    URL obj = new URL(url);
    HttpURLConnection con = (HttpURLConnection) obj.openConnection(proxy);

    OK 了,就這么簡單!

    不僅如此,我們注意到 Proxy 構(gòu)造函數(shù)的第一個參數(shù)為枚舉類型 Proxy.Type.HTTP ,那么很顯然,如果將其修改為 Proxy.Type.SOCKS 即可以使用 SOCKS 代理。

    1.2 HttpClient 使用代理

    由于 HttpClient 非常靈活,使用 HttpClient 來連接代理有很多不同的方法。最簡單的方法莫過于下面這樣:

    1
    2
    3
    4
    HttpHost proxy = new HttpHost("127.0.0.1", 9876, "HTTP");
    CloseableHttpClient httpclient = HttpClients.createDefault();
    HttpGet request = new HttpGet(url);
    CloseableHttpResponse response = httpclient.execute(proxy, request);

    和上一篇中使用 HttpClient 發(fā)送請求的代碼幾乎一樣,只是 httpclient.execute() 方法多加了一個參數(shù),第一參數(shù)為 HttpHost 類型,我們這里設(shè)置成我們的代理即可。

    這里要注意一點的是,雖然這里的 new HttpHost() 和上面的 new Proxy() 一樣,也是可以指定協(xié)議類型的,但是遺憾的是 HttpClient 默認是不支持 SOCKS 協(xié)議的,如果我們使用下面的代碼:

    1
    HttpHost proxy = new HttpHost("127.0.0.1", 1080, "SOCKS");

    將會直接報協(xié)議不支持異常:

    org.apache.http.conn.UnsupportedSchemeException: socks protocol is not supported

    如果希望 HttpClient 支持 SOCKS 代理,可以參看這里:How to use Socks 5 proxy with Apache HTTP Client 4? 通過 HttpClient 提供的 ConnectionSocketFactory 類來實現(xiàn)。

    雖然使用這種方式很簡單,只需要加個參數(shù)就可以了,但是其實看 HttpClient 的代碼注釋,如下:

    1
    2
    3
    4
    5
    6
    7
    /*
    * @param target    the target host for the request.
    *                  Implementations may accept <code>null</code>
    *                  if they can still determine a route, for example
    *                  to a default target or by inspecting the request.
    * @param request   the request to execute
    */

    可以看到第一個參數(shù) target 并不是代理,它的真實作用是 執(zhí)行請求的目標主機,這個解釋有點模糊,什么叫做 執(zhí)行請求的目標主機?代理算不算執(zhí)行請求的目標主機呢?因為按常理來講,執(zhí)行請求的目標主機 應(yīng)該是要請求 URL 對應(yīng)的站點才對。如果不算的話,為什么這里將 target 設(shè)置成代理也能正常工作?這個我也不清楚,還需要進一步研究下 HttpClient 的源碼來深入了解下。

    除了上面介紹的這種方式(自己寫的,不推薦使用)來使用代理之外,HttpClient 官網(wǎng)還提供了幾個示例,我將其作為推薦寫法記錄在此。

    第一種寫法是使用 RequestConfig 類,如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    CloseableHttpClient httpclient = HttpClients.createDefault();      
    HttpGet request = new HttpGet(url);
     
    request.setConfig(
        RequestConfig.custom()
            .setProxy(new HttpHost("45.32.21.237", 8888, "HTTP"))
            .build()
    );
             
    CloseableHttpResponse response = httpclient.execute(request);

    第二種寫法是使用 RoutePlanner 類,如下:

    1
    2
    3
    4
    5
    6
    7
    HttpHost proxy = new HttpHost("127.0.0.1", 9876, "HTTP");
    DefaultProxyRoutePlanner routePlanner = new DefaultProxyRoutePlanner(proxy);
    CloseableHttpClient httpclient = HttpClients.custom()
            .setRoutePlanner(routePlanner)
            .build();
    HttpGet request = new HttpGet(url);
    CloseableHttpResponse response = httpclient.execute(request);

    二、使用系統(tǒng)代理配置

    我們在調(diào)試 HTTP 爬蟲程序時,常常需要切換代理來測試,有時候直接使用系統(tǒng)自帶的代理配置將是一種簡單的方法。以前在做 .Net 項目時,程序默認使用 Internet 網(wǎng)絡(luò)設(shè)置中配的代理,遺憾的是,我這里說的系統(tǒng)代理配置指的 JVM 系統(tǒng),而不是操作系統(tǒng),我還沒找到簡單的方法來讓 Java 程序直接使用 Windows 系統(tǒng)下的代理配置。

    盡管如此,系統(tǒng)代理使用起來還是很簡單的。一般有下面兩種方式可以設(shè)置 JVM 的代理配置:

    2.1 System.setProperty

    Java 中的 System 類不僅僅是用來給我們 System.out.println() 打印信息的,它其實還有很多靜態(tài)方法和屬性可以用。其中 System.setProperty() 就是比較常用的一個。

    可以通過下面的方式來分別設(shè)置 HTTP 代理,HTTPS 代理和 SOCKS 代理:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    // HTTP 代理,只能代理 HTTP 請求
    System.setProperty("http.proxyHost", "127.0.0.1");
    System.setProperty("http.proxyPort", "9876");
     
    // HTTPS 代理,只能代理 HTTPS 請求
    System.setProperty("https.proxyHost", "127.0.0.1");
    System.setProperty("https.proxyPort", "9876");
     
    // SOCKS 代理,支持 HTTP 和 HTTPS 請求
    // 注意:如果設(shè)置了 SOCKS 代理就不要設(shè) HTTP/HTTPS 代理
    System.setProperty("socksProxyHost", "127.0.0.1");
    System.setProperty("socksProxyPort", "1080");

    這里有三點要說明:

    1. 系統(tǒng)默認先使用 HTTP/HTTPS 代理,如果既設(shè)置了 HTTP/HTTPS 代理,又設(shè)置了 SOCKS 代理,SOCKS 代理會起不到作用
    2. 由于歷史原因,注意 socksProxyHostsocksProxyPort 中間沒有小數(shù)點
    3. HTTP 和 HTTPS 代理可以合起來縮寫,如下:
    1
    2
    3
    // 同時支持代理 HTTP/HTTPS 請求
    System.setProperty("proxyHost", "127.0.0.1");
    System.setProperty("proxyPort", "9876");

    2.2 JVM 命令行參數(shù)

    可以使用 System.setProperty() 方法來設(shè)置系統(tǒng)代理,也可以直接將這些參數(shù)通過 JVM 的命令行參數(shù)來指定。如果你使用的是 Eclipse ,可以按下面的步驟來設(shè)置:

    1. 按順序打開:Window -> Preferences -> Java -> Installed JREs -> Edit
    2. 在 Default VM arguments 中填寫參數(shù): -DproxyHost=127.0.0.1 -DproxyPort=9876

    jvm-arguments.jpg

    2.3 使用系統(tǒng)代理

    上面兩種方法都可以設(shè)置系統(tǒng),下面要怎么在程序中自動使用系統(tǒng)代理呢?

    對于 HttpURLConnection 類來說,程序不用做任何變動,它會默認使用系統(tǒng)代理。但是 HttpClient 默認是不使用系統(tǒng)代理的,如果想讓它默認使用系統(tǒng)代理,可以通過 SystemDefaultRoutePlannerProxySelector 來設(shè)置。示例代碼如下:

    1
    2
    3
    4
    5
    6
    SystemDefaultRoutePlanner routePlanner = new SystemDefaultRoutePlanner(ProxySelector.getDefault());
    CloseableHttpClient httpclient = HttpClients.custom()
            .setRoutePlanner(routePlanner)
            .build();
    HttpGet request = new HttpGet(url);    
    CloseableHttpResponse response = httpclient.execute(request);

    參考

    1. HttpClient Tutorial
    2. 評測告訴你:那些免費代理悄悄做的齷蹉事兒
    3. How to use Socks 5 proxy with Apache HTTP Client 4?
    4. 使用ProxySelector選擇代理服務(wù)器
    5. Java Networking and Proxies
    posted on 2016-08-02 14:11 SIMONE 閱讀(1234) 評論(0)  編輯  收藏 所屬分類: JAVA
    主站蜘蛛池模板: 亚洲人成影院午夜网站| 亚欧国产一级在线免费| 女人18毛片a级毛片免费| 爱情岛论坛亚洲品质自拍视频网站| 亚洲免费在线观看| 久久久久久毛片免费播放| 学生妹亚洲一区二区| 亚洲男人第一无码aⅴ网站| 久草免费福利资源站| 亚洲色偷偷综合亚洲AV伊人蜜桃 | 91精品免费在线观看| 亚洲精品无码日韩国产不卡av| www亚洲精品少妇裸乳一区二区| 美女在线视频观看影院免费天天看 | 你懂得的在线观看免费视频| 91亚洲国产成人久久精品网址| 四虎永久精品免费观看| 日本在线免费观看| 亚洲欧美日韩中文二区| 久久精品国产亚洲网站| 久久久久久99av无码免费网站| 久久九九久精品国产免费直播| 最新亚洲春色Av无码专区| 亚洲男人的天堂www| 美女黄网站人色视频免费国产| 国产成人久久AV免费| 香港一级毛片免费看| 亚洲一级毛片免费在线观看| 中文字幕在亚洲第一在线| 成人免费无码视频在线网站| 伊人免费在线观看| 免费大片av手机看片| 亚洲av永久无码精品三区在线4| 亚洲综合色区在线观看| 好爽…又高潮了毛片免费看| 久久国产乱子免费精品| 一个人看的在线免费视频| 亚洲熟妇丰满xxxxx| 亚洲无线一二三四区| 久久精品7亚洲午夜a| 亚洲精品国产自在久久|