一、写在前面

(本专栏分为“java版微博爬虫”和“python版网络爬虫”两个项目,系列里所有文章将基于这两个项目讲解,项目完整源码已经整理到我的Github,有兴趣的可以去看下,链接地址在文末。)

网络爬虫根据需求的不同也分不同种类:

1.一种是爬取网页链接,通过url链接得到这个html页面中指定的链接,把这些链接存储起来,再依次以这些链接为源,再次爬取连接指向html页面中的链接……如此层层递归下去,常用的方法是广度优先或者深度优先,根据爬取层次需求不同而选择不同的方法达到最优效果,爬虫的效率优化是一个关键。

搜索引擎的第一个步骤就是通过爬虫得到需要索引的链接或数据,存放于数据库,然后对这些数据建立索引,然后定义查询语句,解析查询语句并利用检索器对数据库里的数据进行检索。

2.一种是爬取数据信息,如文本信息、图片信息等,有时需要做数据分析,通过某种手段来获取数据样本以供后续分析,常用的方法是爬虫获取指定数据样本或利用现有的公共数据库。本文的微博爬虫属于第二种类,根据自定义搜索关键字爬取微博信息数据。

对于网络爬虫原理,其实并不复杂。基本思路是:由关键字指定的url把所有相关的html页面全抓下来(html即为字符串),然后解析html文本(通常是正则表达式或者现成工具包如jsoup),提取微博文本信息,然后把文本信息存储起来。

重点在于对html页面源码结构的分析,不同的html需要不同的解析方法;还有就是长时间爬取可能对IP有影响,有时需要获取代理IP,甚至需要伪装浏览器爬取。

对于微博,通常情况下是必须登录才能看到微博信息数据(比如腾讯微博),但是有的微博有搜索机制,在非登录的情况下可以直接通过搜索话题来查找相关信息(如新浪微博、网易微博)。考虑到某些反爬虫机制,如果一个账号总是爬取信息可能会有些影响(比如被封号),所以本文采用的爬虫都是非登录、直接进入微博搜索页面爬取。这里关键是初始url地址。

二、网页分析

举个例子,对于有搜索机制的微博,如新浪微博和网易微博:(这里尤其要注意地址及参数!)

新浪微博搜索话题地址:http://s.weibo.com/weibo/苹果手机&nodup=1&page=50

网易微博搜索话题地址:http://t.163.com/tag/苹果手机

分别来看下网页截图和对应网页源码:

(1) 新浪微博:

(2) 网易微博:

我们需要做的就是把微博的文本提取出来,这里有些特征信息:根据关键字搜到的微博,其关键字会被标红,在html源码里有体现,分别查看两个网页的源代码。

可以看到,新浪微博的源码全部为html标签,为了反爬虫故意将源码混乱,并且汉字也做了处理,显示汉字的utf-8编码而不是直接显示汉字,不太好找,这里就需要查找红色字体color:red的部分,其中<span style=\”color:red;\”>\u82f9\u679c\u624b\u673a<\span>中间夹着的哪些utf8编码其实就是关键字“苹果手机”。后面的那些utf8编码就是本条微博的文本内容。

而网易微博在这方面就要看起来容易许多,至少html里直接显示的是汉字,比较好找,而且微博文本部分其实是以json格式体现的,直接解析json就可以提取文本数据了,当然也可以直接用正则。

三、爬取微博

这里先写个简单的爬虫,原理都差不多,就拿网易微博为例,先说下爬虫程序需要用到的工具包:

httpclient-4.3.1.jar  -------建立HTTP链接,用于从url获取html

httpcore-4.3.jar

httpmime-4.3.1.jar

httpclient-cache-4.3.1.jar

fluent-hc-4.3.1.jar

fastjson-1.1.41.jar   ------解析json的工具包

jsoup-1.7.3.jar      -------解析xml,html的工具包

dom4j-1.6.1.jar     -------读写xml的工具包

commons-lang-2.1.jar

commons-logging-1.2.jar

commons-codec-1.8.jar

总体思路:

1. getHTML()方法:从url得到html字符串。

这里有两个关键点:

(1) 设置用户cookie策略,屏蔽掉cookie rejected的报错,当然可以不设置,直接用默认的client,即是CloseableHttpClient client = HttpClients.createDefault();创建的客户端,但是会报错;设置cookie的代码如下:

