java爬虫进阶 —— ip池使用,iframe嵌套,异步访问破解
写之前稍微说一下我对爬与反爬关系的理解
一、什么是爬虫
爬虫英文是splider,也就是蜘蛛的意思,web网络爬虫系统的功能是下载网页数据,进行所需数据的采集。主体也就是根据开始的超链接,下载解析目标页面,这时有两件事,一是把相关超链接继续往容器内添加,二是解析页面目标数据,不断循环,直到没有url解析为止。举个栗子:我现在要爬取苏宁手机价格数据,爬取思路就是拿到第一页的url作为蜘蛛网的中心点开始,爬取当页的手机详情页面的价格信息以及下一页的url并添加进容器,这样循环往复只要存放url容器里有就会一直往下机械执行,直到尾页没有下一页,这就是个扩散的过程。
二、什么是反爬虫以及为什么要反
反爬虫就是根据请求的一定的访问特征进行特殊处理,比如封Ip,弹验证码,返回不对应信息等等。
至于反爬的原因大概有几点
1、爬虫占总PV值高,就相当于一大群僵尸用户在访问你的网站,如果不管制,平白浪费服务器资源
2、某些则是出于商业竞争问题必须反爬,不让自己的商业信息被对手批量获取。之前看到一个例子很贴切,两个to B公司对外售卖商品,而一家写了一个自动爬取对手网站商品价格并于己方商品价格对比,保持低于一定价格进行动态浮动的脚本,顾客在买之前肯定会对同行业价格进行了解,于是结果你们都懂,对方很快发现这边的公司动的手脚,于是一场哄哄烈烈爬与反爬的较量开始了
3、还有就是一些无人认领的爬虫,可能用的人都忘了它的存在,一直在辛勤的爬
三 、常见的一些反爬手段
1、根据ip访问频率以及数量上限封锁ip,那个用户会一秒访问页面几十次或者连续几小时每隔半秒访问一次,动作很明显,封就完事了。
2、还有就是加载页面时动态获取,而不是静态数据了。举个栗子,某东的价格信息是动态加载
3、还有就是主体页面是异步加载嵌套在iframe里面的,并且 src="about:blank" ,这个正常下载下来的页面是没有内容的
4、故意挖坑,在页面做一些隐藏链接,如果被访问明显是爬进去的爬虫,接下来就是一顿封
5、后台对方问进行统计,对userAgent进行阈值判断,这个据说容易误伤
6、还有就是在页面展示上进行做手脚,有的价格信息用图片展示,去哪儿网
7、Cookie反扒,推荐链接,有一篇不错的介绍传送门
四、对前三种进行破解
1.设立ip池循环进行循环访问
首先我们从西刺等代理网站抓取一些免费的ip,其次进行无效ip过滤,这一步看情况吧,我个人实践是西刺网上得ip时而访问得通时而无效,所以我就去掉过滤得步骤,再就是用这些代理ip进行实际访问。
public class CsdnReadCount implements PageProcessor {
// IP地址代理库Map
private static Map<String, Integer> IPProxyRepository = new HashMap<>();
private static List<String> keysArray = new ArrayList<>();
private static int index;
private Site site = Site
.me()
.setDomain("http://www.xicidaili.com/")
.setSleepTime(3000).setUserAgent("Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36");
//按照顺序获取一个ip
public static HttpHost getRandomProxy() {
// 随机获取host:port,并构建代理对象
String host = keysArray.get(index);
if(index<keysArray.size()-1) {
index+=1;
}else {
index = 0;
}
int port = IPProxyRepository.get(host);
HttpHost proxy = new HttpHost(host, port); // 设置http代理
return proxy;
}
//抓取西刺网前两页上代理IP,因为不稳定,所以不做过滤
public void process(Page page) {
Html html = page.getHtml();
List<String> hosts = html.xpath("//div[@id='body']/table/tbody/tr[@class='odd']/td[2]").replace("<td>","").replace("</td>","").all();
List<String> ports = html.xpath("//div[@id='body']/table/tbody/tr[@class='odd']/td[3]").replace("<td>","").replace("</td>","").all();
keysArray.addAll(hosts);
for (int i=0;i<hosts.size();i++){
IPProxyRepository.put(hosts.get(i),Integer.valueOf(ports.get(i)));
}
}
public Site getSite() {
return site;
}
//请求页面,返回页面html代码
public static String getHttpContent(String url)throws IOException {
HttpHost proxy = getRandomProxy();
CloseableHttpClient httpClient = HttpClients.custom().setProxy(proxy).build(); // 创建httpclient对象
HttpGet request = new HttpGet(url); // 构建htttp get请求
request.setHeader("user-agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.221 Safari/537.36 SE 2.X MetaSr 1.0");
RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout(5000).setConnectionRequestTimeout(1000)
.setSocketTimeout(5000).build();
request.setConfig(requestConfig);
String host = null;
Integer port = null;
if (proxy != null) {
host = proxy.getHostName();
port = proxy.getPort();
}
request.setHeader("user-agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.221 Safari/537.36 SE 2.X MetaSr 1.0");
try {
CloseableHttpResponse response = httpClient.execute(request);
String result = EntityUtils.toString(response.getEntity(), "utf-8");
System.out.println("ip"+host+"连接成功"+index);
System.out.println(result);
System.out.println(new Date());
}catch (Exception c){
System.out.println("ip"+host+"连接失败···");
System.out.println("index:"+index);
System.out.println(new Date());
}
return null;
}
public static void main(String[] args) throws InterruptedException,IOException{
CsdnReadCount csdnReadCount = new CsdnReadCount();
Spider spider = Spider.create(csdnReadCount);
spider.addUrl("http://www.xicidaili.com/nn/1");
spider.addUrl("http://www.xicidaili.com/nn/2");
spider.run();
getHttpContent("https://blog.csdn.net/caihaijiang/article/list/1");
}
}
2.异步嵌套iframe的破解
这里用到了selenium需要引入依赖
准备: 下载谷歌驱动(谷歌驱动的版本一定要对应谷歌浏览器得版本,否则会报错)驱动下载传送门
引入所需依赖 :
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>3.3.1</version>
</dependency>
package sample;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import java.util.ArrayList;
import java.util.List;
public class SeleniumCloudMusic {
public static void main(String[] args) {
String key="webdriver.chrome.driver";
//谷歌驱动在你本地位置
String value="C:/Users/win 10/Desktop/暂存/chromedriver.exe";
System.setProperty(key,value);
WebDriver driver = new ChromeDriver();
driver.get("http://music.163.com/#");
WebElement iframe = driver.findElement(By.className("g-iframe"));
driver.switchTo().frame(iframe);
List<WebElement> elements = driver.findElements(By.xpath("//div[@class='u-cover u-cover-1']"));
List<String> playLists = new ArrayList<String>();
for (WebElement webElement:elements){
webElement.findElement(By.tagName("div"));
WebElement node = webElement.findElement(By.tagName("a"));
String url = node.getAttribute("href");
System.out.println(url);
playLists.add(url);
}
for (String str:playLists){
driver.get(str);
WebElement ifra = driver.findElement(By.className("g-iframe"));
driver.switchTo().frame(ifra);
WebElement subject = driver.findElement(By.tagName("h2"));
System.out.println(subject.getText());
}
}
}
3.动态加载破解
此处依旧是某些网站加载数据通过ajax异步加载,你直接爬是没有信息的,所以需要爬取页面数据过程中单独生成请求获取价格数据
package sample;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import us.codecraft.webmagic.Page;
import us.codecraft.webmagic.Site;
import us.codecraft.webmagic.Spider;
import us.codecraft.webmagic.processor.PageProcessor;
import org.json.JSONArray;
import org.json.JSONObject;
public class JDPriceSplider implements PageProcessor {
private Site site = Site
.me()
.setDomain("https://item.jd.com")
.setSleepTime(3000);
public void process(Page page) {
String url = page.getUrl().get();
String id = url.substring(url.lastIndexOf("/") + 1, url.lastIndexOf("."));
//拼接获取价格的url
String priceUrl = "https://p.3.cn/prices/mgets?pduid=1504781656858214892980&skuIds=J_" + id;
//获取价格json信息
String priceJson = getHttpContent(priceUrl);
if (priceJson != null) {
// 解析json [{"op":"4899.00","m":"9999.00","id":"J_3133843","p":"4799.00"}] 将该json字符串封装成json对象
if (priceJson.contains("error")) { // 返回{"error":"pdos_captcha"},说明价格url已经不可用,更换pduid再做解析
} else {
JSONArray priceJsonArray = new JSONArray(priceJson);
JSONObject priceJsonObj = priceJsonArray.getJSONObject(0);
String priceStr = priceJsonObj.getString("p").trim();
Float price = Float.valueOf(priceStr);
System.out.println(price);
}
}
}
//相当于页面进行ajax调用,单独获取价格
public static String getHttpContent(String url) {
CloseableHttpClient httpClient = HttpClients.custom().build(); // 创建httpclient对象
HttpGet request = new HttpGet(url); // 构建htttp get请求
request.setHeader("user-agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.221 Safari/537.36 SE 2.X MetaSr 1.0");
RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout(5000).setConnectionRequestTimeout(1000)
.setSocketTimeout(5000).build();
request.setConfig(requestConfig);
try {
CloseableHttpResponse response = httpClient.execute(request);
return EntityUtils.toString(response.getEntity());
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public Site getSite() {
return site;
}
public static void main(String[] args) {
//访问手机详情页面
Spider spider = Spider.create(new JDPriceSplider());
spider.addUrl("https://item.jd.com/6946605.html");
spider.run();
}
}
---------------------
作者:紫荆王朝
来源:CSDN
原文:https://blog.csdn.net/wu18296184782/article/details/80269274
版权声明:本文为博主原创文章,转载请附上博文链接!
java爬虫进阶 —— ip池使用,iframe嵌套,异步访问破解的更多相关文章
- 【python3】如何建立爬虫代理ip池
一.为什么需要建立爬虫代理ip池 在众多的网站防爬措施中,有一种是根据ip的访问频率进行限制的,在某段时间内,当某个ip的访问量达到一定的阀值时,该ip会被拉黑.在一段时间内被禁止访问. 这种时候,可 ...
- 建立爬虫代理IP池
单线程构建爬虫代理IP池 #!/usr/bin/python3.5 # -*- coding:utf-8 -*- import time import tempfile from lxml impor ...
- Python爬虫代理IP池
目录[-] 1.问题 2.代理池设计 3.代码模块 4.安装 5.使用 6.最后 在公司做分布式深网爬虫,搭建了一套稳定的代理池服务,为上千个爬虫提供有效的代理,保证各个爬虫拿到的都是对应网站有效的代 ...
- 维护爬虫代理IP池--采集并验证
任务分析 我们爬的免费代理来自于https://www.kuaidaili.com这个网站.用`requests`将ip地址与端口采集过来,将`IP`与`PORT`组合成`requests`需要的代理 ...
- python爬虫——建立IP池,将可用IP存放到redis
直接上代码,每行代码后面都有注释 import urllib.request import urllib import re import time import random import sock ...
- 利用代理IP池(proxy pool)搭建免费ip代理和api
先看这里!!!---->转载:Python爬虫代理IP池(proxy pool) WIIN10安装中遇到的问题: 一.先安装Microsoft Visual C++ Compiler for P ...
- 浅析Java中的线程池
Java中的线程池 几乎所有需要异步或并发执行任务的程序都可以使用线程池,开发过程中合理使用线程池能够带来以下三个好处: 降低资源消耗 提高响应速度 提高线程的可管理性 1. 线程池的实现原理 当我们 ...
- [爬虫进阶]使用Jsoup取代你的一切网络请求方法(java,post,get,代理IP)
[爬虫进阶]使用Jsoup取代你的一切网络请求方法(java,post,get,代理IP) 原文链接:https://www.cnblogs.com/blog5277/p/9334560.html 原 ...
- springboot实现java代理IP池 Proxy Pool,提供可用率达到95%以上的代理IP
一.背景 前段时间,写java爬虫来爬网易云音乐的评论.不料,爬了一段时间后ip被封禁了.由此,想到了使用ip代理,但是找了很多的ip代理网站,很少有可以用的代理ip.于是,抱着边学习的心态,自己开发 ...
随机推荐
- Mysql 函数使用记录(三)——UNIX_TIMESTAMP() 、UNIX_TIMESTAMP(date)
参考资料:https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_unix-timestamp UN ...
- IO模型——IO多路复用机制
(1)I/O多路复用技术通过把多个I/O的阻塞复用到同一个select.poll或epoll的阻塞上,从而使得系统在单线程的情况下可以同时处理多个客户端请求.与传统的多线程/多进程模型比,I/O多路复 ...
- centos7 查看防火墙状态
[root@xxx ~]# firewall-cmd --state not running
- ORA-03113: end-of-file on communication channel(归档满处理方法)
归档放在flash_recovery目录,由于归档占满了闪回目录,数据库启动报错ORA-03113: end-of-file on communication channel tail -1200f ...
- 关于JavaScript和Java的区别和联系
转载自: Javascript和Java除了名字和语法有点像,其他没有任何的关系. 做个比较是为了让大家更好的理解Javascript,事实上,两种语言根本没有可比性,是完全不同的. Javasc ...
- unbuntu安装Node.js
在官网https://nodejs.org/en/下载 手动创建链接的话,新安装的angular的ng typescript的tsc都要自己手动建立软链接,要不就每个工程里npm install一 ...
- openstack 重启服务命令
重启openstack的整个服务openstack-service restart 1. 重启dashboardservice httpd restart service memcached rest ...
- python 爬虫利器 Beautiful Soup
python 爬虫利器 Beautiful Soup Beautiful Soup 是一个可以从HTML或XML文件中提取数据的Python库.它能够通过你喜欢的转换器实现惯用的文档导航,查找,修改文 ...
- 日常英语---六、Maplestory Illium
日常英语---六.Maplestory Illium 一.总结 一句话总结: maplestory-['meiplstɔri] illium-镍铬合金 ['meiplstɔri] n. 枫之谷(网 ...
- (转)C#中base关键字的几种用法
base其实最大的使用地方在面相对性开发的多态性上,base可以完成创建派生类实例时调用其基类构造函数或者调用基类上已被其他方法重写的方法.例如: 2.1关于base调用基类构造函数 public c ...