HTTP協議是基於TCP協議的,TCP協議在Java中的體現就是套接字.在了解HTTP協議的基礎上,完全可以通過TCP來實現一套HTTP庫,這個庫可以發起網絡請求和接受網絡請求.只要能用URLConnection能實現的事情,用Socket同樣能夠實現.
代理是"代理服務器",我不直接向百度發起請求,而是向代理服務器發起請求,然后代理服務器代替我向百度發起請求.這樣一來,我的IP地址就不會暴露.在編寫爬蟲時,同一個IP爬多了就會被要求輸入驗證碼,這時就可以通過代理來不停地換IP從而規避驗證碼.
本文提供四種方法,第一種方法通過設置環境變量,第二種方法通過URLConnection,第三種方法通過nio中的SocketChannel,第四種方法通過Socket.
public class TestProxy { static String host = "112.126.65.26"; static int port = 12345; static String url = "http://1212.ip138.com/ic.asp"; public static void main(String[] args) throws Exception { four(); } static void one() throws MalformedURLException, IOException { // 沒有這句話是不行的 System.setProperty("http.proxySet", "true"); System.setProperty("http.proxyHost", host); System.setProperty("http.proxyPort", port + ""); URLConnection connection = new URL(url).openConnection(); show(connection.getInputStream()); } static void two() throws MalformedURLException, IOException { SocketAddress addr = new InetSocketAddress(host, port); Proxy proxy = new Proxy(Proxy.Type.HTTP, addr); // 下面這個網址會告訴你你的ip地址 URLConnection connection = new URL(url).openConnection(proxy); show(connection.getInputStream()); } // 使用socket也是一樣 static void three() throws IOException { SocketChannel sc = SocketChannel .open(new InetSocketAddress(host, port)); sc.write(Charset.forName("utf8") .encode("GET " + url + " HTTP/1.1\r\n\r\n")); ByteBuffer buffer = ByteBuffer.allocate(1024); while (sc.read(buffer) != -1) { buffer.flip(); System.out.println(Charset.forName("utf8").decode(buffer)); buffer.clear(); } sc.close(); } static void four() throws IOException { // 以下地址是代理服務器的地址 Socket socket = new Socket(host, port); // 寫與的內容就是遵循HTTP請求協議格式的內容,請求百度 socket.getOutputStream().write( new String("GET " + url + " HTTP/1.1\r\n\r\n").getBytes()); show(socket.getInputStream()); socket.close(); } static void show(InputStream in) throws IOException { Scanner cin = new Scanner(in); StringBuilder builder = new StringBuilder(); while (cin.hasNext()) { builder.append(cin.nextLine()); } cin.close(); Pattern pattern = Pattern .compile("\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}"); Matcher matcher = pattern.matcher(builder.toString()); matcher.find(); System.out.println(matcher.group()); } }