Java Proxy在爬虫中的应用
一 作用与适用场景
二 常见实现方式与代码示例
URL url = new URL("https://example.com");
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("58.220.95.54", 9401));
HttpURLConnection conn = (HttpURLConnection) url.openConnection(proxy);
conn.setRequestMethod("GET");
conn.setConnectTimeout(5000);
conn.setReadTimeout(10000);
// ... read response
HttpHost proxy = new HttpHost("121.36.44.97", 8080);
RequestConfig config = RequestConfig.custom()
.setProxy(proxy)
.setConnectTimeout(5000)
.setSocketTimeout(10000)
.build();
CloseableHttpClient client = HttpClients.custom()
.setDefaultRequestConfig(config)
.build();
HttpGet req = new HttpGet("https://example.com");
try (CloseableHttpResponse resp = client.execute(req)) {
// ... handle response
}
Document doc = Jsoup.connect("https://example.com")
.proxy("112.113.122.113", 3128)
.userAgent("Mozilla/5.0")
.timeout(10000)
.get();
CredentialsProvider creds = new BasicCredentialsProvider();
creds.setCredentials(
new AuthScope("proxy_host", 8080),
new UsernamePasswordCredentials("user", "pass")
);
HttpClientContext ctx = HttpClientContext.create();
ctx.setCredentialsProvider(creds);
// 在 execute 时传入 ctx
System.setProperty("http.proxyHost", "123.123.123.123");
System.setProperty("http.proxyPort", "8080");
System.setProperty("https.proxyHost", "123.123.123.123");
System.setProperty("https.proxyPort", "8080");
以上示例覆盖了 HttpURLConnection、HttpClient 与 Jsoup 三种主流用法,并包含认证与全局代理的基本配置。
三 代理池设计与动态代理增强
class ProxyNode {
final String host;
final int port;
volatile int failures;
long lastCheck;
double speedMs;
// getters/setters ...
}
class ProxyPool {
private final ConcurrentHashMap<String, ProxyNode> pool = new ConcurrentHashMap<>();
private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
void add(String host, int port) {
pool.put(host + ":" + port, new ProxyNode(host, port));
}
ProxyNode acquire() { /* 按权重/最少使用/最快响应选择 */ }
void release(ProxyNode n, boolean success) { /* 成功+1,失败计数,必要时标记隔离 */ }
void startHealthCheck(long interval, TimeUnit unit) {
scheduler.scheduleAtFixedRate(this::checkAll, interval, interval, unit);
}
}
interface HttpClient { String send(String url, ProxyNode p) throws Exception; }
class HttpClientHandler implements InvocationHandler {
final HttpClient target;
final ProxyPool pool;
public Object invoke(Object proxy, Method m, Object[] args) throws Throwable {
int retries = 3;
for (int i = 0; i < retries; i++) {
ProxyNode p = pool.acquire();
try {
Object r = m.invoke(target, args[0], p);
pool.release(p, true);
return r;
} catch (Exception e) {
pool.release(p, false);
if (i == retries - 1) throw e;
Thread.sleep(500 * (i + 1));
}
}
throw new RuntimeException("All retries failed");
}
}
// 使用:HttpClient proxied = (HttpClient) Proxy.newProxyInstance(
// c.getClass().getClassLoader(), new Class[]{HttpClient.class},
// new HttpClientHandler(realClient, pool));
上述设计将调度、重试、熔断等非业务代码织入调用链,便于横向扩展与统一治理。
四 稳定性与合规要点
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。