爬虫模拟登陆博客园,爬取信息,发送"闪存"消息等操作(微博、BBS同理)
朋友们,好久不见了。最近忙着其他事情,一直没有到博客园转转。你们还好吗?
分享最近项目里面的一小段代码吧。
描述:由于某种需要,需要抓取某些特定网站上的信息,其中有一些网站是需要登录后才能抓取信息的。这就牵扯到如何模拟登陆,登陆后又应该进行哪些处理可以爬取其他页面的信息。
一般来说,需要登录的网站都没有禁用cookie,(如果对cookie和http协议不了解,请自行百度),一般模拟登陆都是利用这一特性进行的。
主要过程如图所示:
本人项目中代码也是大概这么一个过程,我利用了开源工具httpClient 。因为该工具对HTTP协议进行了很好的封装和管理,当然也实现了http中所有的协议,比如get,post等等。
/*
* 测试代码
*/
public static void main(String[] args) throws ClientProtocolException, IOException {
// TODO Auto-generated method stub
String message="Hello,World!";
DefaultHttpClient client=getHttpClient();
if(sendMessage(client, message))
System.out.println("发送成功");
else
System.out.println("发送失败");
}
/***
* 得到一个登陆后添加了cookie的连接。
*
* @author http://www.cnblogs.com/xiaoyi115/
* */
public static DefaultHttpClient getHttpClient() throws ClientProtocolException, IOException{
DefaultHttpClient client=new DefaultHttpClient();
List<NameValuePair> nvps=getNameValuePairs();
String uri="http://passport.cnblogs.com/login.aspx";
List<Cookie> cookies=getCookies( nvps, uri);
for (Cookie cookie : cookies) {
client.getCookieStore().addCookie(cookie);
}
return client;
}
/***
* 显示发送的消息是否成功
* @param client 一个连接
* @param message 需要发送的消息
* @return 返回发送是否成功
* @author http://www.cnblogs.com/xiaoyi115/
* */
public static boolean sendMessage(DefaultHttpClient client,String message) throws ParseException, IOException{
HttpPost post=new HttpPost("http://home.cnblogs.com/ajax/ing/Publish");
post.addHeader("Accept", "application/json, text/javascript, */*; q=0.01");
post.addHeader("Accept-Encoding", "gzip,deflate,sdch");
post.addHeader("Accept-Language", "zh-CN,zh;q=0.8,en;q=0.6");
post.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.154 Safari/537.36");
post.addHeader("Content-Type", "application/json; charset=UTF-8");
post.addHeader("Origin", "http://passport.cnblogs.com");
post.addHeader("Referer", "http://passport.cnblogs.com/login.aspx?ReturnUrl=http%3A%2F%2Fwww.cnblogs.com%2F");
String xjson="{'content':'"+message+"','publicFlag':1}";
StringEntity entity=new StringEntity(xjson,"utf-8");
post.setEntity(entity);
HttpResponse respons=client.execute(post);
if(respons.getStatusLine().getStatusCode()==200&(EntityUtils.toString(respons.getEntity()).contains(message)))
return true;
else
return false;
//System.out.println(respons.getStatusLine().getStatusCode());
//System.out.println(EntityUtils.toString(respons.getEntity()));
}
/***
* 登陆时需要post的对象
*
* @return 返回对象集合
*
* @author http://www.cnblogs.com/xiaoyi115/
* */
public static List<NameValuePair> getNameValuePairs(){
ArrayList<NameValuePair> nvps=new ArrayList<NameValuePair>();
nvps.add(new BasicNameValuePair("__VIEWSTATE", "/wEPDwUKMTk0MDM4Nzg5MGQYAQUeX19Db250cm9sc1JlcXVpcmVQb3N0QmFja0tleV9fFgEFC2Noa1JlbWVtYmVy36jcXkF+JKEwq4mk1eC4ETqcaTA="));
nvps.add(new BasicNameValuePair("__EVENTVALIDATION", "/wEdAAW9J9gK2KAJMjMp9r0ov6f2hI6Xi65hwcQ8/QoQCF8JIahXufbhIqPmwKf992GTkd0wq1PKp6+/1yNGng6H71Uxop4oRunf14dz2Zt2+QKDEEdfo2FEmOcxajQv/HKJB0yp2y8y"));
nvps.add(new BasicNameValuePair("tbUserName", "潇一115"));
nvps.add(new BasicNameValuePair("tbPassword", "*******"));
nvps.add(new BasicNameValuePair("btnLogin", "登 录"));
nvps.add(new BasicNameValuePair("txtReturnUrl", "http://www.cnblogs.com/"));
return nvps;
}
/***
* 得到登陆后的cookie
* @return 返回cookies
*
* @author http://www.cnblogs.com/xiaoyi115/
* */
public static List<Cookie> getCookies( List<NameValuePair> nvp,String uri) throws ClientProtocolException, IOException{
DefaultHttpClient client=new DefaultHttpClient();
HttpPost post=new HttpPost(uri);
post.addHeader("Accept-Encoding", "gzip,deflate,sdch");
post.addHeader("Accept-Language", "zh-CN,zh;q=0.8,en;q=0.6");
post.addHeader("Content-Type", "application/x-www-form-urlencoded");
post.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.154 Safari/537.36");
post.addHeader("Origin", "http://passport.cnblogs.com");
post.addHeader("Referer", "http://passport.cnblogs.com/login.aspx?ReturnUrl=http%3A%2F%2Fwww.cnblogs.com%2F");
post.setEntity(new UrlEncodedFormEntity(nvp,HTTP.UTF_8));
client.execute(post);
List<Cookie> cookies=client.getCookieStore().getCookies();
return cookies;
}
另外,对于爬虫来说,对网页的分析也是一件非常重要的事情。推荐开源工具htmlparser.
新浪微博的登陆会比博客园的登陆稍微难一些。新浪微博会有一步预登陆,获取到一些信息,利用这些信息再进行登陆。
当然,项目中的爬虫远比这个要复杂。需要多线程,既然用到了多线程,就要对线程进行管理、通信,牵扯多个线程如何配合的问题。另外爬取策略也需要考虑,一般爬取在大的方面会有深度优先和广度优先。当然,不是简单的深度或广度,一般需要进行优化,和停止策略。对于同一个站点,不能过于频繁的爬取,这样很容易被禁IP。
爬虫需要了解的东西还很多。就扯这么多吧。
版权所有,欢迎转载,但是转载请注明出处:潇一