本文内容

1、分析一下爬虫存在的问题及解决方案

2、webmagic中代理的使用

3、目前市面上一些比较好用的代理服务器

存在的问题

我们在使用爬虫过程中,大多都会遇到这样的问题:突然某一天爬虫爬不到内容了,目标网站直接返回404或者其他错误信息,这说明我们的爬虫被目标网站给屏蔽了。

爬虫被屏蔽的原因

1、爬虫大量请求对对目标服务器造成了压力

2、爬虫采集目标网站有价值的内容到处传播,对目标网站造成了不良影响

出于以上原因,正常情况下目标网站会把爬虫屏蔽掉,这样直接导致我们开发的爬虫无法采集正确的内容。

未使用代理的情况

我们的爬虫程序以一个固定的ip去访问目标网站,目标网站会发现这个固定的ip有大量的请求,会判定为爬虫,直接进行屏蔽。

如果我们每次请求发送的ip都不一样,这样目标网站一般情况下就不会把我们当成爬虫屏蔽了。

解决办法

使用代理来解决问题

请求过程如下:

1、爬虫采集请求给代理服务器

2、代理服务器一般是一个集群,内部有很多机器,代理随机选择一台机器,将请求发送给目标服务器

3、目标服务器将结果返回给代理服务器

4、代理服务器将结果返回给爬虫

可以看出,整个系统的稳定性在代理服务器上,代理服务器的质量直接影响到整个程序的稳定性。

webmagic中使用代理

从0.7.1版本开始,WebMagic开始使用了新的代理APIProxyProvider。因为相对于Site的“配置”,ProxyProvider定位更多是一个“组件”,所以代理不再从Site设置,而是由HttpClientDownloader设置。

API 说明
HttpClientDownloader.setProxyProvider(ProxyProvider proxyProvider) 设置代理

ProxyProvider有一个默认实现:SimpleProxyProvider。它是一个基于简单Round-Robin的、没有失败检查的ProxyProvider。可以配置任意个候选代理,每次会按顺序挑选一个代理使用。它适合用在自己搭建的比较稳定的代理的场景。

代理示例:

1、设置单一的普通HTTP代理为101.101.101.101的8888端口,并设置密码为"username","password"

HttpClientDownloader httpClientDownloader = new HttpClientDownloader();
httpClientDownloader.setProxyProvider(SimpleProxyProvider.from(new Proxy("101.101.101.101",8888,"username","password")));
spider.setDownloader(httpClientDownloader);

2、设置代理池,其中包括101.101.101.101和102.102.102.102两个IP,没有密码

HttpClientDownloader httpClientDownloader = new HttpClientDownloader();
httpClientDownloader.setProxyProvider(SimpleProxyProvider.from(new Proxy("101.101.101.101", 8888), new Proxy("102.102.102.102", 8888)));

免费代理服务器

1、目前用的还不错的有快代理,有免费 和 收费版,如果是咱们自己搞着玩,可以使用免费版的,如果对代理服务器要求比较高,可以用他们的付费版的。我之前做过一个爬取财经数据的程序,对代理要求比较高,使用的是他们的收费版的,用下来还可以的。如果你们有发现更好的,可以留言,分享分享,谢谢

对于快代理我这边提供一个代理代码,可以拿去直接用:

