Hiệu suất bộ lọc thô tục trong Java


9

Tôi có một yêu cầu để lọc thô tục ra khỏi các bài đăng của người dùng trong một ứng dụng web dựa trên Java. Khách hàng nhận thức được cả Vấn đề ScunthorpeVấn đề Clbuttic và đã chấp nhận hậu quả. Xin vui lòng, tôi không mong muốn một cuộc tranh luận về giá trị của việc thiếu kiểm duyệt.

Có hai bit dữ liệu:

  1. Nội dung gửi của người dùng, có khả năng chứa 500 từ hoặc hơn;
  2. Bảng cơ sở dữ liệu một cột chứa các từ không được phép. Có thể có hàng ngàn hồ sơ trong bảng này.

Giải pháp hiện tại có vẻ sai đối với tôi:

  1. Toàn bộ bảng được tải vào Chuỗi tĩnh [] khi khởi động vào Singleton (do đó nằm trong bộ nhớ).
  2. Đối với mỗi lần gửi của người dùng, chúng tôi lặp qua mảng và thực hiện .indexOf () để xem liệu có từ nào trong Chuỗi [] xuất hiện trong nội dung gửi không.
  3. Nếu nó xuất hiện, chúng tôi thay thế bằng các ký tự kiểu% $ # @%. Điều này được thực hiện bằng cách mã hóa nội dung gửi của người dùng, lặp qua toàn bộ nội dung gửi của người dùng dưới dạng mã thông báo (một lần nữa) và thay thế từng phiên bản của từ được tìm thấy.

Có thể có sự sáng chói trong giải pháp này, nhưng tôi nghi ngờ. Và nhìn nó một lúc tôi không thể tìm được cách vượt qua nó.

Câu hỏi là, giải pháp nào sẽ mang lại hiệu suất tốt và hy vọng có thể hợp lý để các nhà phát triển trong tương lai duy trì sau khi tôi bị sa thải vì không lọc được một số từ tối nghĩa mà tôi chưa từng nghe đến?


Bạn nói điều đó có vẻ sai với bạn, mà không cho chúng tôi biết lý do tại sao bạn nghĩ nó sai. Sau đó, bạn yêu cầu một giải pháp hiệu quả, mà không cho chúng tôi biết, theo cách nào thì giải pháp hiện tại không đủ. Bạn nhận được bao nhiêu văn bản mỗi giây, bạn có thể xử lý bao nhiêu văn bản?
người dùng không xác định

Tôi nghĩ rằng giải pháp là sai, chủ yếu là do cơ sở mã mà tôi đang làm việc không đầy đủ và cẩu thả. Với sự thiên vị của tôi, tôi đã không tin tưởng vào sự ngờ vực của chính mình. Tôi cảm thấy rằng ý kiến ​​của người khác sẽ có lợi. Những thứ gây ra báo động cho tôi là Chuỗi [] (đây là gì năm 1999?), Lặp lại chuỗi rất lớn [] thay vì tập dữ liệu nhỏ hơn nhiều mà người dùng gửi, lồng một vòng lặp bên trong vòng lặp Chuỗi [] với trình người dùng mã thông báo, và như vậy. Việc sử dụng dự kiến ​​là không xác định, lý tưởng là một giải pháp thanh lịch với hiệu suất hợp lý sẽ rất đáng yêu.
cá vây xanh

2
"Hiệu suất hợp lý" có thể có nghĩa là bất cứ điều gì. Nếu bạn không có một mục tiêu cụ thể, bạn không thể biết liệu bạn có đạt được nó hay không. Nếu bạn tăng tốc quá trình, sao cho nhanh hơn 100 lần - đây có phải là mục tiêu không? Nếu người dùng đang chờ 1ms hay 1/10? Người dùng sẽ không được hưởng lợi từ công việc của bạn.
người dùng không xác định

Câu trả lời:


18

Cách duy nhất để thực hiện bộ lọc từ một cách thông minh là sử dụng hệ thống kết hợp ngữ âm. Tôi đã viết một bộ lọc thô tục rất hiệu quả cho một trò chơi trực tuyến nhiều người chơi rất phổ biến dành cho thanh thiếu niên và thanh thiếu niên vài năm trước trong Java.

