GuozhongCrawler看准网爬虫动态切换IP漫爬虫
有些关于URL去重的方面代码没有提供,须要自己去实现。主要这里提供思路
项目地址:http://git.oschina.net/woshidaniu/GuozhongCrawler/tree/master/example/changeProxyIp/
首先爬虫入口类:
public class PervadeSpider {
public static void main(String[] args) {
CrawTaskBuilder builder = CrawlManager.getInstance()
.prepareCrawlTask("看准网漫爬虫", DefaultPageDownloader.class)
.useThread(200)// 使用多个线程下载
.useDynamicEntrance(DynamicEntranceImpl.class)
.useProxyIpPool(KanzhunProxyIpPool.class, 800, 1000 * 60 * 20, 30)
.useQueueSimpleBlockingRequest()//採用广度优先策略,当然redis队列也是fifo。
假设想做分布式爬虫的话能够设置redis队列
.usePageEncoding(PageEncoding.UTF8);
CrawlTask spider = builder.build();
CrawlManager.getInstance().start(spider);
}
public static final class DynamicEntranceImpl extends DynamicEntrance{
@Override
public List<StartContext> loadStartContext() {
StartContext context = new StartContext();
context.injectSeed(context.createPageRequest("http://www.kanzhun.com/companyl/search/?
ka=banner-com", ExtractUrlPageProcessor.class));//公司
context.injectSeed(context.createPageRequest("http://www.kanzhun.com/salaryl/search/?stype=&ka=banner-salary", ExtractUrlPageProcessor.class));//工资
context.injectSeed(context.createPageRequest("http://www.kanzhun.com/jobl/p/?
ka=banner-recruit", ExtractUrlPageProcessor.class));//招聘
context.injectSeed(context.createPageRequest("http://www.kanzhun.com/interviewl/search/?stype=&ka=banner-interview", ExtractUrlPageProcessor.class));//面试
context.injectSeed(context.createPageRequest("http://www.kanzhun.com/topic/100.html?ka=com-topic-1", ExtractUrlPageProcessor.class));//公司之最
return Arrays.asList(context);
}
}
}
动态代理IP提供类:
public class KanzhunProxyIpPool extends ProxyIpPool {
public static final String IP_RESOURCE = "地址忽略";//地址请求的个数必须设置为initProxyIp(int size)中size的个数
public KanzhunProxyIpPool(int initSize, long pastTime, int max_use_count) {
super(initSize, pastTime, max_use_count);
}
private Pattern extractIp = Pattern.compile("([\\d]{1,3}\\.[\\d]{1,3}\\.[\\d]{1,3}\\.[\\d]{1,3}):(\\d+)");
@Override
protected List<ProxyIp> initProxyIp(int size) throws Exception {
List<ProxyIp> ip = new ArrayList<ProxyIp>();
URL url = null;
BufferedReader br = null;
StringBuffer buf = new StringBuffer();
try {
url = new URL(IP_RESOURCE);
InputStream in = url.openStream();
br = new BufferedReader(new InputStreamReader(in,"utf-8"));
String temp = null;
while((temp = br.readLine())!=null){
buf.append(temp).append("\n");
}
ProxyIp proxy = null;
Matcher matcher = extractIp.matcher(buf);
while(matcher.find()){
proxy = new ProxyIp(matcher.group(1), Integer.parseInt(matcher.group(2)));
ip.add(proxy);
}
} catch (Exception e) {
e.printStackTrace();
System.out.println(buf);
}finally{
if(br != null){
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return ip;
}
}
漫爬页面处理类:
public class ExtractUrlPageProcessor implements PageProcessor {
private String domain = "http://www.kanzhun.com";
private List<URLFilter> urlFilters = new ArrayList<URLFilter>();
private List<Pattern> urlRegulars = null;
public ExtractUrlPageProcessor(){
System.out.println("载入漫爬抽取URL正则");
urlRegulars = ConfigReader.getExtractRegular();
System.out.println("载入漫爬规则完成");
addURLFilter(new URLFilter() {
@Override
public boolean filter(String url) {
return !url.contains("javascript");//去除jquery标签
}
});
addURLFilter(new URLFilter() {
@Override
public boolean filter(String url) {
return url.contains("http://www.kanzhun.com");//保证域名内URL
}
});
addURLFilter(new URLFilter() {
@Override
public boolean filter(String url) {
for (Pattern pattern : urlRegulars) {
boolean result = pattern.matcher(url).find();
if(result)
return true;
}
return false;//保证url符合urlRegulars里随意一个正则
}
});
}
/**
* kanzhunId抽取正则
*/
final static Pattern[] idExtracts = new Pattern[]{
Pattern.compile("gso(\\d+)[^\\d]+"),//简单介绍抽取公司id
Pattern.compile("gsr(\\d+)[^\\d]+"),//点评抽取公司id
Pattern.compile("gsm(\\d+)[^\\d]+"),//面试抽取公司id
Pattern.compile("gsx(\\d+)[^\\d]+"),//工资抽取公司id
Pattern.compile("g(\\d+)[^\\d]+"),//招聘抽取公司id
Pattern.compile("gsp(\\d+)[^\\d]+"),//照片抽取公司id
Pattern.compile("gsl(\\d+)[^\\d]+")//员工抽取公司id
};
@Override
public PageScript getJavaScript() {
// TODO Auto-generated method stub
return null;
}
private Pattern normalContain = Pattern.compile("看准网");
@Override
public Pattern getNormalContain() {
return normalContain;
}
@Override
public void process(OkPage page,StartContext context,List<BasicRequest> queue,List<Proccessable> objectContainer) throws Exception {
// TODO Auto-generated method stub
/**
* 每一个页面抽取的符合urlRegulars规则的url
*/
Set<String> extractUrls = new HashSet<String>();
/**
* 每一个页面全部的kanzhunId
* 这里解释下比方阿里巴巴的首页是http://www.kanzhun.com/gso9012.html?ka=com1-title
* 那个阿里巴巴的kanzhunId就是9012
* 我们能够依据这个推导出阿里巴巴的
* 点评页:http://www.kanzhun.com/gsr9012.html?ka=com-blocker1-review
* 面试页:http://www.kanzhun.com/gsm9012.html?ka=com-blocker1-interview
* 工资页:http://www.kanzhun.com/gsx9012.html?ka=com-blocker1-salary
* 招聘页:http://www.kanzhun.com/job/g9012.html?ka=com-blocker1-job
* 照片页:http://www.kanzhun.com/gsp9012.html?ka=com-blocker1-photo
* 员工页:http://www.kanzhun.com/gsl9012.html?ka=com-blocker1-employee
*
*/
Set<String> kanzhunIds = new HashSet<String>();
Document doc = Jsoup.parse(page.getContent());
Elements allLinks = doc.select("a");
String href = null;
for (Element link : allLinks) {
href = link.attr("href");
if(href.startsWith("/")){
href = domain+href;
}
if(pass(href)){
extractUrls.add(href);
}
//抽取页面全部包括的kanzhunID
for (Pattern pattern : idExtracts) {
Matcher matcher = pattern.matcher(href);
if(matcher.find()){
kanzhunIds.add(matcher.group(1));
}
}
}
//step1
System.out.println(page.getRequest().getUrl()+"抽取了URL"+extractUrls.size()+"个:");
//对url去重(这个须要你们自己实现这里用伪代码表示)
System.out.println("去出反复url...");
//step2
System.out.println(page.getRequest().getUrl()+"抽取了kanzhunId"+kanzhunIds.size()+"个:");
//对抓过的kanzhunId进行去重(这个须要你们自己实现这里用伪代码表示)
System.out.println("kanzhunId进行去重...");
//将抽取的URL增加到队列
for (String extractUrl:extractUrls) {
PageRequest pageRequest = context.createPageRequest(extractUrl, ExtractUrlPageProcessor.class);
queue.add(pageRequest);//加到队列
}
//将抽取的kanzhunId封装成每一个企业的主页URL。
抓取企业信息
for (String kanzhunId:kanzhunIds) {
PageRequest pageRequest = context.createPageRequest("http://www.kanzhun.com/gso"+kanzhunId+".html?
ka=com1-title", CompanyPageProcessor.class);
queue.add(pageRequest);//加到队列
}
}
@Override
public void processErrorPage(Page arg0, StartContext arg1) throws Exception {
// TODO Auto-generated method stub
}
/**
* 对每一个URL进行filter
* @param url
* @return
*/
private boolean pass(String url){
for (URLFilter filter : urlFilters) {
if(!filter.filter(url)){
return false;
}
}
return true;
}
public void addURLFilter(URLFilter urlFilter){
urlFilters.add(urlFilter);
}
}
最后URL抽取规则贴上。
<ExtractRegular>
<!-- 行业URL 或者 公司标签 或者 城市-->
<Regular>/pl[act][a-z0-9]+\.html</Regular>
<!-- 行业URL 或者 城市-->
<Regular>/xs[ac][a-z0-9]+\.html</Regular>
<!-- 招聘分类URL-->
<Regular>/jobli_.+</Regular>
<!-- 面试分类URL-->
<Regular>/ms[ac].+</Regular>
<!-- 公司之最-->
<Regular>/topic/[a-z0-9]+</Regular>
<!-- 热门职位-->
<Regular>/salary/(\d+)/</Regular>
<Regular>/interview/(\d+)/</Regular>
</ExtractRegular>
搞定。
GuozhongCrawler看准网爬虫动态切换IP漫爬虫的更多相关文章
- Python 爬虫使用动态切换ip防止封杀
对于爬虫被封禁 ! 爬虫一般来说只要你的ip够多,是不容易被封的. 一些中小网站要封杀你,他的技术成本也是很高的,因为大多数网站没有vps,他们用的是虚拟空间或者是sae,bae这样的paas云. 其 ...
- (转)内网网站发布到外网-nat123动态公网IP动态域名解析
环境描述: 路由器分配的是动态公网IP,且有路由器登录管理权限,网站服务器部署在路由器内部网络.如何将内网网站发布到外网大众访问? 解决方案: 内网使用nat123动态域名解析,将域名实时固定解析到路 ...
- node.js 爬虫动态代理ip
参考文章: https://andyliwr.github.io/2017/12/05/nodejs_spider_ip/ https://segmentfault.com/q/10100000081 ...
- [转]IP动态切换脚本
因为公司办公室要设置固定IP才行,而家里的IP段和公司是不一样的,家里采用了DHCP机制,这样每次就得改IP设置,很是不方便,就写了这个脚本来动态切换,很流畅的说!WINXP,WIN7测试通过~嘿嘿~ ...
- python爬虫-《笔趣看》网小说《悟空看私聊》
小编是个爱看小说的人,哈哈 # -*- coding:UTF-8 -*- ''' 类说明:下载<笔趣看>网小说<悟空看私聊> ''' from bs4 import Beaut ...
- 简单爬虫,突破IP访问限制和复杂验证码,小总结
简单爬虫,突破复杂验证码和IP访问限制 文章地址:http://www.cnblogs.com/likeli/p/4730709.html 好吧,看题目就知道我是要写一个爬虫,这个爬虫的目标网站有 ...
- 随机切换IP和UA
在爬虫爬取过程中,网站会根据我们的IP和UA去确认到底是浏览器操作还是爬虫在操作,所以,为了让爬虫不被网站禁止,随机切换Ip 和UA是很重要的,因为这个类在各个爬虫中经常要用到,所以可以自已维护一份随 ...
- 动态切换数据库(EF框架)
文章简略:本文测试项目为Silverlight+EF+RIA Service动态切换数据库的问题 通常,Ado.net EntityFramework的数据库连接字符串Connect ...
- ExtJS动态切换主题
ExtJS动态切换主题 在Sencha Cmd构建的Ext程序中怎么去动态切换主题,目前看好像只能单一切换,但是在官网文档找到了答案 Resource Management在上一节通过 ...
随机推荐
- 类的const和非const成员函数的重载
我们从一个例子说起,来看上一篇文章中的String类, 我们为它提供一个下标操作符([ ])以读写指定位置的字符(char). 只要了解过C++的操作符重载的语法,很快就可以写出下面这个[]操作符重载 ...
- 每日一小练——Armstrong数
上得厅堂.下得厨房,写得代码,翻得围墙,欢迎来到睿不可挡的每日一小练! 题目:Armstrong数 内容: 在三位的正整数中,比如abc.有一些能够满足a^3+b^3+c^3=abc的条件,也就是说各 ...
- phpsso 与 Discuz!
经过测试仍然有问题,phpcms登陆,论坛可以实现同步登陆,但论坛登陆phpcms无法同步登陆.但总体来说也能使用了.如果有更好的方法欢迎补充. 整合原理: UCenter 作服务端:phpsso 与 ...
- 解决 同时安装 python3,python2环境时,用pip安装 python3 包
应用场景 默认mac上已经安装了 python2; 而我又安装了 python3,并使用 python3; 安装了 pip 默认,pip安装的包安装在了 python2上了: 但是我想用 pip把安装 ...
- JDK中枚举的底层实现
前提 上一篇文章复习介绍了JDK中注解的底层实现,跟注解一样比较常用,但是底层实现比较神秘的还有枚举类型.趁着国庆假期的最后两天,把JDK中枚举的底层实现也进行一次探究. 通过例子查找本质 在探究JD ...
- Tetris
he Tetris game is one of the most popular computer games ever created. The original game was designe ...
- 微信群的id
今天网速慢了,竟然把微信群的id卡出来了,记录一下. 格式应该是一个像QQ群一样的数字,然后+@chatroom 看图! 文章来源:刘俊涛的博客 欢迎关注,有问题一起学习欢迎留言.评论.
- Adobe Audition3.0 找不到所支持的音频设备 请检查您的音频设置
Adobe Audition 找不到所支持的音频设备 请检查您的音频设置 解决方案: 运行regedit,打开注册表编辑器,定位到 HKEY_CLASSES_ROOT\CLSID\{AB7 ...
- java在线预览txt、word、ppt、execel,pdf代码
在页面上显示各种文档中的内容.在servlet中的逻辑 word: BufferedInputStream bis = null; URL url = null; HttpURLConnection ...
- 〖Android〗CM10.2编译错误解决
错误1: hardware/samsung/exynos4/hal/libhdmi/SecHdmi/SecHdmiV4L2Utils.cpp: In function 'int android::hd ...