CookieSpecProvider cookieSpecProvider = new CookieSpecProvider(){
public CookieSpec create(HttpContext context){
return new BrowserCompatSpec(){
@Override
public void validate(Cookie cookie, CookieOrigin origin) throws MalformedCookieException {
//Oh, I am easy;
}
};
}
};
Registry<CookieSpecProvider> r = RegistryBuilder
.<CookieSpecProvider> create()
.register(CookieSpecs.BEST_MATCH, new BestMatchSpecFactory())
.register(CookieSpecs.BROWSER_COMPATIBILITY, new BrowserCompatSpecFactory())
.register("easy", cookieSpecProvider)
.build();

(2) 设置socket超时socketTimeout和连接超时connectTimeout,这很关键,如果不设置的话,当网络不好的情况下,某次请求没有及时得到响应,程序可能会卡死。但是设置连接超时,超时之后再自动重连就可以避免这个问题。代码如下:

RequestConfig requestConfig = RequestConfig.custom()
.setCookieSpec("easy")
.setSocketTimeout(5000) //设置socket超时时间
.setConnectTimeout(5000) //设置connect超时时间
.build();

2.isExitHTML()方法:

判断html是否合法(有效html,有微博内容的),有时候会出现页面不存在的情况,是因为该关键字没有微博信息,这是页面有提示:“没有找到相关的微博呢,换个关键词试试吧!”如下图;

3.writeWeibo2txt()方法:

正则解析(这里主要解析微博文本内容content、用户id、发文时间prettyTime),得到微博文本数据:控制台输出、写到txt文件;

(这里没有用jsoup去解析html,直接用的正则,有时间后面再写jsoup解析html的,比正则方便,当然对正则表达式这个工具掌握很熟练的朋友可以忽略……)

我的博客里另外有一篇正则教程完全总结,可以去看下:正则表达式总结

本来网易微博的源代码里嵌入了json元素,前面的html标签的都不是微博文本数据,在这个标签后面        <scriptid="data_searchTweet" type="application/json">才是json格式包括的微博文本,本来打算先把json串用正则匹配出来,后来发现,直接匹配关键字岂不更好?但这里要注意的是匹配的时候可能会有很多换行符之类的东西,我这里只匹配了三个field,正则表达式"id":\s"\d{19}",(\n*?)|(\s*?)"content":\s".*?",(\n*?)|(\s*?)"prettyTime":\s".*?"

顺便推荐一个检测正则的工具:http://tool.oschina.net/regex?optionGlobl=global

把源码贴上来吧:

