从 HTML Java 中提取文本

Posted

技术标签:

【中文标题】从 HTML Java 中提取文本【英文标题】:Text Extraction from HTML Java 【发布时间】:2010-11-26 01:05:54 【问题描述】:

我正在开发一个下载 html 页面然后选择一些信息并将其写入另一个文件的程序。

我想提取段落标签之间的信息,但我只能得到段落的一行。我的代码如下;

FileReader fileReader = new FileReader(file);
BufferedReader buffRd = new BufferedReader(fileReader);
BufferedWriter out = new BufferedWriter(new FileWriter(newFile.txt));
String s;

while ((s = br.readLine()) !=null) 
    if(s.contains("<p>")) 
        try 
            out.write(s);
         catch (IOException e) 
        
    

我试图添加另一个 while 循环,它会告诉程序继续写入文件,直到该行包含 &lt;/p&gt; 标记,通过说;

while ((s = br.readLine()) !=null) 
    if(s.contains("<p>")) 
        while(!s.contains("</p>") 
            try 
                out.write(s);
             catch (IOException e) 
            
        
    

但这不起作用。有人可以帮忙吗。

【问题讨论】:

我们肯定看到了 SO 转义 HTML 标签的错误。 您是否将它们作为带有反引号的代码引用? HTML 解析器确实存在,而且数量很多。 【参考方案1】:

jsoup

另一个我非常喜欢使用的 html 解析器是 jsoup。您可以在 2 行代码中获取所有 &lt;p&gt; 元素。

Document doc = Jsoup.connect("http://en.wikipedia.org/").get();
Elements ps = doc.select("p");

然后在一个文件中再写一行

out.write(ps.text());  //it will append all of the p elements together in one long string

或者,如果您希望它们在单独的行中,您可以遍历元素并单独写出它们。

【讨论】:

如果文档不使用p 标签(非语义标记),我认为这不起作用 @sinθ 该问题明确要求p 元素。这个答案是正确的。 谢谢@Danny,我♥这汤!【参考方案2】:

jericho 是几个可能的 html 解析器之一,它可以使这项任务既简单又安全。

【讨论】:

【参考方案3】:

JTidy 可以将 HTML 文档(甚至是格式错误的文档)表示为文档模型,这使得提取 &lt;p&gt; 标记内容的过程比手动遍历原始文本更为优雅。

【讨论】:

【参考方案4】:

尝试(如果您不想使用 HTML 解析器库):


        FileReader fileReader = new FileReader(file);
        BufferedReader buffRd = new BufferedReader(fileReader);
        BufferedWriter out = new BufferedWriter(new FileWriter(newFile.txt));
        String s;
        int writeTo = 0;
        while ((s = br.readLine()) !=null) 
        
                if(s.contains("<p>"))
                
                        writeTo = 1;

                        try 
                        
                            out.write(s);
                     
                        catch (IOException e) 
                        

                    
                
                if(s.contains("</p>"))
                
                        writeTo = 0;

                        try 
                        
                            out.write(s);
                     
                        catch (IOException e) 
                        

                    
                
                else if(writeTo==1)
                
                        try 
                        
                            out.write(s);
                     
                        catch (IOException e) 
                        

                    
                

【讨论】:

如果&lt;p&gt;&lt;/p&gt; 在同一行会怎样?在这种情况下,字符串将被写出两次。我想这真的取决于输入。 你可以添加一些状态,看看你是否已经写出了一行,然后再写出来。【参考方案5】:

我已经成功使用 TagSoup 和 XPath 解析 HTML。

http://home.ccil.org/~cowan/XML/tagsoup/

【讨论】:

【参考方案6】:

使用 ParserCallback。它是 JDK 中包含的一个简单类。每次找到新标签时它都会通知您,然后您可以提取标签的文本。简单例子:

import java.io.*;
import java.net.*;
import javax.swing.text.*;
import javax.swing.text.html.*;
import javax.swing.text.html.parser.*;

public class ParserCallbackTest extends HTMLEditorKit.ParserCallback

    private int tabLevel = 1;
    private int line = 1;

    public void handleComment(char[] data, int pos)
    
        displayData(new String(data));
    

    public void handleEndOfLineString(String eol)
    
        System.out.println( line++ );
    

    public void handleEndTag(HTML.Tag tag, int pos)
    
        tabLevel--;
        displayData("/" + tag);
    

    public void handleError(String errorMsg, int pos)
    
        displayData(pos + ":" + errorMsg);
    

    public void handleMutableTag(HTML.Tag tag, MutableAttributeSet a, int pos)
    
        displayData("mutable:" + tag + ": " + pos + ": " + a);
    

    public void handleSimpleTag(HTML.Tag tag, MutableAttributeSet a, int pos)
    
        displayData( tag + "::" + a );
//      tabLevel++;
    

    public void handleStartTag(HTML.Tag tag, MutableAttributeSet a, int pos)
    
        displayData( tag + ":" + a );
        tabLevel++;
    

    public void handleText(char[] data, int pos)
    
        displayData( new String(data) );
    

    private void displayData(String text)
    
        for (int i = 0; i < tabLevel; i++)
            System.out.print("\t");

        System.out.println(text);
    

    public static void main(String[] args)
    throws IOException
    
        ParserCallbackTest parser = new ParserCallbackTest();

        // args[0] is the file to parse

        Reader reader = new FileReader(args[0]);
//      URLConnection conn = new URL(args[0]).openConnection();
//      Reader reader = new InputStreamReader(conn.getInputStream());

        try
        
            new ParserDelegator().parse(reader, parser, true);
        
        catch (IOException e)
        
            System.out.println(e);
        
    

所以你需要做的就是在找到段落标签时设置一个布尔标志。然后在 handleText() 方法中提取文本。

【讨论】:

【参考方案7】:

试试这个。

 public static void main( String[] args )

    String url = "http://en.wikipedia.org/wiki/Big_data";

    Document document;
    try 
        document = Jsoup.connect(url).get();
        Elements paragraphs = document.select("p");

        Element firstParagraph = paragraphs.first();
        Element lastParagraph = paragraphs.last();
        Element p;
        int i=1;
        p=firstParagraph;
        System.out.println("*  " +p.text());
        while (p!=lastParagraph)
            p=paragraphs.get(i);
            System.out.println("*  " +p.text());
            i++;
         
 catch (IOException e) 
    // TODO Auto-generated catch block
    e.printStackTrace();


【讨论】:

这个“元素”和“文档”是什么。这是任何第三方解析器吗?也显示导入行【参考方案8】:

您可能只是在工作中使用了错误的工具:

perl -ne "print if m|<p>| .. m|</p>|" infile.txt >outfile.txt

【讨论】:

这是一个公平的警察。不过有点晚了。

以上是关于从 HTML Java 中提取文本的主要内容,如果未能解决你的问题,请参考以下文章

Java提取文本文档中的所有网址(小案例介绍正则基础知识)

从 HTML 页面上的多个帖子中提取三个文本项到 csv 或类似文件中?

js如何从mp4文件获取电影名称图片

从文本文档图像中提取文本检测特征

我的位图文本文件中的所有字符都是中文

如何从文本文档中预测连续值(时间)? [关闭]