java版 正文抽取 基于文字连接比

时间:2022-08-22 09:48:56


package cn.tdt.crawl.jdbc;
import java.util.regex.Matcher;
import java.util.regex.Pattern; import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements; public class HtmlExtract {
private static double linkTextRadio = 0.25; // 链接文字比 // 过滤不必要的数据
public static String filterContent(String str) {
if (str == "") {
return "";
}
str = str.replaceAll("(?is)<!DOCTYPE.*?>", "");
str = str.replaceAll("(?is)<!--.*?-->", "");
str = str.replaceAll("(?is)<script.*?>.*?</script>", "");
str = str.replaceAll("(?is)<style.*?>.*?</style>", "");
// str=str.replaceAll("&.{2,5};|&#.{2,5};", " ");
return str;
} // 计算链接数
public static int calcLinks(Element node) {
Elements links = node.select("a[href]");
return links.size();
} // 计算内容长度
public static double calcWords(Element node) {
String con = node.text();
if (con.length() == 0) {
return 1 + linkTextRadio;
} else {
return con.length();
}
} // 计算标点符号的个数
public static int calcSign(Element node) {
String[] sign = { ",", ";", ".", "\"", "'", "\\?", "。", ":", "," };
int i = 0;
for (String ch : sign) {
int count = 0;
count = node.text().split(ch).length - 1;
i = +count;
}
return i;
} // 将所有的空节点全部删除
public static Element drawCon(Element node) {
if (node.tagName() == "a") {
// 这个就不用进去深入了
return node;
}
int links; // 链接数
double words; // 文字长度
double cellRatio;
int signs; // 符号出现的情况 Elements nodes = node.children();
for (Element cnode : nodes) {
if (!cnode.hasText()) {
// System.out.println("删除"+cnode);
cnode.remove();
} else {
links = calcLinks(cnode);
words = calcWords(cnode);
cellRatio = links / words;
signs = calcSign(cnode);
if (signs < 1) {
// 删除没有标点符号的节点
cnode.remove();
} else if (cellRatio > linkTextRadio) {
cnode.remove();
} else {
drawCon(cnode);
}
}
}
return node;
} // 提取标题
private String drawTitle(String str) {
// TODO Auto-generated method stub
// 先取页面的title部分的值
if (str.length() < 1) {
return null;
}
String tit = "";
int xhpos = -1; // 下划线的位置
int zhpos = -1; // 中横线的位置
Pattern pt = Pattern.compile("<title>(.*)</title>",
Pattern.CASE_INSENSITIVE);
Matcher mc = pt.matcher(str);
if (mc.find()) {
tit = mc.group(1).trim();
// 下面需要过滤一下,有些标题会加上下划线或者中横线
xhpos = tit.indexOf("_");
zhpos = tit.indexOf("|");
if (xhpos > 0) {
tit = tit.substring(0, xhpos);
}
if (zhpos > 0) {
tit = tit.substring(0, zhpos);
}
} return tit;
} // 提取作者
private String[] drawAuthor(String str) {
if (str.length() < 1) {
return null;
}
// 这种信息一般就是直接用正则就好
String[] author = new String[2];
int tPos = 0; // 日期所在的位置
Pattern pt = Pattern.compile(
"作者.+(\\d{4}[-|年]\\d{1,2}[-|月]\\d{1,2}[日]?)",
Pattern.CASE_INSENSITIVE);
Matcher mc = pt.matcher(str);
if (mc.find()) {
// System.out.println("123");
author[0] = mc.group(1); // 存储日期信息
tPos = mc.group().trim().indexOf(author[0]);
author[1] = mc.group().trim().substring(0, tPos);
return author;
}
return null;
} // 核心处理函数
public String[] extract(String str) {
String title; // 标题
//String author = ""; // 作者
//String uptime = ""; // 发布时间
String content; // 正文
//String[] authors = new String[2]; str = filterContent(str);
Document doc = Jsoup.parse(str);
// 取body
Element bodynode = doc.select("body").first();
title = drawTitle(str);
//authors = drawAuthor(str);
// 开始遍历节点,进行去噪处理,抽取正文
content = drawCon(bodynode).text();
// 防止溢出
// if (authors.length > 1) {
// author = authors[1];
// uptime = authors[0];
// }
// System.out.println(title);
// System.out.println(author);
// System.out.println(uptime);
// System.out.println(content);
String[] arr = new String[2];
arr[0] = title;
arr[1] = content;
return arr;
} public static void main(String[] args){ } }