/**
* @note 1.根据搜索关键词从指定url得到相应的html页面,并验证其合法性;
* 2.得到微博样本:写到txt文件里
*
* @author DianaCody
* @since 2014-09-26 15:08
*
*/ import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.regex.Pattern;
import java.util.regex.Matcher; import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.cookie.Cookie;
import org.apache.http.cookie.CookieOrigin;
import org.apache.http.cookie.CookieSpec;
import org.apache.http.cookie.CookieSpecProvider;
import org.apache.http.cookie.MalformedCookieException;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.cookie.BestMatchSpecFactory;
import org.apache.http.impl.cookie.BrowserCompatSpec;
import org.apache.http.impl.cookie.BrowserCompatSpecFactory;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils; public class Weibo163 { private String getHTML(String url) throws URISyntaxException, ClientProtocolException, IOException {
//采用用户自定义cookie策略,不显示cookie rejected的报错
CookieSpecProvider cookieSpecProvider = new CookieSpecProvider(){
public CookieSpec create(HttpContext context){
return new BrowserCompatSpec(){
@Override
public void validate(Cookie cookie, CookieOrigin origin) throws MalformedCookieException { }
};
}
};
Registry<CookieSpecProvider> r = RegistryBuilder
.<CookieSpecProvider> create()
.register(CookieSpecs.BEST_MATCH, new BestMatchSpecFactory())
.register(CookieSpecs.BROWSER_COMPATIBILITY, new BrowserCompatSpecFactory())
.register("cookie", cookieSpecProvider)
.build();
RequestConfig requestConfig = RequestConfig.custom()
.setCookieSpec("cookie")
.setSocketTimeout(5000) //设置socket超时时间
.setConnectTimeout(5000) //设置connect超时时间
.build();
CloseableHttpClient httpClient = HttpClients.custom()
.setDefaultCookieSpecRegistry(r)
.setDefaultRequestConfig(requestConfig)
.build();
HttpGet httpGet = new HttpGet(url);
httpGet.setConfig(requestConfig);
String html = "html获取失败"; //用于验证是否取到正常的html
try{
CloseableHttpResponse response = httpClient.execute(httpGet);
html = EntityUtils.toString(response.getEntity());
//System.out.println(html); //打印返回的html
} catch (IOException e) {
e.printStackTrace();
}
return html;
} private boolean isExistHTML(String html) throws InterruptedException {
boolean isExist = false;
Pattern pNoResult = Pattern.compile("\\\\u6ca1\\\\u6709\\\\u627e\\\\u5230\\\\u76f8"
+ "\\\\u5173\\\\u7684\\\\u5fae\\\\u535a\\\\u5462\\\\uff0c\\\\u6362\\\\u4e2a"
+ "\\\\u5173\\\\u952e\\\\u8bcd\\\\u8bd5\\\\u5427\\\\uff01"); //没有找到相关的微博呢,换个关键词试试吧!(html页面上的信息)
Matcher mNoResult = pNoResult.matcher(html);
if(!mNoResult.find()) {
isExist = true;
}
return isExist;
} private void writeWeibo2txt(String html, String savePath) throws IOException {
File htmltxt = new File(savePath); //新建一个txt文件用于存放爬取的结果信息
FileWriter fw = new FileWriter(htmltxt);
BufferedWriter bw = new BufferedWriter(fw);
//regex-----"id":\s"\d{19}",(\n*?)|(\s*?)"content":\s".*?",(\n*?)|(\s*?)"prettyTime":\s".*?"
Pattern p = Pattern.compile("\"id\":\\s\"\\d{19}\",(\\n*?)|(\\s*?)\"content\":\\s\".*?\",(\\n*?)|(\\s*?)\"prettyTime\":\\s\".*?\"");
Matcher m = p.matcher(html);
while(m.find()) {
System.out.println(m.group());
bw.write(m.group());
}
bw.close();
} public static void main(String[] args) throws IOException, URISyntaxException, InterruptedException {
Weibo163 crawler = new Weibo163();
String searchword = "iPad"; //搜索关键字为"iPad"的微博html页面
String html = crawler.getHTML("http://t.163.com/tag/"+searchword);
String savePath = "e:/weibo/html.txt"; //输出到txt文件的存放路径
if(html != "html获取失败") {
if(crawler.isExistHTML(html)) {
System.out.println(html);
crawler.writeWeibo2txt(html, savePath);
}
}
//Pattern p = Pattern.compile("<script id=\"data_searchTweet\" type=\"application/json\">.+?<\script>"); //<script id="data_searchTweet" type="application/json">.*?<\script>
//Matcher m = p.matcher(html);
//html = crawler.getHTML("http://s.weibo.com/weibo/"+searchword+"&nodup=1&page="+1); //System.out.println(html);
} }

程序运行截图:

该java爬虫项目源码github地址:https://github.com/DianaCody/Spider_SinaTweetCrawler_java

原创文章,转载请注明出处:http://blog.csdn.net/dianacody/article/details/39584977

另外一个系列对爬虫的整理笔记http://www.crifan.com/files/doc/docbook/web_scrape_emulate_login/release/html/web_scrape_emulate_login.html