Nó được dựa trên một đúp sửa đổi cao MetaPhone thuật toán đã được tinh chỉnh để có nhiều chính xác thay vì mặc định là để phù hợp với nhiều thứ càng tốt. Nó cực kỳ hiệu quả vì nó đã chọn cách viết sai và cách phát âm giống như các từ thực tế. Tôi cũng đã thêm l33tnói và txtnói với thuật toán MetaPhone, làm cho nó trở thành thuật toán Triple / Quad Metaphone nhiều hơn.

Nó có một bộ xử lý trước nén các chữ cái đang chạy và phát hiện ra những thứ như những đứa trẻ sắp xếp những thứ như w o r d sbằng cách nén các chữ cái lại với nhau một cách thông minh và loại bỏ các bản sao đang chạy như thế wwoorrddss, nó chỉ dành riêng cho tiếng Anh.

Nó đã đủ nhanh 8 năm trước để được sử dụng trong luồng hệ thống trò chuyện thời gian thực mà không có bất kỳ độ trễ đáng chú ý nào với hàng chục ngàn người dùng trên một hệ thống CPU lõi đơn.

Chúng tôi có một danh sách các từ được Metaphone mã hóa trong một bảng trong cơ sở dữ liệu và nó được tải vào Bản đồ tĩnh nhỏ đến mức đáng ngạc nhiên và chúng tôi không bao giờ phải làm gì đặc biệt để truy cập danh sách các từ bị cấm, tôi có thể thêm phát hiện cụm từ bằng cách sử dụng các kỹ thuật tương tự cho gần như miễn phí.

Tất nhiên tôi đã có một bản ghi hoạt động của tất cả các cuộc trò chuyện từ hàng ngàn trẻ em đang cố gắng phá vỡ hệ thống trong thời gian thực vì vậy tôi đã có một bộ dữ liệu khá toàn diện để làm việc. Cách tôi thực hiện ghi nhật ký là khi ai đó kích hoạt bộ lọc bằng số dương, tôi đã ghi lại một số tin nhắn trò chuyện tiếp theo không kích hoạt bộ lọc từ họ, theo cách đó nếu họ tìm được cách xoay quanh một từ hoặc cụm từ cụ thể, tôi có thể điều chỉnh hệ thống của tôi và nắm bắt điều đó Tôi đã có bằng chứng đạn khá đẹp chỉ sau vài tuần.


3
Giải pháp này có vẻ là tốt nhất. Vấn đề là (hoặc tại thời điểm này) mà tôi đã phải giải quyết nó vào một buổi chiều. Nếu có đủ thời gian, tôi sẽ thực hiện phương pháp Double MetaPhone hoặc thuê bạn làm việc đó. :-)
blueishgoldfish

Vì vậy, tôi đoán một nửa số người sẽ ngừng chơi trò chơi ngay bây giờ: D
Davor dralo

2

Nếu bạn muốn thực hiện việc khớp một cách hiệu quả, thuật toán Aho Corasick là một tùy chọn khá tốt (tôi chắc chắn bạn có thể tìm thấy một triển khai Java trôi nổi xung quanh).

Tất nhiên, bạn có thể muốn xử lý trước bài nộp để thay thế bất kỳ lỗi chính tả nào ('$' -> 's', '@' -> 'a', '| <' -> 'k', v.v.)


Chính xác những gì tôi đang tìm kiếm, cảm ơn! Đây là một triển khai Java: hkn.eecs.ber siêu.edu / ~ ydy / java
Remi Mélisson

0

Thay vì tải vào Chuỗi tĩnh [], hãy sử dụng HashMap [] hoặc một số loại cây nhị phân khác (nếu bạn muốn cải thiện tìm kiếm) làm cho chuỗi trở thành khóa của bạn trong hàm băm. Tách Chuỗi của bạn theo dấu cách và xóa dấu chấm câu. Sau đó, bạn có thể truy vấn HashMap cho mỗi từ trong phân tách chuỗi của bạn; nếu hashmap trở lại với null null thì bạn biết bạn có một từ xấu.

Điều thất bại ở đây là vấn đề Clbuttic khi ai đó thêm các ký tự ngẫu nhiên xung quanh từ xấu ex. bhassda


Tôi nghĩ rằng sự cảnh báo cuối cùng là điều làm cho giải pháp này trở nên vô dụng - không có cách nào để mở rộng nó thành bất cứ điều gì ngoài các trận đấu toàn từ.

