您的位置:首页 > 编程语言 > Java开发

Java抓取新浪微博首页数据

2015-08-06 22:12 483 查看
最近打算做一些东西,数据积累是储备的第一步,因此就不可避免地要写爬虫,抓取网页上的有效信息。因为期待数据有一些话题,量又比较大,考虑到经常逛微博,而且微博的话题又恰好可能满足后续的需求,因此就决定抓取新浪微博的数据。

那么问题就来了:

问题1:用什么语言?最常用的是java,HttpURLConnection等类又可以很方便地通过get或post请求获取url的数据,所以就先用Java实现吧,后续再考虑用python尝试。

问题2:新浪微博数据抓取需要登录,而登录过程又需要一点复杂的分析过程。在网上搜了一些资料,不过都已经失效。又急于抓取,所以决定先采用设置cookie的方式,绕过登录过程;先抓取,然后再研究登录方法【新浪微博cookie的有效时间?一般是设置30分钟】。

 

(临时)解决了以上两个问题,就可以先开始第一步,获取页面内容。先从首页开始。

 

首页地址:http://weibo.com/u/1596867051/home?wvr=5&lf=reg

使用httpfox,监控登录过程中的每次请求。

注意第一条请求,也就是首页url的这条请求。这是一条Get请求[废话],在左下角的Headers中可以看到请求头部的内容,有效的就是Cookie这里,只要在抓取时,设置头部的cookie内容为这里的内容即可。到这里,就拿到了首页,下拉加载前的全部页面内容。

 

第二阶段:

怎样从页面源码中得到所需的信息?

 

1、看需求【这也是废话。。。】

我关注的是右侧榜单,大家都可以看到,右侧有“亚洲新歌榜实时趋势”,“热门话题”,电影热议榜,好友动态,明星势力榜。计划为,定期抓取“热门话题排行榜”内容,解析页面内容后存储所需数据至本地,然后做成接口,提供给app调用。

热门话题页面:http://d.weibo.com/100803?refer=index_hot_new

同首页一样,get请求,头部设置上述的cookie,得到源码。内容结构:包括1小时排行和24小时排行,先以抓取1小时的排行榜为例。每项内容包括排名:top1,2,3; 话题名称 #话题# 形式, 类别/标签(明星、电视节目、电视剧...一位在微博做数据挖掘工作的同学好像就负责做这个),话题简介:“大型时尚真人秀节目《中国超模》5月21日起每周四21:20@重庆卫视 首播”,阅读量 主持人; 下面的问题就是从html中提取出这些元素。

 

页面结构分析:firefox,查看页面元素结构。热门话题内容在<divclass="m_wrap clearfix">标签下,<ul class="pt_ulclearfix">列表中,每一个li是一条话题。所以先定位到这里,然后在做进一步的解析。看起来很容易,是吗?那么我就错了。很遗憾,直接抓取过来的结果并非像查看源码那样是很标准的html,抓渠道的内容是包含了js的。因此,需要分析JS请求每个话题的构成。很幸运,JS的结构仍然是比较容易识别的,每一条话题都是这样的一个javascript代码段:

<script>

FM

.view({

"ns" : "pl.content.miniTab.index",

"domid" : "Pl_Discover_Pt6Rank__5",

"css" : ["style/css/module/discover/DSC_pictext_b.css?version=156d8fd88e66bcf3"],

"js" : "page/js/pl/content/miniTab/index.js?version=5ea4401897bd1150",

"html" : "xxxxxx"         //这里是一段很长的代码,封装了一条话题的所有信息,包括很多无用的数据

})

</script>

 

不得不说,是很乱。但只要抽取相关部分就可以了。基本思路就是根据html标签的对称结构,拿到每段话题的内容(如上面这段,娶到FM.view内,html属性下的值,然后再得到所需的排名、话题、阅读数字段数据)

 

2.1 话题内容截取

(1)获取所有符合要求的<script>代码段,这里要用到正则或字符串匹配算法。考虑到每个<script>xxx</script>是对称的结构,那么正则无疑是个不错的选择;使用的正则表达式为:

Pattern p = Pattern.compile("\\<script>FM.view(.*?)\\</script>");
        Matcherm = p.matcher(buf);
        while(m.find()){
        if(t_rs.contains("html") &&t_rs.contains("pt_li S_line2")){
                rsList.add(t_rs);
            }      
}
代码中,在第一步的匹配结果下,又增加了包含pt_liS_line2标签的条件,过滤后,只有一个script代码段符合条件,就是包含了15条热门话题的那段代码。

