爬虫的第二步,是对源码进行解析,提炼出目标内容。
正则表达式(Regular Expression),计算机科学的一个概念。通常被用来检索、替换那些符合某个规则的文本。
在爬虫程序中,随处可见正则表达式的影子。无论是 URL 筛选过滤,还是正文内容解析,都离不开正则表达式的支持。可以这么说,如果没有正则表达式,那么开发者将很难编写一个完整的爬虫程序。
如果之前没有接触过正则表达式,可以通过以下教程快速入门:
Java 与正则表达式相关的类主要在 java.util.regex 包中。在 Java 中使用正则表达式,首先就要掌握 regex 包中的 Pattern 类与 Matcher 类。二者的作用如下表所示:
class name | introduction |
---|---|
Pattern | 表示一个已经编译好的正则表达式 |
Matcher | 通过 Pattern 实例对任意字符序列进行匹配的引擎 |
使用 Pattern 与 Matcher 实现正则匹配,需要以下步骤:
Pattern.compile(String regex)
创建一个不可变的、线程安全的 Pattern 实例;Pattern.matcher(CharSequence input)
获得 Matcher 类实例;find()
方法对任意字符序列进行匹配(matches()
和 lookingAt()
方法也可以实现匹配功能);group(int group)
返回匹配到的子字符串。下面,我们尝试使用正则表达式从以下 HTML 文本中解析出节点 P 中的文本信息。
<html>
<body>
<p>今天的日期是:2017-11-11p>
body>
html>
package demo;
import util.FileUtils;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 正则表达式 demo
*
* @author panda
* @date 2017/11/12
*/
public class RegexDemo {
private static Pattern DATE_PATTERN = Pattern.compile("(.*?)
");
public static void main(String[] args) {
String htmlBody = FileUtils.readFile("test.html", "UTF-8");
System.out.println(htmlBody);
Matcher matcher = DATE_PATTERN.matcher(htmlBody);
if (matcher.find()) {
String[] s = new String[matcher.groupCount() + 1];
for (int i = 0; i <= matcher.groupCount(); i++) {
s[i] = matcher.group(i);
}
System.out.println(s[1]);
}
}
}
运行主函数后,控制台输出如下信息:
<html> <body> <p>今天的日期是:2017-11-11p> body>html>
今天的日期是:2017-11-11
XPath 是一门在 XML 文档中查找信息的语言,可用来在 XML 文档中对元素和属性进行遍历。它可以通过路径表达式在树状数据结构中选取指定节点或节点集。
由于 HTML 和 XML 一样拥有树状数据结构,因此 XPath 同样适用 HTML 文档。
在 Java 中使用 XPath,需要引入以下 jar 包:
通过 XPath 实现 HTML 文档解析,一般需要以下步骤:
parse(InputSource var1)
方法获取一个 Document 实例;下面,我们尝试使用 XPath 来解析出上述 HTML 文档中 P 节点的文本信息。
package demo;
import org.apache.xpath.XPathAPI;
import org.cyberneko.html.parsers.DOMParser;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;
import util.FileUtils;
import java.io.ByteArrayInputStream;
import java.io.InputStreamReader;
/**
* XPath demo
*
* @author panda
* @date 2017/11/18
*/
public class XPathDemo {
public static void main(String[] args) {
String htmlBody = FileUtils.readFile("test.html", "UTF-8");
System.out.println(htmlBody);
try {
DOMParser parser = new DOMParser();
parser.setFeature("http://xml.org/sax/features/namespaces", false);
parser.setProperty(
"http://cyberneko.org/html/properties/default-encoding",
"UTF-8");
ByteArrayInputStream in = new ByteArrayInputStream(htmlBody.getBytes());
InputStreamReader reader = new InputStreamReader(in);
InputSource source = new InputSource(reader);
parser.parse(source);
Document doc = parser.getDocument();
Node node = XPathAPI.selectSingleNode(doc, ".//P");
System.out.println(node.getTextContent());
} catch (Exception e) {
e.printStackTrace();
}
}
}
运行主函数后,我们可以在控制台看到同样的结果。
jsoup 是一款 Java 的 HTML 解析器,可直接解析某个 URL 地址、HTML 文本内容。它提供了一套非常强大的 API,可通过 DOM,CSS 以及类似于 jQuery 的操作方法来取出和操作数据。
实际上,jsoup 与 XPath 非常相似。
在 Java 中使用 jsoup,同样需要我们引入 jar 包:
通过 jsoup 解析 HTML 文档,需要以下步骤:
Jsoup.parse(String html)
获取一个 Document 实例(注意,不是 w3c 下的 Document);下面,我们尝试使用 jsoup 完成相同的解析需求。
package demo;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import util.FileUtils;
/**
* jsoup demo
*
* @author panda
* @date 2017/11/12
*/
public class JsoupDemo {
public static void main(String[] args) {
String htmlBody = FileUtils.readFile("test.html", "UTF-8");
System.out.println(htmlBody);
Document doc;
try {
doc = Jsoup.parse(htmlBody);
Elements elements = doc.getElementsByTag("P");
for (int i = 0; i < elements.size(); i++) {
Element element = elements.get(i);
System.out.println(element.text());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
运行主函数后,我们同样能获取相同的结果。
如果想了解 jsoup 更多使用方法,请参考以下专栏:http://blog.csdn.net/column/details/jsoup.html
Gson 是 Google 提供的用于解析 Json 数据的开源类库,相似的类库还有 Jackson、FastJson 等。
使用 Gson,需添加 jar 包:
一个简单的 Gson 解析 Json 数据示例,需要以下步骤:
fromJson(String json, Class classOfT)
方法实现 Json 数据到 POJO 的映射;现在,我们尝试解析出以下 Json 数据中的信息。
{
name:"panda",
age:18
}
package demo;
import com.google.gson.Gson;
import util.FileUtils;
/**
* Gson demo
*
* @author panda
* @date 2017/11/30
*/
public class GsonDemo {
public static void main(String[] args) {
String jsonString = FileUtils.readFile("json.txt", "UTF-8");
Gson gson = new Gson();
User user = gson.fromJson(jsonString, User.class);
System.out.println("name:" + user.name);
System.out.println("age:" + user.age);
}
private class User {
private String name;
private int age;
}
}
运行主函数后,获取如下结果:
name:panda
age:18
如果想更全面地学习 Gson,请点这里:http://www.jianshu.com/p/e740196225a4