Webクローラーを行うと、プロキシIPのための一般的な需要が比較的大きいです。サイト情報をクロールする過程で、多くのサイトがないので、抗爬虫類の戦略は、各IPの周波数制御を行うことであるかもしれません。サイトをクロールするときだから我々は、IPエージェントの多くを必要とします。
IPエージェントの取得は、次の方法から入手することができます。
- 無料サイト、低品質、IPのほとんど使用で利用可能
- エージェントサービス料、高品質の多くを購入
- 自分のプロキシサーバー、安定を構築しますが、サーバーのリソースの多くを必要とします。
複数の無料のウェブサイトから事前にプロキシIP爬虫類による買収後にこの記事プロキシIPプールは、それはMongoDBの、フロントページの最後の表示に格納されて提供され、IPが利用可能かどうかを判断するためにチェックします。
利用可能なプロキシを取得
プロキシコアコードを取得し、それは次のことを行うために、主に、達成するためにRxJava2を使用して、ProxyManagerです。
- ParallelFlowableを作成し、各ページの並列グラブは無料のプロキシIPを提供しています。ParallelFlowable学生が理解していないために、あなたは私の以前の記事を参照できるのParallelFlowable RxJavaを
Flowable.fromIterable(ProxyPool.proxyMap.keySet())
.parallel()
-
各ページのクロール、リターンリスト<プロキシ>
map(new Function<String, List<Proxy>>() { @Override public List<Proxy> apply(String s) throws Exception { try { return new ProxyPageCallable(s).call(); } catch (Exception e) { e.printStackTrace(); } return null; } })
-
プロキシIPのリストについては、各ページのために利用可能かどうかを判断するために確認する必要があります
flatMap(new Function<List<Proxy>, Publisher<Proxy>>() { @Override public Publisher<Proxy> apply(List<Proxy> proxies) throws Exception { if (proxies == null) return null; List<Proxy> result = proxies .stream() .parallel() .filter(new Predicate<Proxy>() { @Override public boolean test(Proxy proxy) { HttpHost httpHost = new HttpHost(proxy.getIp(), proxy.getPort(), proxy.getType()); return HttpManager.get().checkProxy(httpHost); } }).collect(Collectors.toList()); return Flowable.fromIterable(result); } })
- proxyListをオンに保存します
subscribe(new Consumer<Proxy>() { @Override public void accept(Proxy proxy) throws Exception { log.debug("Result Proxy = "+proxy.getType()+"://"+proxy.getIp()+":"+proxy.getPort()); proxy.setLastSuccessfulTime(new Date().getTime()); ProxyPool.proxyList.add(proxy); } });
完全なダイアグラム添付
次に、完全ProxyManagerコードを添付:
import com.cv4j.proxy.domain.Proxy;
import com.cv4j.proxy.http.HttpManager;
import com.cv4j.proxy.task.ProxyPageCallable;
import io.reactivex.Flowable;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpHost;
import org.reactivestreams.Publisher;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;
/**
* Created by tony on 2017/10/25.
*/
@Slf4j
@Component
public class ProxyManager {
/**
* 抓取代理,成功的代理存放到ProxyPool中
*/
public void start() {
Flowable.fromIterable(ProxyPool.proxyMap.keySet())
.parallel()
.map(new Function<String, List<Proxy>>() {
@Override
public List<Proxy> apply(String s) throws Exception {
try {
return new ProxyPageCallable(s).call();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
})
.flatMap(new Function<List<Proxy>, Publisher<Proxy>>() {
@Override
public Publisher<Proxy> apply(List<Proxy> proxies) throws Exception {
if (proxies == null) return null;
List<Proxy> result = proxies
.stream()
.parallel()
.filter(new Predicate<Proxy>() {
@Override
public boolean test(Proxy proxy) {
HttpHost httpHost = new HttpHost(proxy.getIp(), proxy.getPort(), proxy.getType());
return HttpManager.get().checkProxy(httpHost);
}
}).collect(Collectors.toList());
return Flowable.fromIterable(result);
}
})
.sequential()
.subscribe(new Consumer<Proxy>() {
@Override
public void accept(Proxy proxy) throws Exception {
log.debug("Result Proxy = "+proxy.getType()+"://"+proxy.getIp()+":"+proxy.getPort());
proxy.setLastSuccessfulTime(new Date().getTime());
ProxyPool.proxyList.add(proxy);
}
});
}
}
定期的なタスク
、スケジュールされたタスクを実行する最初のミッションをクロールした後に、古いデータを削除してから、MongoDBのに新しいデータを挿入するために、数時間ごと。
import com.cv4j.proxy.ProxyManager;
import com.cv4j.proxy.ProxyPool;
import com.cv4j.proxy.dao.ProxyDao;
import com.cv4j.proxy.domain.Proxy;
import com.safframework.tony.common.utils.Preconditions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* Created by tony on 2017/11/22.
*/
@Component
public class ScheduleJobs {
@Autowired
ProxyDao proxyDao;
@Autowired
ProxyManager proxyManager;
/**
* 每六个小时跑一次任务
*/
@Scheduled(cron = "0 0 */6 * * ?")
public void cronJob() {
System.out.println("Job Start...");
proxyManager.start();
CopyOnWriteArrayList<Proxy> list = ProxyPool.proxyList;
// 先删除旧的数据
proxyDao.deleteAll();
// 然后再进行插入新的proxy
if (Preconditions.isNotBlank(list)) {
for (Proxy p:list) {
proxyDao.saveProxy(p);
}
}
System.out.println("Job End...");
}
}
フロントに表示
:プロジェクト全体は、ローカルアクセスアドレス実行した後、春ブーツを使用して構築された
HTTP:// localhostを:8080 /ページ名負荷= proxy_listを?
次のようにプレビュー効果は次のとおりです。
使用前に、あなたはまた、テストを行うことができ、あなただけのプロキシIPをダブルクリックすることができます。
第二の試験が削除される場合にはProxyPoolはIPに失敗しました。
概要
もちろん、あなたがより高い安定性プロキシIPを追求したいか、より良い購入を検討の彼が利用できるIPプロキシのプールを維持することが爬虫類を行う際に、必要なものです。
最後に、githubのアドレスを添付:
https://github.com/fengzhizi715/ProxyPool