17

Tôi đang làm việc trên một chương trình tải xuống các trang HTML và sau đó chọn một số thông tin và ghi nó vào một tệp khác.Trích xuất văn bản từ HTML Java

Tôi muốn trích xuất thông tin nằm giữa các thẻ đoạn, nhưng tôi chỉ có thể lấy một dòng của đoạn văn. Mã của tôi là như sau;

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) { 
     } 
    } 
} 

tôi đã cố gắng để thêm một vòng lặp while, mà sẽ nói với chương trình để tiếp tục viết để nộp cho đến khi dòng chứa thẻ </p>, bằng cách nói;

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

Nhưng điều này không hiệu quả. Ai đó có thể vui lòng giúp đỡ.

+0

Chúng tôi chắc chắn đang gặp lỗi trong việc thoát khỏi thẻ HTML của SO. – Yishai

+0

Bạn có trích dẫn chúng dưới dạng mã có dấu gạch chéo ngược không? – pjp

+0

Trình phân tích cú pháp HTML tồn tại và có rất nhiều trình phân tích cú pháp. –

Trả lời

1

Hãy thử (nếu bạn không muốn sử dụng một thư viện phân tích cú pháp 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) 
         { 

        } 
       } 
} 
+1

Điều gì sẽ xảy ra nếu '

' và '

' nằm trên cùng một dòng? Trong trường hợp này, chuỗi sẽ được viết ra hai lần.Tôi đoán nó thực sự phụ thuộc vào đầu vào. – pjp

+0

Bạn có thể thêm một số trạng thái để xem bạn đã viết ra dòng trước khi viết lại. – pjp

9

jericho là một trong những phân tích cú pháp html posible mà có thể làm nhiệm vụ này cả hai dễ dàng và an toàn.

4

JTidy có thể đại diện cho một tài liệu HTML (thậm chí là một tài liệu không đúng định dạng) làm mô hình tài liệu, làm cho quá trình trích xuất nội dung của thẻ <p> một quy trình khá thanh lịch hơn so với thủ công thông qua văn bản thô.

+0

Có cách nào tốt nhất để tránh phân tích cú pháp HTML theo cách thủ công – pjp

-2

Bạn có thể chỉ được sử dụng các công cụ sai cho công việc:

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

-1: câu trả lời sai cho câu hỏi –

+0

Đó là cảnh sát công bằng. Tuy nhiên, một loại hit muộn. – brianary

+2

Số lần truy cập trễ theo cả hai cách :) –

0

Sử dụng một ParserCallback. Một lớp đơn giản của nó bao gồm với JDK. Nó thông báo cho bạn mỗi lần tìm thấy một thẻ mới và sau đó bạn có thể trích xuất văn bản của thẻ. Ví dụ đơn giản:

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); 
     } 
    } 
} 

Vì vậy, tất cả những gì bạn cần làm là đặt cờ boolean khi tìm thấy thẻ đoạn. Sau đó, trong phương thức handleText() bạn trích xuất văn bản.

19

jsoup

Trình phân tích cú pháp html khác mà tôi thực sự thích sử dụng là jsoup. Bạn có thể nhận tất cả các phần tử <p> trong 2 dòng mã.

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

Sau đó viết nó ra vào một tập tin trong hơn một dòng

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

hoặc nếu bạn muốn họ trên dòng riêng biệt, bạn có thể lặp qua các yếu tố và viết chúng ra riêng rẽ.

+0

Nếu tài liệu không sử dụng thẻ 'p' (không đánh dấu ngữ nghĩa), tôi giả định điều này sẽ không hoạt động –

+1

@ sinθ Câu hỏi được yêu cầu một cách rõ ràng cho các phần tử' p'. Câu trả lời này chính xác tại chỗ. –

+0

Cảm ơn @Danny, tôi ♥ món súp này! –

0

Hãy thử điều này.

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(); 
} 
} 
+0

'Yếu tố' và 'Tài liệu' này là gì. Đây có phải là bất kỳ trình phân tích cú pháp của bên thứ ba nào không? Hiển thị các dòng nhập quá – James

Các vấn đề liên quan