public class KuaidailiProxyProvider implements ProxyProvider {
private Logger logger = Logger.getLogger(KuaidailiProxyProvider.class); private List<Proxy> proxyList = new ArrayList<>();
private volatile Map<String, ArrayBlockingQueue<Proxy>> siteProxysMap = new HashMap<String, ArrayBlockingQueue<Proxy>>();
private Object siteProxysMapLock = new Object();
//获取代理信息的地址
private String apiurl;
//用户名
private String username;
//密码
private String password;
private volatile static KuaidailiProxyProvider instance = null; public KuaidailiProxyProvider(String apiurl, String username, String password) {
this.apiurl = apiurl;
this.username = username;
this.password = password;
this.init();
} public static KuaidailiProxyProvider getInstance(String apiurl, String username, String password) {
if (instance == null) {
synchronized (KuaidailiProxyProvider.class) {
if (instance == null) {
instance = new KuaidailiProxyProvider(apiurl, username, password);
}
}
}
return instance;
} private void init() {
try {
logger.info("get proxy");
String s = HttpsUtil.requestGet(this.apiurl);
logger.info(s);
if (StringUtil.isNotEmpty(s)) {
final JSONObject jsonObject = JSON.parseObject(s);
if (jsonObject == null) {
return;
}
final JSONObject data = jsonObject.getJSONObject("data");
if (data == null) {
return;
}
final JSONArray proxy_list = data.getJSONArray("proxy_list");
if (proxy_list == null && proxy_list.size() == 0) {
return;
}
List<String> tempList = new ArrayList<>();
for (int i = 0; i < proxy_list.size(); i++) {
final String string = proxy_list.getString(i);
final String[] split = string.split(":");
proxyList.add(new Proxy(split[0], Integer.parseInt(split[1]), this.username, this.password));
}
}
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
} private ArrayBlockingQueue<Proxy> get(String key) {
try {
ArrayBlockingQueue<Proxy> queue = siteProxysMap.get(key);
if (queue == null) {
synchronized (siteProxysMapLock) {
queue = siteProxysMap.get(key);
if (queue == null) {
ArrayBlockingQueue<Proxy> proxies = new ArrayBlockingQueue<Proxy>(proxyList.size());
for (Proxy proxy : proxyList) {
proxies.put(proxy);
}
siteProxysMap.put(key, proxies);
}
}
}
} catch (InterruptedException e) {
this.logger.error(e.getMessage(), e);
}
return siteProxysMap.get(key);
} @Override
public void returnProxy(Proxy proxy, Page page, Task task) {
this.logger.info(proxy);
try {
String key = getKey(task);
this.get(key).put(proxy);
} catch (InterruptedException e) {
this.logger.error(e.getMessage(), e);
}
} private String getKey(Task task) {
final String domain = task != null && task.getSite() != null ? task.getSite().getDomain() : null;
return StringUtil.isNotEmpty(domain) ? domain : KuaidailiProxyProvider.class.getName();
} @Override
public Proxy getProxy(Task task) {
Proxy proxy = null;
try {
proxy = this.get(this.getKey(task)).take();
this.logger.info(proxy);
} catch (InterruptedException e) {
logger.error(e.getMessage(), e);
}
return proxy;
}
}

调用KuaidailiProxyProvider.getInstance获取代理实例。

可以关注公众号:路人甲Java,获取年薪50万课程,获取最新文章。

java爬虫系列第五讲-如何使用代理防止爬虫被屏蔽?的更多相关文章

  1. Java 设计模式系列(十二)代理模式

    Java 设计模式系列(十二)代理模式 代理模式是对象的结构模式.代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用. package com.github.binarylei.de ...

  2. python爬虫系列(1)——一个简单的爬虫实例

    本文主要实现一个简单的爬虫,目的是从一个百度贴吧页面下载图片. 1. 概述 本文主要实现一个简单的爬虫,目的是从一个百度贴吧页面下载图片.下载图片的步骤如下: 获取网页html文本内容:分析html中 ...

  3. java爬虫系列目录

    1. java爬虫系列第一讲-爬虫入门(爬取动作片列表) 2. java爬虫系列第二讲-爬取最新动作电影<海王>迅雷下载地址 3. java爬虫系列第三讲-获取页面中绝对路径的各种方法 4 ...

  4. python 全栈开发,Day134(爬虫系列之第1章-requests模块)

    一.爬虫系列之第1章-requests模块 爬虫简介 概述 近年来,随着网络应用的逐渐扩展和深入,如何高效的获取网上数据成为了无数公司和个人的追求,在大数据时代,谁掌握了更多的数据,谁就可以获得更高的 ...

  5. 爬虫系列(三) urllib的基本使用

    一.urllib 简介 urllib 是 Python3 中自带的 HTTP 请求库,无需复杂的安装过程即可正常使用,十分适合爬虫入门 urllib 中包含四个模块,分别是 request:请求处理模 ...

