最近做项目需要从新浪微博中大批量爬取新浪微博数据,当然大家熟知的方法就是使用API来获取数据,但是这样有个限制,只能搜索相应用户的home_timeline,不能按关键字大批量(几十万甚至百万千万级别数据),而且API还有一个限制就是每小时请求次数时有限的。当然,各大网站都有自己的防护措施,当它检测到某个ip在短时间内发起大量请求时,它就会认为这种操作有问题,需要填写验证码,或者直接封ip,几天后才可以重新解锁使用,这种机制是很有必要的,因为这样可以防范恶意的连续请求导致服务器瘫痪。其他就不多说了,直接看核心代码吧:
String termString[] = { "中国", "日本", "韩国", "美国", "俄国", "英美" };
String userAgent = "User-Agent";
String userAgentValue = "Mozilla/12.0 (compatible; MSIE 8.0; Windows NT)";
String contentType = "Content-Type";
String contentTypeValue = "application/x-www-form-urlencoded";
String pathString = "";
for (int i = 0; i < termString.length; i++) {
for (int j = 0; j < 50; j++) {//对每个term(搜索关键字),取50页的内容
pathString = "http://s.weibo.com/weibo/"
+ URLEncoder.encode(termString[i], "UTF-8") + "&page="
+ (j + 1);
try {
OutputStream os = null;
InputStreamReader isr = null;
URL url = new URL(pathString);
HttpURLConnection httpConn = (HttpURLConnection) url
.openConnection();
httpConn.setRequestMethod("POST");
httpConn.setConnectTimeout(60000);
httpConn.setReadTimeout(60000);
httpConn.setRequestProperty(userAgent, userAgentValue);
httpConn.setRequestProperty(contentType, contentTypeValue);
httpConn.setDoOutput(true);
httpConn.setDoInput(true);
os = httpConn.getOutputStream();
os.flush();
isr = new InputStreamReader(httpConn.getInputStream());
StringBuffer content = new StringBuffer();
int c;
while ((c = isr.read()) != -1) {
content.append((char) c);
}
System.out.println(decodeUnicode(content.toString()));
} catch (Exception e) {
e.printStackTrace();
}
Random random = new Random();
int slpmillsecs = 40000 + random.nextInt(20000) + 1;
Thread.sleep(slpmillsecs);// 停40~60s
}
}
一开始,我用10s左右的间隔时间,发现新浪还是能够检测出来,后来果断改的大一些,正常来说40s以下的间隔时间也是可以的,但是具体最小值是多少我没有测试,大家有兴趣可以试试。
PS:本文提出的爬取网页内容的方法仅供参考和自己以后翻看,我推算过这种采集数据花费的时间,跟使用API采集数据差不多甚至还要多一些,这里只是提供了这样一个采集新浪微博数据的思路,不喜勿喷。。。