访问我的博客

前言

在今年二月份在项目中引入了 WebMagic 技术,用来抓取合作方的书籍,详见之前文章:WebMagic之爬虫监控,这两天新接入了一个合作商,对方接口采取的是 HTTPS 协议,而以前合作商的接口全都是 HTTP 的,在接入这家合作商的时候,发现了问题,只要是 HTTPS 的 URL 全部无法爬取。

一、问题复现

在 WebMagic-core 包中,us.codecraft.webmagic.processor.example.GithubRepoPageProcessor 这个包下面是作者放的示例代码,拷贝这个类代码到新建的类中,右键运行这个类,运行后控制台报出错误:

[WARN ] 2018-05-12 13:28:11,828 download page https://github.com/code4craft error [us.codecraft.webmagic.downloader.HttpClientDownloader.download(HttpClientDownloader.java:91)]

进入这个类,定位到 HttpClientDownloader 源代码 85 行

public Page download(Request request, Task task) {
......
try {
httpResponse = httpClient.execute(requestContext.getHttpUriRequest(), requestContext.getHttpClientContext());
page = handleResponse(request, task.getSite().getCharset(), httpResponse, task);
onSuccess(request);
logger.info("downloading page success {}", request.getUrl());
return page;
} catch (IOException e) {
logger.warn("download page {} error", request.getUrl(), e);
onError(request);
return page;
} finally {
...
}
}

在 85 行此处断点 Debug 运行,发现此行抛出了 SSLException 异常。异常的内容是:

javax.net.ssl.SSLException: Received fatal alert: protocol_version

二、解决问题方法(一)

出现异常后,通过 Google 搜索了一下,找到了 WebMagic 作者黄大的解决方式,详见 Https下无法抓取只支持TLS1.2的站点

于是按照黄大说的方式来做

  1. 首先复制源码中的 HttpClientGeneratorHttpClientDownloader 到自己的项目中。

  2. 修改 HttpClientGenerator 的代码,只需要修改 buildSSLConnectionSocketFactory 这个方法为如下即可。

        ...
    private SSLConnectionSocketFactory buildSSLConnectionSocketFactory() {
    try {
    return new SSLConnectionSocketFactory(createIgnoreVerifySSL(), new String[]{"SSLv3", "TLSv1", "TLSv1.1", "TLSv1.2"},
    null,
    new DefaultHostnameVerifier()); // 优先绕过安全证书
    } catch (KeyManagementException e) {
    logger.error("ssl connection fail", e);
    } catch (NoSuchAlgorithmException e) {
    logger.error("ssl connection fail", e);
    }
    return SSLConnectionSocketFactory.getSocketFactory();
    }
    ...

    注意: DefaultHostnameVerifier 需要使用 org.apache.http.conn.ssl.DefaultHostnameVerifier,而不要使用 sun.net.www.protocol.https.DefaultHostnameVerifier

  3. 修改 HttpClientDownloader 中引用的 HttpClientGenerator 为你修改后的类。

  4. 设置爬虫 Spider 的 Downloader 为 你修改的 HttpClientDownloader

    Spider.create(new GithubRepoPageProcessor()).setDownloader(new HttpClientDownloader()).addUrl("https://github.com/code4craft").thread(5).run();
  5. 运行后,发现控制台已经可以正常输出所抓取网页的内容了

三、解决问题方法(二)

既然对方接口地址是 HTTPS 的,那我们访问他的 HTTP 接口不就没有这个问题了么?但是事实是,访问对方 HTTP 接口时,会自动跳转到 HTTPS 网址,所以这条路行不通。这时我忽然想到,之前使用 Nginx 解决前端跨域的方法,使用我方的 HTTP 域名,反向代理到对方的 HTTPS 网址是不是就解决了问题呢?于是对 Nginx 进行配置。

server {
listen 80;
server_name partner.domain.com; location / {
proxy_set_header Host github.com;
proxy_pass https://github.com/;
}
}

启动/重启 Nginx,将爬虫的地址由 https://github.com/code4craft 修改为 http://partner.domain.com/code4craft,使用 WebMagic 默认的 Downloader,启动爬虫

public class GithubRepoPageProcessor implements PageProcessor {

    private Site site = Site.me().setRetryTimes(3).setSleepTime(1000).setTimeOut(10000);

    @Override
public void process(Page page) {
System.out.println(page.getRawText());
} @Override
public Site getSite() {
return site;
} public static void main(String[] args) {
Spider.create(new GithubRepoPageProcessor()).addUrl("http://partner.domain.com/code4craft").thread(5).run();
}
}

发现控制台成功打印出了页面的内容,测试中,如果页面,页面的其他请求还是会错误,只有第一个页面是正确的,因此此方法只适合与 Ajax 类似的接口,我们是这样处理抓取 Https 问题的,因为第一种方法对于我们 JDK1.6 项目无效,第一种方法在 JDK 1.8 测试时可以正常抓取的。

后记

