网页正文抽取(包含提取图片)

转自:http://bbs.it-home.org/thread-12676-1-1.html

/**
 *@author Xin Chen
 *Created on 2009-11-11
 *Updated on 2010-08-09
 *Email:  [email protected]
 *Blog:   http://hi.baidu.com/爱心同盟_陈鑫
 *Modified By : Yang @ http://www.chainlt.com
 */
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import dbhelper.TextTool;

/**
 * <p>
 * 在线性时间内抽取主题类(新闻、博客等)网页的正文。 采用了<b>基于行块分布函数</b>的方法,为保持通用性没有针对特定网站编写规则。
 * </p>
 *
 * @author Chen Xin
 * @version 1.0, 2009-11-11
 */
public class TextExtract {
    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;
    private static List<String> old_lines;
    private static String oldhtml;

    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("(?is)style=\".*?\"", "");// remove css
        html = html.replaceAll("&.{2,5};|&#.{2,5};", " ");// remove special char
        oldhtml = html;
        html = html.replaceAll("(?is)<.*?>", "");
        // <!--[if !IE]>|xGv00|9900d21eb16fa4350a3001b3974a9415<![endif]-->
    }

    private static String getText() {
        lines = Arrays.asList(html.split("\n"));
        old_lines = Arrays.asList(oldhtml.split("\n"));
        indexDistribution.clear();
        boolean haveimg_arr[] = new boolean[old_lines.size()];
        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);
            if (old_lines.get(i).toLowerCase().contains("<img")) {
                haveimg_arr[i] = true;
            }
        }
        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 (haveimg_arr[i]) {
                    continue;
                }
                if (indexDistribution.get(i).intValue() == 0
                        || indexDistribution.get(i + 1).intValue() == 0) {
                    end = i;
                    boolend = true;
                }
            }
            if (boolend) {
                StringBuilder tmp = new StringBuilder();
                // System.out.println(start+1 + "\t\t" + end+1);
                for (int ii = start; ii <= end; ii++) {
                    if (haveimg_arr[ii]) {
                        String img = getImg(old_lines.get(ii));
                        if (img == null)
                            continue;
                        tmp.append(img + "\n");
                        continue;
                    }
                    if (lines.get(ii).length() < 5)
                        continue;
                    tmp.append("<p>" + lines.get(ii) + "</p>\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();
    }

    public static String getImg(String s) {
        String img = TextTool.getBetweenOne(s, "<img", "</img>");
        if (img == null) {
            img = TextTool.getBetweenOne(s, "<img", "/>");
        } else {
            img = "<img" + img + "</img>";
        }
        if (img != null) {
            img = "<img" + img + "/>";
        }
        return img;
    }
}

PS:

Q:经常看见的正则前面的 (?i) (?s) (?m) (?is) (?im) 是什么意思?
A: 称为内联匹配模式,通常用内联匹配模式代替使用枚举值RegexOptions指定的全局匹配模式,写起来更简洁。
  (?i) 表示所在位置右侧的表达式开启忽略大小写模式
  (?s) 表示所在位置右侧的表达式开启单行模式。
  更改句点字符 (.) 的含义,以使它与每个字符(而不是除 \n 之外的所有字符)匹配。
  注意:(?s)通常在匹配有换行的文本时使用
  (?m) 表示所在位置右侧的表示式开启指定多行模式。
  更改 ^ 和 $ 的含义,以使它们分别与任何行的开头和结尾匹配,
  而不只是与整个字符串的开头和结尾匹配。
  注意:(?m)只有在正则表达式中涉及到多行的“^”和“$”的匹配时,才使用Multiline模式。
  上面的匹配模式可以组合使用,比如(?is),(?im)。
  另外,还可以用(?i:exp)或者(?i)exp(?-i)来指定匹配的有效范围。

时间: 2024-11-10 15:39:38

网页正文抽取(包含提取图片)的相关文章

网页正文抽取

转自丕子:http://www.zhizhihu.com/html/y2013/4202.html 总结我用过的网页正文抽取工具: decruft http://t.cn/S7bVEC python-readabilityhttp://t.cn/zYeoZ8b boilerpipe http://t.cn/h41EEs python-boilerpipehttp://t.cn/zYeoyPw pismo http://t.cn/zYeoyP2 Goose http://t.cn/zYeoZ8G 

按示例学python:使用python抓取网页正文

本方法是基于文本密度的方法,最初的想法来源于哈工大的<基于行块分布函数的通用网页正文抽取算法>,本文基于此进行一些小修改. 约定: 本文基于网页的不同行来进行统计,因此,假设网页内容是没有经过压缩的,就是网页有正常的换行的. 有些新闻网页,可能新闻的文本内容比较短,但其中嵌入一个视频文件,因此,我会给予视频较高的权重:这同样适用于图片,这里有一个不足,应该是要根据图片显示的大小来决定权重的,但本文的方法未能实现这一点. 由于广告,导航这些非正文内容通常以超链接的方式出现,因此文本将给予超链接的

提取网页正文的开源库的比较

前段时间在工作中,需要提取出网页的正文,就试验了一下机中提取网页正文开源库. 试验中主要试验了java和python两种提取正文的开源库,测试的连接是:http://www.chinanews.com/gj/2014/11-19/6791729.shtml.结果如下: A.Java: 1.Cx-extractor( http://cx-extractor.googlecode.com):基于行块的分布来提取网页中的正文. 提取的方法是首先使用Jsoup来获取网页的内容,之后将内容传给cx-ext

asp.net正则表达式提取网页网址、标题、图片实例以及过滤所有HTML标签实例

无论你用什么语言,正则表达式的处理方法都是非常灵活.高效的,尤其是对某些字符串的抓取.过滤方面,更显其优势. 正则表达式的写法通常比较简单,几行短代码便能轻松完成看似很复杂的事情,更值得称赞的是,它的执行效率非常高,运行速度相当快.因此我在项目的开发中,通常把正则表达式作为处理问题的首选方法. 正则表达式的运用,在各种语言里都是相通的,也就是说,当你懂得在PHP中使用正则表达式,那么在任何一种语言中也能轻驾就熟. 这里给出两个asp.net实例. 1.asp.net正则表达式提取网址.标题.图片

从web编辑器 UEditor 中单独提取图片上传,包含多图片单图片上传以及在线涂鸦功能

UEditor是由百度web前端研发部开发所见即所得富文本web编辑器,具有轻量,可定制,注重用户体验等特点,开源基于MIT协议,允许自由使用和修改代码.(抄的...) UEditor是非常好用的富文本web编辑器,而且全中文API和注释,方便学习和使用.特别是图片上传查看及涂鸦功能极为喜欢,但是有很多情况我们并不需要Web编辑器,而只需要图片上传.那么问题来了,提取图片上传哪家强..... 网上有很多图片上传的控件.插件.但都不是那么的完美,有的只有一张图片上传不包含批量上传,有的没有图片查看

网页正文内容抽取测试

通过网页解析,抽取网页正文内容 原文地址:https://www.cnblogs.com/chenying99/p/10068855.html

crawler_基于块儿统计正文抽取_改进版

import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.regex.Pattern; /** * <p> * 在线性时间内抽取主题类(新闻.博客等)网页的正文. 采用了<b>基于行块分布函数</b>的方法,为保持通用性没有针对特定网站编写规则. * </p> * * @author Chen Xin([email protecte

网页前端开发,对于图片慢加载简介

http://www.cnblogs.com/qingseyuandi/p/loadingLater.html 网页前端的图片慢加载给网页显示的成本降低了不少,因此我在这边简单的介绍一下慢加载的一个技术原理,希望能起到抛砖引玉的作用,写的不好的地方希望指正,谢谢~~   技术背景 现在的网页系统,对于一些对图片资源比较多,并且一次性无法浏览完整个网页的情况下,图片慢加载可以提高客户端的体验,如IT大头:淘宝,网易,新浪等等...  技术原理   技术说穿了其实也就那么回事,懂了就简单了,呵呵~

基于文本密度的新闻正文抽取方法之Python实现

参考文章链接: http://www.cnblogs.com/jasondan/p/3497757.html http://d.wanfangdata.com.cn/Patent/CN201410007832.6/ 基于网页分析构思出的正文提取算法 回顾以上的网页分析,如果按照文本密度来找提取正文,那么就是写这么一个算法,能够从过滤html标签后的文本中找到正文文本的起止行号,行号之间的文本就是网页正文部分. 还是从上面三个网页的分析结果看,他们都有这么一个特性:正文部分的文本密度要高出非正文部