免费代理IP的获取方式——编程实现

    网络爬虫,看似简单,实则不简单,做过网络爬虫工作比较会有体会。


    网络爬虫难点主要集中在1、屏蔽IP 2、验证码问题 3、用户登录问题 4、如何做到分布式 5、异步请求问题


    这次主要是想解决第一点 IP防屏蔽。网站屏蔽IP的唯一先决条件是检测到你的IP访问频率过快,解决的方式有两种:第一种是降低抓取频率,这样也就降低了抓取效率 第二种是使用大量的代理IP来进行抓取。


    之前一直通过购买代理IP的方式来解决,但是花销有点大,到最后快上万了,因为网上的代理IP都是按量购买的,而我们爬取的话基本长则都是一两个月的,虽说一天也就不到几十块钱,但是量大啊,还得考虑并发等等问题。实在是没辙,开始建立自己的IP库。比如在百度一搜 免费代理IP 里面下面一系列的代理IP网站都出来了


    blob.png 

    

    也许有人问:这不是这么多的代理IP吗,直接拿来用不就可以了嘛?我呵呵!!!接下来的您就不用看了。


    上面虽说免费代理IP一大片,但是能用的还是少量的,现在我们要解决的就是如果从这里面检索出那些可用的代理IP来,持续累计自然就形成了自己的代理IP库。

    

    通过这种方式,爬取一天的话可以获取到上千的可用代理IP,效果还是不错的。


    第一步的话,当然是找到可用的IP源了,这里我就拿 快代理 来做实验了。


     

    4061C27D-D546-48C0-973C-B7AD94D9DFC7.png


     打开他的免费代理IP页面 可以看到有上千页的代理IP,一开始的时候我通过全部遍历的形式来获取,结果基本在第15页之后 就没有可用的代理IP了,所以编程的时候需要限制抓取的页数,限制在15页,抓取到15页就不要再往下抓取了,否则徒劳无功。


     首先定义IP地址的匹配规则,以前是针对每个IP网站进行列表匹配,其实只要定义好IP地址的规则,直接使用内容页进行匹配即可。

    

String ipReg = "\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3} \\d{1,6}";


    之后就是获取页面内容了,这里采用Jsoup来进行获取,事实上使用JSoup来抓取网页内容是非常方便的,而且也可以作为API访问,JSON访问获取等,强力推荐。


    在用JSOUP抓取的时候,对于头部信息的设置,建议打开代理IP网站,将里面的header信息全部放入进去,这样基本百分比没问题。使用谷歌浏览器访问的话类似这种:


    FEF3FBDE-2C20-4422-8DDB-F52A1520F942.png

    

    详细示例代码为:


Document doc = Jsoup.connect(baseUrl + i + "/")
	.header("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8")
	.header("Accept-Encoding", "gzip, deflate, sdch")
	.header("Accept-Language", "zh-CN,zh;q=0.8,en;q=0.6")
	.header("Cache-Control", "max-age=0")
	.header("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36")
	.header("Cookie", "Hm_lvt_7ed65b1cc4b810e9fd37959c9bb51b31=1462812244; _gat=1; _ga=GA1.2.1061361785.1462812244")
	.header("Host", "www.kuaidaili.com")
	.header("Referer", "http://www.kuaidaili.com/free/outha/")
	.timeout(30*1000)
	.get();


    然后还需要考虑到翻页问题,实际上几乎所有代理IP网站的翻页都是很简单的那种,直接使用一个for循环就能搞定。设置最大访问页面即可。


    比如快代理的就是 http://www.kuaidaili.com/free/inha/2/ 直接改变后面的页数字就行了,设置最大页数为15.


    获取到页面之后,就是用IP规则来匹配了,使用java正则即可。


    在这里我将获取到的有效代理IP放在了Redis中,这样全平台就都可以借助于redis来使用代理IP共享,同时使用的是set来进行存储,可以设定代理IP的存在时间。使用的时候使用smember 共享,当然你也可以使用spop. 在使用之前再次检测一下代理IP的可用性,不可用的话直接spop掉 重新从ip库里获取就可以了。


    IP检测有效性:(注意:jsoup没有.proxy这个方法,是改进的版本)


