以前抓淘宝数据和抓取优酷、土豆的源视频地址的时候需要通过IO流获取它们的HTML的源代码,为了方便所以写了这个工具类。
package com.hanyastar.util;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import com.hanyastar.exception.HanyaException;
import com.hanyastar.exception.HanyaToolsException;
/**
* HTML操作工具类。
* @author Belen
* @since 2013/05/25
*/
public abstract class HTMLUtils {
/**
* 通过BufferedInputStream,根据URL获取页面的源代码(源代码转化成小写字母返回).
*
* @param url
* url地址
* @param encode
* 编码 如果encode为空,则以GBK形式转换.
* @return 页面源代码
* @author Belen
* @throws HanyaException
*/
public static String getHtml2(String url, String encode)
throws HanyaException {
if(url == null)
throw new HanyaToolsException("url",new NullPointerException("url"));
if(encode == null){
encode = "GBK";
}
StringBuffer html = new StringBuffer();
String result = null;
URLConnection conn = null;
BufferedInputStream in = null;
try {
URL u = new URL(url);
conn = u.openConnection();
conn.setRequestProperty("User-Agent",
"Mozilla/4.0 (compatible; MSIE 7.0; NT 5.1; GTB5; .NET CLR 2.0.50727; CIBA)");
// 设置连接主机超时(单位:毫秒)
conn.setConnectTimeout(30000);
// 设置从主机读取数据超时(单位:毫秒)
conn.setReadTimeout(30000);
in = new BufferedInputStream(conn.getInputStream());
String inputLine;
byte[] buf = new byte[4096];
int bytesRead = 0;
while (bytesRead >= 0) {
inputLine = new String(buf, 0, bytesRead, "ISO-8859-1");
html.append(inputLine);
bytesRead = in.read(buf);
inputLine = null;
}
buf = null;
result = new String(html.toString().trim().getBytes("ISO-8859-1"),
encode).toLowerCase();
} catch (MalformedURLException e) {
throw new HanyaException(e);
} catch (IOException e) {
throw new HanyaException(e);
} finally {
try {
if (in != null) {
in.close();
}
if (conn != null) {
conn = null;
}
} catch (IOException e) {
throw new HanyaException(e);
}
}
return result;
}
/**
* 通过ByteArrayOutputStream,根据URL获取页面的源代码(HTML源代码返回).
*
* @param url
* @param encode 以encode编码类型转换数据,如果encode为空,则以GBK形式转换.
* @return
* @throws HanyaException
*/
public static String getHtml(String url,String encode) throws HanyaException{
if(url == null)
throw new HanyaToolsException("url",new NullPointerException("url"));
if(encode == null){
encode = "GBK";
}
InputStream in = null;
ByteArrayOutputStream bos = null;
try {
URL u = new URL(url);
HttpURLConnection httpConn = (HttpURLConnection) u.openConnection();
// 设置user agent确保系统与浏览器版本兼容
HttpURLConnection.setFollowRedirects(true);
httpConn.setRequestMethod("GET");
httpConn.setRequestProperty("User-Agent","Mozilla/4.0 " +
"(compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727)");
in = u.openStream();
// 设置连接主机超时(单位:毫秒)
httpConn.setConnectTimeout(30000);
// 设置从主机读取数据超时(单位:毫秒)
httpConn.setReadTimeout(30000);
int length = 0;
bos = new ByteArrayOutputStream();
while((length = in.read()) != -1) {
bos.write(length);
bos.flush();
}
in.close();
return new String(bos.toByteArray(),encode);
} catch (MalformedURLException e) {
throw new HanyaException(e);
} catch (IOException e) {
throw new HanyaException("流处理失败。"+e);
} finally{
try {
if(in != null){
in.close();
}
if(bos != null){
bos.close();
}
} catch (IOException e) {
throw new HanyaException(e);
}
}
}
}
获取网站的网页源码时,一般网站都有访问次数限制,也就是说如果发现一个IP多次访问他们的网站,一般都会在几分钟内限制你的IP,所以:
1、可以使用动态更换IP的方式来获取,但更换IP后获取源码的速度相对会降低。
2、也可以弄一个定时器或线程睡眠下,如果获取失败定时器将自动启动,定时5分钟后在继续访问,从而提高成功率。
以前帮一个公司弄一些淘宝数据,按他们的要求抓取一些数据从而生成报表,这些数据都是通过多次访问而组装起来的。
所以每一组数据大概需要请求淘宝10次左右,大概有20多万条数据,一共就需要请求超过200多万次。
一般情况下3分钟内同一IP请求淘宝的数据超过3000次就会限制你的IP(估计)。淘宝会在5分钟后解除限制,这时候我采用以上第二种方式就解决了这个问题。