  6. 爬虫系列(七) requests的基本使用

    一.requests 简介 requests 是一个功能强大.简单易用的 HTTP 请求库,可以使用 pip install requests 命令进行安装 下面我们将会介绍 requests 中常用 ...

  7. Python3爬虫系列:理论+实验+爬取妹子图实战

    Github: https://github.com/wangy8961/python3-concurrency-pics-02 ,欢迎star 爬虫系列: (1) 理论 Python3爬虫系列01 ...

  8. 爬虫系列(九) xpath的基本使用

    一.xpath 简介 究竟什么是 xpath 呢?简单来说,xpath 就是一种在 XML 文档中查找信息的语言 而 XML 文档就是由一系列节点构成的树,例如,下面是一份简单的 XML 文档: &l ...

  9. 爬虫系列(二) Chrome抓包分析

    在这篇文章中,我们将尝试使用直观的网页分析工具(Chrome 开发者工具)对网页进行抓包分析,更加深入的了解网络爬虫的本质与内涵 1.测试环境 浏览器:Chrome 浏览器 浏览器版本:67.0.33 ...

随机推荐

  1. nginx日志模块及日志定时切割

    一:作用 Ngx_http_log_module:定义日志格式,并且以指定的格式保存. 二:示例配置 log_format compression '$remote_addr - $remote_us ...

  2. HTML5网页录音和上传到服务器,支持PC、Android,支持IOS微信

    准备做一个网页版聊天界面,表情啊.图片啊.上传文件啊都应该要有,视频就算了,语音还是要的. 本文记录的是在网页上用GitHub上的Recorder进行在线录音和上传到服务器,前几天升了一下级,以后有时 ...

  3. 供应链金融&区块链应用

    现代管理教育对供应链的定义为“供应链是围绕核心企业,通过对商流,信息流,物流,资金流的控制,从采购原材料开始,制成中间产品以及最终产品,最后由销售网络把产品送到消费者手中的将供应商,制造商,分销商,零 ...

  4. java代码之美(11)---java代码的优化

    java代码的优化 随着自己做开发时间的增长,越来越理解雷布斯说的: 敲代码要像写诗一样美.也能理解有一次面试官问我你对代码有洁癖吗? 一段好的代码会让人看就像诗一样,也像一个干净房间会让人看去很舒服 ...

  5. 《前端之路》之 JavaScript 高级技巧、高阶函数(一)

    目录 一.高级函数 1-1 安全的类型检测 1-2 作用域安全的构造函数 1-3 惰性载入函数 1-4 函数绑定 1-5 函数柯里化 1-6 反函数柯里化 一.高级函数 1-1 安全的类型检测 想到类 ...

  6. Itest(爱测试),最懂测试人的开源测试管理软件隆重发布

    测试人自己开发,汇聚10年沉淀,独创流程驱动测试.度量展现测试人价值的测试协同软件,开源免费   官网刚上线,近期发布源码:http://www.itest.work 在线体验 http://www. ...

  7. 003-005:Java平台相关的面试题

    本文首发于公众号:javaadu 003:字节码是什么? 在Java中,字节码存放于以.class结尾的二进制文件. 字节码之于Java,类似于汇编语言之于C/C++.对于C/C++语言来说,不同的平 ...

  8. sqlite数据库如何远程连接?

    sqlite数据库如何远程连接代码如下:QSqlDatabase db =QSqlDatabase::addDatabase("QSQLITE"); db.setHostName( ...

  9. 个人整理的 Windows 下 .NET 开发必装的软件

    注: 最后更新时间:2019-03-15 一..NET 开发 1. 必装 软件名称 说明 下载地址 JetBrains Toolbox JetBrins 全家桶管理工具. 下载地址 JetBrains ...

  10. Windows7下chm文件打不开

    从网上下载的CHM文件在Windows7系统中无法显示内容,是因为Windows7系统中的浏览器下载的文件是被默认为锁定的,所以打开以后是无法显示里面的具体内容的,解决的办法: 选中这个CHM文件: ...