java爬虫抓取动态网页(伪造网页浏览器证书伪造不到数据数据的解决方案)
优采云 发布时间: 2021-12-17 06:16java爬虫抓取动态网页(伪造网页浏览器证书伪造不到数据数据的解决方案)
这个java爬虫程序,在保证可以正常爬取网站的同时,增加了证书伪造,是针对网站反爬取无法抓取数据的解决方案。使用java ArrayList()抓取网站中的有效链接,同时释放资源,以免占用过多系统资源导致系统无法运行和终止。经过测试,确实可以用。
首先是伪造网页浏览器证书,取得网站的信任,才能顺利抓取数据。具体方案如下:
public static void getCertificate(){
HostnameVerifier hv = new HostnameVerifier() {
public boolean verify(String urlHostName, SSLSession session) {
System.out.println("Warning: URL Host: " + urlHostName + " vs. "
+ session.getPeerHost());
return true;
}
};
try {
trustAllHttpsCertificates();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
HttpsURLConnection.setDefaultHostnameVerifier(hv);
}
使用的代码片段太长,已经封装成函数,如下图:
private static void trustAllHttpsCertificates() throws Exception {
javax.net.ssl.TrustManager[] trustAllCerts = new javax.net.ssl.TrustManager[1];
javax.net.ssl.TrustManager tm = new miTM();
trustAllCerts[0] = tm;
javax.net.ssl.SSLContext sc = javax.net.ssl.SSLContext
.getInstance("SSL");
sc.init(null, trustAllCerts, null);
javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(sc
.getSocketFactory());
}
上述程序中使用的miTM函数如下:
static class miTM implements javax.net.ssl.TrustManager,javax.net.ssl.X509TrustManager {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public boolean isServerTrusted(java.security.cert.X509Certificate[] certs) {
return true;
}
public boolean isClientTrusted(java.security.cert.X509Certificate[] certs) {
return true;
}
public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType)throws java.security.cert.CertificateException {
return;
}
public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType)throws java.security.cert.CertificateException {
return;
}
}
好了,到了这里,获取证书的代码就结束了。
下一步是获取网页静态页面内容的功能:
public static String returnHtml(String string){
URL url = null;
try {
url= new URL(string);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
URLConnection connection = null;
try {
connection = url.openConnection();
}catch (IOException e1) {
e1.printStackTrace();
}
connection.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
try {
connection.connect();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
InputStreamReader isr = null;
try {
isr=new InputStreamReader(connection.getInputStream(),Charset.forName("UTF-8"));
}catch (IOException e1) {
e1.printStackTrace();
}
// 定义一个字符串用来存储网页内容
String result = "";
// 定义一个缓冲字符输入流
BufferedReader in = null;
// 初始化 BufferedReader输入流来读取URL的响应
in = new BufferedReader(isr);
// 用来临时存储抓取到的每一行的数据
String line;
try {
while ((line = in.readLine()) != null) {
// 遍历抓取到的每一行并将其存储到result里面
result += line;
}
} catch (IOException e) {
// TODO Auto-generated catch block
System.out.println("发送GET请求出现异常!" + e);
e.printStackTrace();
}
return result;
}
仅仅获取网页的静态资源是不够的。我们还需要抓取页面上的链接并进行迭代访问以获得我们最终想要的数据:
public static void getLink(String result){
Document doc = Jsoup.parse(result);
Elements table = doc.select("table.resulttable");
Elements es=table.select("a");
for (Iterator it = es.iterator(); it.hasNext();) {
Element e = (Element) it.next();
link.add(e.attr("href"));
System.out.println(e.text()+" "+e.attr("href"));
}
}
如果一些网站安全方面比较好,页面的数据会被Ajax动态加载。在这种情况下,我们需要通过ajax后台访问接口获取数据,然后进行链接拼接,然后直接访问后台数据接口获取json数据。具体方案如下:
<p>public static void getJson(ArrayList link){
FileOutputStream out=null;
try{
out = new FileOutputStream(new File("C:\\Users\\yihong\\Desktop\\数据抓取.txt"),true);
}catch(FileNotFoundException e){
}
String s;
for(int i=0;i