完整代码如下:没有优化,效率有点低。后续会进行优化

public class TestLogin {

public static void main(String[] args) throws IOException{
String strURL="http://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.4.18)";

// strURL="http://weibo.com/u/1596867051/home?wvr=5&lf=reg";
strURL="http://d.weibo.com/100803?refer=index_hot_new";
URL url = new URL(strURL);
HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();

// httpConn.setRequestProperty("Host", "www.jimubox.com");

// httpConn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0");

// httpConn.setRequestProperty("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");

// httpConn.setRequestProperty("Accept-Language", "zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3");

// httpConn.setRequestProperty("Accept-Encoding", "gzip, deflate");

//
String cookie="你的cookie“;
httpConn.setRequestProperty("Cookie", cookie);

// httpConn.setRequestProperty("Connection", "keep-alive");

httpConn.setRequestProperty("charset", "utf-8");

InputStreamReader input = new InputStreamReader(httpConn.getInputStream(), "utf-8");
BufferedReader bufReader = new BufferedReader(input);
String line = "";
StringBuilder contentBuf = new StringBuilder();
while ((line = bufReader.readLine()) != null) {
contentBuf.append(line);
}
String buf = contentBuf.toString();

//字符串匹配/正则表达式,得到所有<script></script>标签段的index

// System.out.println(buf);

// String testStr = "12315<text>show me</text> <text>show me</text>";

// Pattern p = Pattern.compile("<text>(.*)</text>");

// Matcher m = p.matcher(testStr);

// while(m.find()){

// System.out.println(m.group(1));

// }

String test="<html><script>FM.view({})</script><script>FM.view({})</script><script>FM.view({})</script>";
Pattern p = Pattern.compile("\\<script>FM.view(.*?)\\</script>");

// Pattern p = Pattern.compile("\\<script>(.*?)\\</script>");
Matcher m = p.matcher(buf);
List<String> rsList=new ArrayList<String>();
List<String> liList=new ArrayList<String>();
while(m.find()){
String t_rs=m.group(1);
if(t_rs.contains("html") && t_rs.contains("pt_li S_line2")){
rsList.add(t_rs);
}
}

if(rsList.isEmpty()){
System.out.println("抓取异常!!!!");
}
String topics = rsList.get(0);

// System.out.println(topics);
p = Pattern.compile("\\<li class\\=(.*?)li>");
m = p.matcher(topics);
while(m.find()){
if(m.group(1).startsWith("\\\"pt_li S_line2\\\"")){
String li=m.group(1);

String regex = "http.*?faxian_huati"; 
Pattern p1=Pattern.compile(regex);
Matcher m1=p1.matcher(new String(li));

// if(m1.find()){

// System.out.println(m1.group(0));

// }

//

// regex = "http:\\\\/\\\\/ww3.sinaimg.cn.*?\\.jpg"; 

// p1=Pattern.compile(regex);

// m1=p1.matcher(new String(li));

// if(m1.find()){

// System.out.println(m1.group(0));

// }

//top排名

// regex = "\\<span class\\=\\\\\"DSC_topicon\\\\\">(.*?)<\\\\/span>"; 

// p1=Pattern.compile(regex);

// m1=p1.matcher(new String(li));

// if(m1.find()){

// System.out.println(m1.group(1));

// }

//话题名称

// regex = "\\#(.*?)#"; 

// p1=Pattern.compile(regex);

// m1=p1.matcher(new String(li));

// if(m1.find()){

// System.out.println(m1.group(0));

// }

//分类标签
regex = "\\<\\\\/span>(.*?)<\\\\/a>"; 
p1=Pattern.compile(regex);
m1=p1.matcher(new String(li));
if(m1.find()){
System.out.println(m1.group(1));
}

}
}

// for(String li:liList){

// //图片url

// String regex = "http.*?faxian_huati"; 

// Pattern p1=Pattern.compile(regex);

// Matcher m1=p1.matcher(new String(li));

// if(m1.find()){

// System.out.println(m1.group(0));

// }

// }

//

// for(String li:liList){

// //图片url

// String regex = "http:\\\\/\\\\/ww3.sinaimg.cn.*?\\.jpg"; 

// Pattern p1=Pattern.compile(regex);

// Matcher m1=p1.matcher(new String(li));

// if(m1.find()){

// System.out.println(m1.group(0));

// }

// }
}

}

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  爬虫 java 新浪微博