Đó là một tuyên bố công bằng; nhưng nó trở nên khó nắm bắt mọi điều có thể mà tâm trí con người có thể nghĩ ra để trốn tránh một bộ lọc thô tục. Bạn luôn có thể tạo một biểu thức chính quy lớn với các câu lệnh OR để kết hợp tất cả các tùy chọn và sau đó khớp biểu thức chính quy với đầu vào. HOẶC bạn có thể thực hiện chọn từ cơ sở dữ liệu với "trường từ xấu" từ cơ sở dữ liệu có RLIKE so với đầu vào. Trả về chỉ từ xấu và cũng sẽ trả lại từ xấu.

@Suroot Không khó để nắm bắt bất kỳ từ hoặc cụm từ nào phù hợp với ngữ âm như câu hỏi của tôi nói về. Kết hợp tuyệt đối sẽ không bao giờ hoạt động hoặc tỷ lệ, nhưng kết hợp ngữ âm hoạt động gần như 100% thời gian một khi bạn điều chỉnh như bạn có thể có được.

-1

Sử dụng một hệ thống ngữ âm không phải là giải pháp duy nhất bằng bất kỳ phương tiện nào, nhưng nó có thể là đơn giản nhất vì có rất nhiều thư viện nguồn mở thực hiện loại điều đó.

Phần cứng luôn luôn là phần phù hợp của bất kỳ thuật toán nào và có vẻ như trận đấu của bạn khá chậm và ngây thơ. Bạn không thể cho rằng indexOf sẽ khớp chính xác mà không cần một số hình thức kiểm tra phụ trợ.

Ngoài ra, bạn sẽ kết thúc vòng lặp trên toàn bộ chuỗi N lần, trong đó N là số lượng từ trong danh sách đen của bạn. Các đề xuất sử dụng Set hoặc HashMap chắc chắn sẽ cải thiện mọi thứ phần nào.

Trong hầu hết các trường hợp, một thuật toán dựa trên trạng thái tuyến tính là tốt nhất và nhanh nhất. Tôi đã viết giải pháp cho Clean Nói và nó sử dụng loại thuật toán này với một hệ thống kết hợp ngữ âm tiền xử lý. Đây là giải pháp duy nhất không trở nên phức tạp khi được sử dụng thô tục (nếu foo là thô tục, nhúng là foosucker) và có thể duy trì mức hiệu suất cao. Nó cũng mở rộng quy mô độc đáo cho các ngôn ngữ khác mà không cần triển khai các bộ mã mới.

Cuối cùng, tiền xử lý dưới mọi hình thức thường là điều cần tránh. Trong hầu hết các trường hợp, bạn có thể làm điều tương tự theo kiểu tuyến tính khi bạn xử lý từng ký tự trong chuỗi.

Tất nhiên, tôi khuyên bạn nên xem xét các giải pháp khác trong dài hạn vì trong hầu hết các ứng dụng xử lý nội dung do người dùng tạo phức tạp hơn là chỉ lọc thô tục. Thường thì bạn cũng muốn lọc thông tin cá nhân như email và số an sinh xã hội và đôi khi những thứ như URL. Thêm vào đó, chúng tôi đã thấy rằng hầu hết các ứng dụng cần một số hình thức kiểm duyệt nội dung và hệ thống. Những sự gia tăng phức tạp đáng kể.


-2

Những gì bạn muốn làm trong trường hợp như thế này là xác định danh sách nào trong hai danh sách từ là danh sách nhỏ hơn. Nói danh sách "verboten" của bạn chứa 2000 từ và lượng người dùng gửi tối đa là 500 từ. Trong trường hợp đó, bạn sẽ lặp qua danh sách các từ trong bài gửi của người dùng và tìm từng từ một trong danh sách các từ bị cấm và ngược lại.

Một thay đổi khác tôi sẽ thực hiện là bạn không giữ danh sách các từ bị cấm trong Chuỗi [] - nếu bạn tìm kiếm trong mảng bạn đã tìm kiếm O (n) cho mỗi từ trong bài đăng của người dùng. Điều đó khá tệ. Tôi sẽ cố gắng đưa cấu trúc dữ liệu mà bạn đang tìm kiếm vào một loại cấu trúc cây hoặc thùng chứa kết hợp nào đó có hiệu suất tra cứu tốt hơn (log n thay vì n). Thách thức ở đây là nếu bạn đặt người dùng gửi vào thùng chứa này, bạn sẽ phải theo dõi vị trí từ để bạn có thể xây dựng lại đầu vào hoặc cập nhật chuỗi đầu vào nếu bạn có một lần tìm kiếm.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.