2010-03-05 38 views
13

Tôi đang phân tích email. Khi tôi thấy câu trả lời cho một email, tôi muốn xóa văn bản được trích dẫn để tôi có thể thêm văn bản vào email trước đó (ngay cả khi thư trả lời của nó).Cách xóa văn bản được trích dẫn khỏi email và chỉ hiển thị văn bản mới

Thông thường, bạn sẽ thấy điều này:

email 1 (bắt đầu cuộc nói chuyện)

This is the first email 

email thứ 2 (trả lời đầu tiên)

This is the second email 

Tim said: 
This is the first email 

Kết quả của điều này sẽ "Đây là email thứ hai". Mặc dù các ứng dụng email khác nhau trích dẫn văn bản khác nhau, nếu có một số cách khác nhau để nhận hầu hết văn bản email mới, điều đó cũng có thể chấp nhận được.

Trả lời

2

Khi các email trước đó được lưu trữ trên đĩa, hoặc có sẵn somwhow, bạn có thể kiểm tra tất cả các thư, gửi bởi một người nhận cụ thể để xác định, đó là văn bản phản hồi.

Bạn cũng có thể thử xác định ký tự trích dẫn bằng cách kiểm tra ký tự đầu tiên của dòng cuối cùng. Normaly những dòng cuối cùng luôn luôn bắt đầu với cùng một nhân vật.

Khi 2 dòng cuối cùng bắt đầu bằng một ký tự ifferent, bạn có thể thử các dòng đầu tiên, bởi vì đôi khi câu trả lời được thêm vào ở cuối văn bản.

Nếu bạn đã phát hiện ra các ký tự này, bạn có thể xóa các dòng cuối cùng bắt đầu bằng ký tự này cho đến khi một dòng trống hoặc một dòng bắt đầu với một ký tự khác được phát hiện.

chưa được thử nghiệm và là giống như mã giả

String[] lines; 

    // Check the size of the array first, length > 2 
    char startingChar = lines[lines.length - 1].charAt(0); 
    int foundCounter = 0; 
    for (int i = lines.length - 2; i >=0; --i) { 
     String line = lines[i]; 

     // Check line size > 0 
     if(startingChar == line.charAt(0)){ 
      ++foundCounter; 
     } 
    } 

    final int YOUR_DECISION = 2; // You can decide 
    if(foundCounter > YOUR_DECISION){ 
     deleteLastLinesHere(startingChar, foundCounter); 
    } 
+1

'char startingChar = lines [lines.length - 1];' sẽ không biên dịch. Ý của bạn là 'char startingChar = lines [lines.length - 1] .charAt (0);'? – sfussenegger

+1

vâng, xin lỗi. Như tôi đã nói, điều này giống như mã giả;). Tôi sẽ cập nhật câu trả lời –

1

Từ quan sát hành vi của Gmail trong vấn đề này tôi đã quan sát chiến lược của họ:

  1. viết thư thứ 2 hoàn chỉnh.
  2. Nối văn bản như: Mở [timestamp], [đầu tiên tên người gửi email] < [đầu tiên email của người gửi địa chỉ email]> đã viết:
  3. Nối email hoàn chỉnh đầu tiên. a. Nếu email của bạn ở dạng văn bản thuần thì hãy thêm '>' trước mỗi dòng của email đầu tiên. b. Nếu nó ở dạng HTML thì Gmail cung cấp lề trái như:

    border-left: 1px solid #CCC; lề: 0px 0px 0px 0.8x; padding-left: 1ex; biểu định kiểu tác nhân người dùng blockquote

    và sau đó nối văn bản của email đầu tiên.

Bạn có thể đảo ngược kỹ thuật này khi phân tích email từ địa chỉ Gmail. Tôi đã không nhìn vào các khách hàng khác nhưng họ nên có hành vi tương tự.

1

Bạn sẽ nhận được nó gần đúng với một vài dòng mã:

String newMessage = ""; 
for (String line : emailLines) { 
    if (!line.matches("^[>].*")) { 
    newMessage = newMessage.concat(line); 
    } 
} 

Nếu cần thiết, bạn có thể thêm kiểm tra regex khác cho khách hàng e-mail mà lại chữ ký văn bản trích dẫn khác nhau.

+0

Tôi thích cách tiếp cận đơn giản. –

12

tôi sử dụng regex sau (s) để phù hợp với đầu trong việc cho văn bản trích dẫn (người cuối cùng là một mà đếm):