【网络爬虫】【java】微博爬虫(一):小试牛刀——网易微博爬虫(自定义关键字爬取微博数据)(附软件源码)的更多相关文章

  1. 【网络爬虫】【python】网络爬虫(二):网易微博爬虫软件开发实例(附软件源码)

    对于urllib2的学习,这里先推荐一个教程<IronPython In Action>,上面有很多简明例子,并且也有很详尽的原理解释:http://www.voidspace.org.u ...

  2. (转)python爬虫----(scrapy框架提高(1),自定义Request爬取)

    摘要 之前一直使用默认的parse入口,以及SgmlLinkExtractor自动抓取url.但是一般使用的时候都是需要自己写具体的url抓取函数的. python 爬虫 scrapy scrapy提 ...

  3. 【JAVA-JDT-AST】Java抽象语法树的构建、遍历及转成dot格式(附Github源码)

    Background: 最近为了重现tree-based clone detection的论文:L. Jiang, G. Misherghi, Z. Su, and S. Glondu. Deckar ...

  4. Python爬虫一爬取B站小视频源码

    如果要爬取多页的话 在最下方循环中 填写好循环的次数就可以了 项目源码 from fake_useragent import UserAgent import requests import time ...

  5. 另类爬虫:从PDF文件中爬取表格数据

    简介   本文将展示一个稍微不一样点的爬虫.   以往我们的爬虫都是从网络上爬取数据,因为网页一般用HTML,CSS,JavaScript代码写成,因此,有大量成熟的技术来爬取网页中的各种数据.这次, ...

  6. MATLAB爬虫爬取股票数据

    近年来,大数据盛行,有关爬虫的教程层次不穷.那么,爬虫到底是什么呢? 什么是爬虫? 百度百科是这样定义的: 网络爬虫(又被称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种 ...

  7. python爬虫——爬取网页数据和解析数据

    1.网络爬虫的基本概念 网络爬虫(又称网络蜘蛛,机器人),就是模拟客户端发送网络请求,接收请求响应,一种按照一定的规则,自动地抓取互联网信息的程序.只要浏览器能够做的事情,原则上,爬虫都能够做到. 2 ...

  8. 爬虫系列4:Requests+Xpath 爬取动态数据

    爬虫系列4:Requests+Xpath 爬取动态数据 [抓取]:参考前文 爬虫系列1:https://www.cnblogs.com/yizhiamumu/p/9451093.html [分页]:参 ...

  9. 一个月入门Python爬虫,轻松爬取大规模数据

    Python爬虫为什么受欢迎 如果你仔细观察,就不难发现,懂爬虫.学习爬虫的人越来越多,一方面,互联网可以获取的数据越来越多,另一方面,像 Python这样的编程语言提供越来越多的优秀工具,让爬虫变得 ...

随机推荐

  1. C语言关键字—-sizeof 、typedef、const、static、register、extern、#define

    关键字:sizeof .#define.typedef.const.static.register.extern sizeof 1. 作用:求数据所占得内存空间大小 2. 本质:求数据得类型所占的内存 ...

  2. 2.Qt Creator的使用

    下面以一个简单的程序来说明Qt Creator的使用: 首先,按图片步骤创建一个Qt项目 创建完成后 上图标记处工具栏提供了简化树形视图.分栏等功能(自行尝试吧...) 在使用Qt制作一个界面时,我们 ...

  3. mysql 中遇到金额 BigDecimal类型字段

    当数据库字段为BigDecimal型,and后面判断去掉. 否则当为0时候,视为空处理了.即传参为null

  4. mac USB串口工具配置

     安装USB serial 驱动 我的usb serial芯片是 pl2303, 先到官网上下载对应驱动,并安装.安装完成之后会要求重启. http://www.prolific.com.tw/adm ...

  5. linux新建文件和文件夹命令

    1.touch命令 touch命令用来修改文件的访问时间.修改时间.如果没有指定时间,则将文件时间属性改为当前时间. 当指定文件不存在,touch命令变为创建该文件. 语法: touch [-acm] ...

  6. Vmware虚拟机安装XP系统

    刚开始下载的雨林木风ghost镜像,首先是虚拟机无法自动识别系统版本.然后启动的时候也是无法从光驱启动,又接连下载了几个版本的系统镜像, 都是ghost的,都不好使,百度,偶然发现有人提了一句,需要用 ...

  7. Spring整合Hibernate的方法

    一.基本支持 Spring 支持大多数流行的 ORM 框架, 包括 Hibernate JDO, TopLink, Ibatis 和 JPA. Spring 对这些 ORM 框架的支持是一致的, 因此 ...

  8. BZOJ 2069 POI2004 ZAW 堆优化Dijkstra

    题目大意:给定一张无向图.每条边从两个方向走各有一个权值,求从点1往出走至少一步之后回到点1且不经过一条边多次的最短路 显然我们须要从点1出发走到某个和点1相邻的点上,然后沿最短路走到还有一个和点1相 ...

  9. ubuntu 12.04 解压安装jdk

    ubuntu下解压安装jdk,简单方便.分享一下安装方法: 注:该方法针对新系统,之前没有配置过jdk的情况. 1.下载相应版本号的jdk压缩包.如 jdk-8u5-linux-x64.gz 2.解压 ...

  10. (转)CentOS6.5安装Darwin Streaming Server搭建RTSP流媒体服务器

    参考: 1,CentOS6.5安装Darwin Streaming Server搭建RTSP流媒体服务器 http://www.yimiju.com/articles/567.html