Guest User

Untitled

a guest
Oct 16th, 2013
709
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. package com.shashok.vpustotu;
  2.  
  3. import java.awt.event.*;
  4. import java.io.*;
  5. import java.nio.charset.Charset;
  6. import java.nio.file.*;
  7. import java.security.MessageDigest;
  8. import java.security.NoSuchAlgorithmException;
  9. import java.util.*;
  10. import java.util.concurrent.*;
  11. import javax.swing.Timer;
  12. //кодирование в Hex формат
  13. import org.apache.commons.codec.binary.Hex;
  14. //парсинг html
  15. import org.jsoup.Jsoup;
  16. import org.jsoup.nodes.*;
  17. //парсинг командной строки
  18. import com.beust.jcommander.*;
  19.  
  20. import static java.nio.file.StandardOpenOption.*;
  21.  
  22. public class Grabber implements Runnable{
  23.    
  24.     static BlockingQueue<String> queue = new ArrayBlockingQueue<>(10); //очередь цитат от парсеров в обработчик
  25.    
  26.     static Set<String> hashes = new HashSet<>(); //список хешей прочтёных цитат       
  27.    
  28.     static int quotesCount, dupCount; //счетчики цитат и дубликатов
  29.    
  30.     @Override
  31.     public void run() {
  32.         try {
  33.             while (true) {  //в вечном цикле собираем данные
  34.                 Document doc = Jsoup.connect("http://vpustotu.ru/moderation/").get();
  35.                 Element element = doc.getElementsByClass("fi_text").first();
  36.                 if (element != null){
  37.                     queue.put(element.text()); //и отправляем их в очередь
  38.                 }
  39.             }
  40.         } catch (IOException | InterruptedException e) {
  41.             e.printStackTrace();
  42.         }      
  43.     }
  44.    
  45.     private static class CommandLine {
  46.         @Parameter(names = "-h", help = true)
  47.         boolean help;
  48.        
  49.         @Parameter(names = "-w", description = "количество потоков")
  50.         int workers = 2;
  51.        
  52.         @Parameter(names = "-r", description = "частота отчетов (сек)")
  53.         int reportPeriod = 10;
  54.        
  55.         @Parameter(names = "-d", description = "кол-во дубликатов для остановки")
  56.         int dupToStop = 500;
  57.        
  58.         @Parameter(names = "-hf", description = "файл хешей")
  59.         String hashFile = "hash.bin";
  60.        
  61.         @Parameter(names = "-qf", description = "файл записей")
  62.         String quotesFile = "quotes.txt";
  63.     }
  64.    
  65.     public static void main(String[] args) throws IOException, NoSuchAlgorithmException, InterruptedException {
  66.         final CommandLine commandLine = new CommandLine(); //тут будут переданные аргументы
  67.         JCommander commander = new JCommander(commandLine, args); //вот такой нетипичный вызов  
  68.         if (commandLine.help) commander.usage(); //вызов справки надо обрабатывать вручную
  69.        
  70.         MessageDigest md5 = MessageDigest.getInstance("MD5");
  71.        
  72.         //Открываем файлы: хеши на чтение и запись, цитаты только на запись
  73.         try (OutputStream hashFile = Files.newOutputStream(Paths.get(commandLine.hashFile),
  74.                     CREATE, APPEND, WRITE, SYNC);
  75.              InputStream hashStream = Files.newInputStream(Paths.get(commandLine.hashFile));
  76.              BufferedWriter quotesFile = Files.newBufferedWriter(Paths.get(commandLine.quotesFile),
  77.                     Charset.forName("UTF8"), CREATE, APPEND, WRITE, SYNC)) {       
  78.        
  79.             //читаем хеши
  80.             byte[] hbytes = new byte[16]; //читать будем блоками по 16 байт - как раз один хеш
  81.             while (hashStream.read(hbytes) != -1){
  82.                 hashes.add(Hex.encodeHexString(hbytes));
  83.             }
  84.                    
  85.             //в цикле создадим нужное нам количество worker'oв
  86.             for (int i = 0; i < commandLine.workers; i++){
  87.                 Thread worker = new Thread(new Grabber());
  88.                 worker.setPriority(2);
  89.                 worker.setDaemon(true);
  90.                 worker.start();
  91.             }
  92.            
  93.             //таймер оповещения о текущем состоянии
  94.             new Timer(commandLine.reportPeriod * 1000, new ActionListener() {              
  95.                 @Override
  96.                 public void actionPerformed(ActionEvent arg0) {
  97.                     System.out.printf("Всего %d / Повторов %d (%d записей/сек) \n",
  98.                         hashes.size(), dupCount, quotesCount/commandLine.reportPeriod);
  99.                     quotesCount = 0;
  100.                 }
  101.             }).start();
  102.            
  103.             //оповещение при закрытии
  104.             Runtime.getRuntime().addShutdownHook(new Thread() {
  105.                 public void run() {
  106.                     System.out.printf("Завершаю работу. Всего записей: " + hashes.size());
  107.                 }
  108.             });
  109.    
  110.             while (true) {
  111.                 String quote = queue.take(); //принимаем цитаты по очереди
  112.                 quotesCount++;
  113.                 md5.update(quote.getBytes());
  114.                 byte[] hash = md5.digest(); //считаем хеш
  115.                 String hashString = Hex.encodeHexString(hash); //конвертируем в строку
  116.                 if (!hashes.contains(hashString)){ //проверяем уникальность хеша цитаты
  117.                     //все в порядке - заносим хеш в хранилище
  118.                     hashes.add(hashString);
  119.                     //записываем хеш и цитату в файлы
  120.                     hashFile.write(hash);
  121.                     quotesFile.write(quote);
  122.                     quotesFile.write("\n\n\n");
  123.                     quotesFile.flush();                
  124.                 } else {
  125.                     if (++dupCount == commandLine.dupToStop){
  126.     System.out.println("Достигнут предел повторов, завершаю работу. Всего записей: "+hashes.size());
  127.                                     return;
  128.                     }
  129.                 }
  130.             }
  131.         }
  132.     }
  133. }
RAW Paste Data