如果第一种方法解决不了你的问题,那就跟我一样弄一个临时域名反向代理吧,Nginx 在这方面还是蛮好用的。

解决WebMagic抓HTTPS时出现SSLException的更多相关文章

  1. 解决PHP curl https时error 77(Problem with reading the SSL CA cert (path? access rights?))

    服务器环境为CentOS,php-fpm,使用curl一个https站时失败,打开curl_error,捕获错误:Problem with reading the SSL CA cert (path? ...

  2. fiddler 解决不能抓https包的问题

    新解决方案 重置Fiddler,具体步骤: Tools > Fiddler Options > HTTPS > “Certificates generated by MakeCert ...

  3. Fiddler对https抓包时,提示"HTTPS decryption is disabled."

    安装了fiddlercertmaker.exe 后,对 https://www.baidu.com 进行抓包时,右侧界面提示"HTTPS decryption is disabled.&qu ...

  4. Fiddler对https抓包时,提示"HTTPS decryption is disabled."原因及破解

    Fiddler对https抓包时,提示"HTTPS decryption is disabled." 原因:没有启用 https 解密. 破解: ----------------- ...

  5. fiddler抓包时显示Tunnel to......443是怎么回事

    之前公司的app使用的http协议,因此不需要安装证书也能够转包. 后来改成https协议后,在使用fiddler进行抓包时,一直出现tunnel to 443. 百度了好久也没有具体的解决办法,后来 ...

  6. 【这特么是个坑。。。】iOS 10.3下解决Charles抓包ssl证书信任问题

    针对近期iOS 10.3以上的系统charles抓https信任问题 前言 最近iPhone系统更新到ios 10.3后,在公司里用Charles抓包竟然出现了一些问题,https的请求都会失败,提示 ...

  7. fidder 抓 https包配置方法(ios & android & pc浏览器)

    1. fidder抓https包的基本配置,可参见以下博文 http://blog.csdn.net/idlear/article/details/50999490 2. 遇到问题:抓包看只有Tunn ...

  8. Python 解决Python安装包时提示Unable to find vcvarsall.bat的问题

    解决Python安装包时提示Unable to find vcvarsall.bat的问题   by:授客 QQ:1033553122 问题 Python安装包时,提示Unable to find v ...

  9. [Python] 抓取时光网的电影列表并生成网页

    抓取时光网的电影列表并生成网页 源码 https://github.com/YouXianMing/BeautifulSoup4-WebCralwer 分析 利用BeautifulSoup进行分析网页 ...

随机推荐

  1. bzoj 1426 收集邮票

    f[i]:当前已拥有i种邮票,还需要买的邮票数的期望值. g[i]:当前已拥有i种邮票,还需要的钱的期望值. 每张邮票初始都是1元钱,每买一张邮票,还没购买的邮票每张都涨价1元.  f[i]=1+(n ...

  2. python中的异常

    Python提供了两个非常重要的功能来处理异常和错误: 1) 异常处理try-.except 2) 断言assert 异常和断言,可以用于我们调试python程序,跟踪程序执行状态,尽快排查问题. 3 ...

  3. Applet web端对文件的读取方式

    转载:http://www.exam8.com/computer/Java/zonghe/200708/659876.html ---- 我们知道,在Java Applet中出于安全性考虑,Apple ...

  4. 【STM32H7教程】第4章 STM32H7工程模板建立(MDK5)

    完整教程下载地址:http://forum.armfly.com/forum.php?mod=viewthread&tid=86980 第4章   STM32H7工程模板建立(MDK5) 本章 ...

  5. 基于ko-easyui实现的PC前端模板功能完善

    上一篇博客我向大家介绍了基于ko-easyui实现的开发模板,博客地址:https://www.cnblogs.com/cqhaibin/p/9825465.html#4095185.但在还遗留三个问 ...

  6. FreeSql 如何实现 Sqlite 跨库查询

    FreeSql 是 .NetFramework 4.6+..NetCore 下的 ORM 功能库,提供了丰富的功能,支持五种流行数据库 MySql/SqlServer/PostgreSQL/Oracl ...

  7. TFS线上生成环境发布历程

    继前文 TFS在项目中Devops落地进程(上) TFS在项目中DevOps落地进程(下) 自从之前将开发环境使用TFS进行了自动化之后,就享受在此成果中,其他后续进度就停顿了好一段时间. 毕竟在我们 ...

  8. RIP 实验

    一.环境准备 1. 软件:GNS3 2. 路由:c7200 二.实验操作 实验要求: 1. 理解 RIP 协议的工作原理 2. 理解 RIPv1.RIPv2 的特性 3. 掌握 RIP 协议的基本配置 ...

  9. JavaScript面试的完美指南(开发者视角)

    为了说明 JS 面试的复杂性,首先,请尝试给出以下结果: onsole.log(2.0 == "2" == new Boolean(true) == "1") ...

  10. ajax分页借鉴

    大家好这是我分页是用的代码希望大家可以相互交流ajax局部刷新 var pageindex = 1; var where = ""; var Pname = "" ...