【问题标题】:Text Extraction from HTML Java从 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 解析器确实存在,而且数量很多。

标签: java html screen-scraping html-content-extraction text-extraction


【解决方案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
          

          【讨论】:

          • 这是一个公平的警察。不过有点晚了。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-04-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多