我开发了一个爬虫程序使用的是httpclient4.3.5+jsoup1.7.2,发现在爬取数据的时候有的时候会卡住,发现每次都是执行到
response = httpClient.execute(httpGet);
这句话的时候,我百度之后,发了一句话说的很好:
我们知道Socket在读数据的时候是阻塞式的,如果没有读到数据程序会一直阻塞在那里。在同步请求的时候我们肯定是不能允许这样的情况发生的,这就需要我们在请求达到一定的时间后控制阻塞的中断,让程序得以继续运行。Socket为我们提供了一个setSoTimeout()方法来设置接收数据的超时时间,单位是毫秒。当设置的超时时间大于0,并且超过了这一时间Socket还没有接收到返回的数据的话,Socket就会抛出一个SocketTimeoutException。
于是我设置了sockettimeout,但是还是会卡住,有的人说将httpGet释放,response释放,对我的程序来说都没啥用,我发现卡住之后response会没有返回值。后来我在网上继续寻找答案,看到一篇博文,说是可以使用定时器来设置时间,如果httpClient.execute(httpGet)执行过长,将httpClient关闭。我最初写代码的时候将httpClient写成了单例!!!结果httpClient释放资源之后,再次请求,就报错,代码写了一段时间不看很容易忘记。
代码修改之后有了下面的代码:
public CrawlResultPojo crawler(ProxyIP proxy, int index, String proxyPath) {
CrawlResultPojo crawlResultPojo = new CrawlResultPojo();
if (urlPojo == null || urlPojo.getUrl() == null || urlPojo.getUrl().equals("")) {
crawlResultPojo.setSuccess(false);
crawlResultPojo.setPageContent(null);
return crawlResultPojo;
}
BufferedReader br = null;
CloseableHttpResponse response = null;
RequestConfig requestConfig = null;
URIBuilder uriBuilder = null;
Map<String, Object> parasMap = null;
List<NameValuePair> params = null;
BasicNameValuePair basicNameValuePair = null;
HttpGet httpGet = null;
HttpPost httpPost = null;
HttpEntity entity = null;
InputStreamReader isr = null;
int httpCode = 0;
CloseableHttpClient httpClient = null;
try {
params = new LinkedList<>();
parasMap = urlPojo.getParasMap();
uriBuilder = new URIBuilder(urlPojo.getUrl());
if (proxy == null) {
requestConfig = RequestConfig.custom().setConnectTimeout(2000).setSocketTimeout(5000)