4种HTML结构化解析方法

来源:互联网 发布:电信宽带无法连接网络 编辑:程序博客网 时间:2024/04/26 15:36

以下三种方式,每个网站需要定义相关的模板---------



1. dom解析方式 --------------------------------------------------------------------------------------------------------------------------------------
下载:jsoup.jar
参考代码(百度搜索):
String url = "http://www.baidu.com/s?cl=2&tn=baiduwb&rn=20&ie=utf-8&rtt=2&wd=%E6%9D%8E%E5%A4%A9%E4%B8%80&pn=0";
Document doc = Jsoup.connect(url).get();
Elements eles = doc.select("div[id=wrapper] div[id=main] div[class=content_bg] div[class=content] ol[id=weibo] li");
for (Element element : eles) {
//网址
String url = element.select("div a[name=weibo_rootnick]").attr("href");
//描述
String description = element.select("div").text();
//作者
String author = element.select("div a[name=weibo_rootnick]").text();
//评论数
String pingTotalStr = element.select("div div[class=weibo_info] div[class=weibo_pz] a[name=weibo_ping]").text();
//浏览数
String transTotalStr = element.select("div div[class=weibo_info] div[class=weibo_pz] a[name=weibo_trans]").text();
}



2. 字符串首尾截取--------------------------------------------------------------------------------------------------------------------------------------
public static String substringByKeyNotSkey(String str, String skey, String ekey){
        String temp = str.substring(str.indexOf(skey)+skey.length());
        String ucUrl = temp.substring(0, temp.indexOf(ekey));
        return ucUrl;
    }



3. 正则表达式--------------------------------------------------------------------------------------------------------------------------------------
html.replaceAll("(?is)<!DOCTYPE.*?>", "");



4. 通用型,分析能力有限,但能兼容大部分网站--------------------------------------------------------------------------------------------------------------------------------------
/**
 * <p>
 * 在线性时间内抽取主题类(新闻、博客等)网页的正文。 采用了<b>基于行块分布函数</b>的方法,为保持通用性没有针对特定网站编写规则。
 * </p>
 *
 * @version 1.0, 2009-11-11
 */
public class TextExtractUtil {
    private static List<String> lines;
    private final static int blocksWidth;
    private static int threshold;
    private static String html;
    private static boolean flag;
    private static int start;
    private static int end;
    private static StringBuilder text;
    private static ArrayList<Integer> indexDistribution;

    static {
        lines = new ArrayList<String>();
        indexDistribution = new ArrayList<Integer>();
        text = new StringBuilder();
        blocksWidth = 3;
        flag = false;
        /* 当待抽取的网页正文中遇到成块的新闻标题未剔除时,只要增大此阈值即可。 */
        /* 阈值增大,准确率提升,召回率下降;值变小,噪声会大,但可以保证抽到只有一句话的正文 */
        threshold = 86;
    }

    public static void setthreshold(int value) {
        threshold = value;
    }

    /**
     * 抽取网页正文,不判断该网页是否是目录型。即已知传入的肯定是可以抽取正文的主题类网页。
     *
     * @param _html
     *            网页HTML字符串
     *
     * @return 网页正文string
     */
    public static String parse(String _html) {
        return parse(_html, false);
    }

    /**
     * 判断传入HTML,若是主题类网页,则抽取正文;否则输出<b>"unkown"</b>。
     *
     * @param _html
     *            网页HTML字符串
     * @param _flag
     *            true进行主题类判断, 省略此参数则默认为false
     *
     * @return 网页正文string
     */
    public static String parse(String _html, boolean _flag) {
        flag = _flag;
        html = _html;
        preProcess();
        // System.out.println(html);
        return getText();
    }

    private static void preProcess() {
        html = html.replaceAll("(?is)<!DOCTYPE.*?>", "");
        html = html.replaceAll("(?is)<!--.*?-->", ""); // remove html comment
        html = html.replaceAll("(?is)<script.*?>.*?</script>", ""); // remove
                                                                    // javascript
        html = html.replaceAll("(?is)<style.*?>.*?</style>", ""); // remove css
        html = html.replaceAll("&.{2,5};|&#.{2,5};", " "); // remove special
                                                            // char
        html = html.replaceAll("(?is)<.*?>", "");
        // <!--[if !IE]>|xGv00|9900d21eb16fa4350a3001b3974a9415<![endif]-->
    }

    private static String getText() {
        lines = Arrays.asList(html.split("\n"));
        indexDistribution.clear();

        for (int i = 0; i < lines.size() - blocksWidth; i++) {
            int wordsNum = 0;
            for (int j = i; j < i + blocksWidth; j++) {
                lines.set(j, lines.get(j).replaceAll("\\s+", ""));
                wordsNum += lines.get(j).length();
            }
            indexDistribution.add(wordsNum);
            // System.out.println(wordsNum);
        }

        start = -1;
        end = -1;
        boolean boolstart = false, boolend = false;
        text.setLength(0);

        for (int i = 0; i < indexDistribution.size() - 1; i++) {
            if (indexDistribution.get(i) > threshold && !boolstart) {
                if (indexDistribution.get(i + 1).intValue() != 0
                        || indexDistribution.get(i + 2).intValue() != 0
                        || indexDistribution.get(i + 3).intValue() != 0) {
                    boolstart = true;
                    start = i;
                    continue;
                }
            }
            if (boolstart) {
                if (indexDistribution.get(i).intValue() == 0
                        || indexDistribution.get(i + 1).intValue() == 0) {
                    end = i;
                    boolend = true;
                }
            }
            StringBuilder tmp = new StringBuilder();
            if (boolend) {
                // System.out.println(start+1 + "\t\t" + end+1);
                for (int ii = start; ii <= end; ii++) {
                    if (lines.get(ii).length() < 5)
                        continue;
                    tmp.append(lines.get(ii) + "\n");
                }
                String str = tmp.toString();
                // System.out.println(str);
                if (str.contains("Copyright") || str.contains("版权所有"))
                    continue;
                text.append(str);
                boolstart = boolend = false;
            }
        }
        return text.toString();
    }
}
原创粉丝点击