/** general spacers for time and date */ 
    private static final String spacers = "[\\s,/\\.\\-]"; 

    /** matches times */ 
    private static final String timePattern = "(?:[0-2])?[0-9]:[0-5][0-9](?::[0-5][0-9])?(?:(?:\\s)?[AP]M)?"; 

    /** matches day of the week */ 
    private static final String dayPattern = "(?:(?:Mon(?:day)?)|(?:Tue(?:sday)?)|(?:Wed(?:nesday)?)|(?:Thu(?:rsday)?)|(?:Fri(?:day)?)|(?:Sat(?:urday)?)|(?:Sun(?:day)?))"; 

    /** matches day of the month (number and st, nd, rd, th) */ 
    private static final String dayOfMonthPattern = "[0-3]?[0-9]" + spacers + "*(?:(?:th)|(?:st)|(?:nd)|(?:rd))?"; 

    /** matches months (numeric and text) */ 
    private static final String monthPattern = "(?:(?:Jan(?:uary)?)|(?:Feb(?:uary)?)|(?:Mar(?:ch)?)|(?:Apr(?:il)?)|(?:May)|(?:Jun(?:e)?)|(?:Jul(?:y)?)" + 
               "|(?:Aug(?:ust)?)|(?:Sep(?:tember)?)|(?:Oct(?:ober)?)|(?:Nov(?:ember)?)|(?:Dec(?:ember)?)|(?:[0-1]?[0-9]))"; 

    /** matches years (only 1000's and 2000's, because we are matching emails) */ 
    private static final String yearPattern = "(?:[1-2]?[0-9])[0-9][0-9]"; 

    /** matches a full date */ 
    private static final String datePattern  = "(?:" + dayPattern + spacers + "+)?(?:(?:" + dayOfMonthPattern + spacers + "+" + monthPattern + ")|" + 
               "(?:" + monthPattern + spacers + "+" + dayOfMonthPattern + "))" + 
               spacers + "+" + yearPattern; 

    /** matches a date and time combo (in either order) */ 
    private static final String dateTimePattern = "(?:" + datePattern + "[\\s,]*(?:(?:at)|(?:@))?\\s*" + timePattern + ")|" + 
               "(?:" + timePattern + "[\\s,]*(?:on)?\\s*"+ datePattern + ")"; 

    /** matches a leading line such as 
    * ----Original Message---- 
    * or simply 
    * ------------------------ 
    */ 
    private static final String leadInLine = "-+\\s*(?:Original(?:\\sMessage)?)?\\s*-+\n"; 

    /** matches a header line indicating the date */ 
    private static final String dateLine = "(?:(?:date)|(?:sent)|(?:time)):\\s*"+ dateTimePattern + ".*\n"; 

    /** matches a subject or address line */ 
    private static final String subjectOrAddressLine = "((?:from)|(?:subject)|(?:b?cc)|(?:to))|:.*\n"; 

    /** matches gmail style quoted text beginning, i.e. 
    * On Mon Jun 7, 2010 at 8:50 PM, Simon wrote: 
    */ 
    private static final String gmailQuotedTextBeginning = "(On\\s+" + dateTimePattern + ".*wrote:\n)"; 


    /** matches the start of a quoted section of an email */ 
    private static final Pattern QUOTED_TEXT_BEGINNING = Pattern.compile("(?i)(?:(?:" + leadInLine + ")?" + 
                     "(?:(?:" +subjectOrAddressLine + ")|(?:" + dateLine + ")){2,6})|(?:" + 
                     gmailQuotedTextBeginning + ")" 
                    ); 

Tôi biết rằng trong một số cách này là quá mức cần thiết (và might chậm!) nhưng nó hoạt động khá tốt. Xin vui lòng cho tôi biết nếu bạn tìm thấy bất cứ điều gì mà không phù hợp với điều này vì vậy tôi có thể cải thiện nó!

+1

Tầm quan trọng của {2,6} trong QUOTED_TEXT_BEGINNING là gì? Bạn có thể đưa ra một ví dụ mà nó sẽ phù hợp? – Divij

+1

@Divij yêu cầu có ít nhất 2 và không quá 6 dòng từ tập hợp: chủ đề, đến, từ, bcc, cc, ngày. Một tối thiểu sẽ giống như và chủ đề, ở mức tối đa, tất cả 6. Họ dường như xảy ra theo thứ tự nào, vì vậy tôi giữ trật tự lỏng lẻo, nhưng muốn ràng buộc nó vì lý do chất lượng và hiệu suất. – smurthas

+0

Cảm ơn câu trả lời của bạn, chúng tôi rất thích chúng tôi. nhưng, Mẫu này không hoặc cho dòng sau "Vào ngày 16-09-2014, Thử nghiệm dịch vụ Indies đã viết:" vui lòng đưa ra giải pháp càng sớm càng tốt –

2

RegEx hoạt động tốt, ngoại trừ nó phù hợp với văn bản mà bắt đầu từ Chủ đề và bỏ qua tất cả mọi thứ mà đi trước "Subject"

Text 
-------- Original Message -------- 
<TABLE border="0" cellpadding="0" cellspacing="0"> 
    <TBODY> 
    <TR> 
     <TH align="right" valign="baseline"> 
     // the matcher starts working from here 
5

Kiểm tra các bằng sáng chế google về vấn đề này: http://www.google.com/patents/US7222299

Nói tóm lại họ băm phần các văn bản (có lẽ là một cái gì đó giống như câu) và sau đó tìm kiếm các trận đấu để băm trong các tin nhắn trước đó. Siêu nhanh và họ có thể sử dụng điều này làm đầu vào cho thuật toán luồng. Thật là một ý tưởng hay!

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