package com.qianjieyun.bigdata.proxy;

import org.jsoup.Jsoup;

/**
 * 
 * ProxyUtil
 * @Description:TODO 代理IP工具
 * @author:千界云 http://qianjieyun.com
 * @email:[email protected]
 * @date 2016年9月14日
 */
public class ProxyUtil {

	//默认:分割
	public static String getProxy(){
		return RedisUtil.getRu().spop(Constant.REDIS_KEY_PROXY);
	}
	
	public static void putProxy(String ip, Integer port){
		RedisUtil.getRu().sadd(Constant.REDIS_KEY_PROXY, ip+":"+port);
	}
	
	public static boolean checkProxy(String ip, Integer port){
		try {
			//http://1212.ip138.com/ic.asp 可以换成任何比较快的网页
			Jsoup.connect("http://json.cn/")
					.timeout(3*1000)
					.proxy(ip, port, null)
					.get();
			System.out.println(ip+":"+port);
			return true;
		} catch (Exception e) {
			return false;
		}
	}
}


    最终完整的抓取 快代理 可用免费代理的代码为:

package com.qianjieyun.bigdata.proxy;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;

/**
 * 
 * ProxyCralwerUnusedVPN
 * @Description:TODO 免费代理IP获取 不需要使用VPN 国外代理IP网站抓取需要使用VPN
 * 在使用之前,请配置自己的Redis工具,如果不想使用,直接在代码中注释掉即可
 * @author:千界云 http://qianjieyun.com
 * @email:[email protected]
 * @date 2016年9月14日
 */
public class ProxyCralwerUnusedVPN {

	public static void main(String[] args) {
		ProxyCralwerUnusedVPN proxyCrawler = new ProxyCralwerUnusedVPN();
		
		proxyCrawler.startCrawler();
	}
	
	public void startCrawler(){
		//13 http://www.kuaidaili.com
		kuaidailiCom("http://www.kuaidaili.com/free/inha/", 15);
		kuaidailiCom("http://www.kuaidaili.com/free/intr/", 15);
		kuaidailiCom("http://www.kuaidaili.com/free/outha/", 15);
		kuaidailiCom("http://www.kuaidaili.com/free/outtr/", 15);
	}
	
	private void kuaidailiCom(String baseUrl,int totalPage){
		String ipReg = "\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3} \\d{1,6}";
		Pattern ipPtn = Pattern.compile(ipReg);
		
		for (int i = 1; i < totalPage; i++) {
			try {
				Document doc = Jsoup.connect(baseUrl + i + "/")
						.header("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8")
						.header("Accept-Encoding", "gzip, deflate, sdch")
						.header("Accept-Language", "zh-CN,zh;q=0.8,en;q=0.6")
						.header("Cache-Control", "max-age=0")
						.header("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36")
						.header("Cookie", "Hm_lvt_7ed65b1cc4b810e9fd37959c9bb51b31=1462812244; _gat=1; _ga=GA1.2.1061361785.1462812244")
						.header("Host", "www.kuaidaili.com")
						.header("Referer", "http://www.kuaidaili.com/free/outha/")
						.timeout(30*1000)
						.get();
				System.out.println(doc.text());
				Matcher m = ipPtn.matcher(doc.text());
				
				while(m.find()){
					String[] strs = m.group().split(" ");
					if(ProxyUtil.checkProxy(strs[0],Integer.parseInt(strs[1]))){
						RedisUtil.getRu().sadd(Constant.REDIS_KEY_PROXY, strs[0]+":"+strs[1]);
					}
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}	
}


    如果实际运行的话,顶多只能获取四五十个免费IP,但是注意这只是一个IP源啊。通过收集整理 到现在为止 直接可以访问的IP源有将近30个,需要使用VPN才能访问的有11个(国外的IP网站)


    所以这些就够用了。此源码下载, 另附含12个IP源的源码下载


    最终可用免费代理IP结果如下:

    

    85B293DF-62B6-42BB-873D-D5029E474AA8.png

        


猜你喜欢

转载自blog.csdn.net/fhg12225/article/details/52538957