Autore Topic: E' necessario un parser html nel mio caso?E qual'è il migliore?  (Letto 1886 volte)

Offline Phate

  • Utente junior
  • **
  • Post: 123
  • Respect: +6
    • Mostra profilo
  • Dispositivo Android:
    Samsung galaxy S
  • Sistema operativo:
    Windows 7
E' necessario un parser html nel mio caso?E qual'è il migliore?
« il: 10 Ottobre 2012, 10:52:18 CEST »
0
Allora, ho una serie di stringhe html e per adesso me la sto cavando con i metodi di string e le regular expression per fare quelle 2-3 manipolazioni che mi servono.
Le regex però sono pesanti e io faccio tre replaceAll di fila nel mio codice, così volevo sapere se è meglio aggiungere proprio una libreria esterna che mi faccia da parser html..da notare che il percorso sarebbe stringa --> struttura html--> manipolazione di alcuni tag --> di nuovo string.
E' chiaro che la cosa mi conviene solo se il miglioramento di prestazioni è sensibile...inoltre volevo sapere gli sviluppatori android cosa usano a questo scopo!
Io per i miei progetti java mi sono trovato bene con htmlcleaner ma provandolo un po' su android noto dei piccoli memory leaks..magari non è la scelta migliore?

Offline bradipao

  • Moderatore globale
  • Utente storico
  • *****
  • Post: 4043
  • keep it simple
  • Respect: +567
    • Github
    • Google+
    • bradipao
    • Mostra profilo
  • Dispositivo Android:
    Nexus 5
  • Play Store ID:
    Bradipao
  • Sistema operativo:
    W7
Re:E' necessario un parser html nel mio caso?E qual'è il migliore?
« Risposta #1 il: 10 Ottobre 2012, 11:01:09 CEST »
0
La mia è solo una sensazione: secondo me passare dal una struttura html ti rende il tutto un ordine di grandezza più lento.
NON rispondo a domande nei messaggi privati
Bradipao @ Play Store

Offline iceweasel

  • Moderatore globale
  • Utente senior
  • *****
  • Post: 878
  • Respect: +147
    • Mostra profilo
  • Dispositivo Android:
    LGE P990 - Google Nexus 5
  • Sistema operativo:
    Linux Debian Sid
Re:E' necessario un parser html nel mio caso?E qual'è il migliore?
« Risposta #2 il: 10 Ottobre 2012, 11:53:35 CEST »
+1
Se vedi il codice di Android della classe String la replaceAll è implementata con una regex :-)

Codice (Java): [Seleziona]
...
public String replaceAll(String regularExpression, String replacement) {
        return Pattern.compile(regularExpression).matcher(this).replaceAll(replacement);
    }
...

Per ottimizzare le manipolazioni di stringhe in Java la cosa migliore è utilizzare la regex con regole furbe pre-compilate statiche, generare il minor numero di stringhe intermedie, al massimo aiutarsi con la classe StringBuilder.




« Ultima modifica: 10 Ottobre 2012, 12:47:36 CEST da iceweasel »
adb logcat | tee /tmp/logcat | grep TAG

Offline Sakazaki

  • Utente normale
  • ***
  • Post: 396
  • Respect: +74
    • Mostra profilo
  • Dispositivo Android:
    Sony xperia Z
  • Play Store ID:
    Saka Labs
  • Sistema operativo:
    Windows 8
R: E' necessario un parser html nel mio caso?E qual'è il migliore?
« Risposta #3 il: 10 Ottobre 2012, 11:59:45 CEST »
0
Probabilmente non è questo il caso, ma confermo che per la concatenazione di stringhe lo string builder può portare a miglioramenti più che consistenti.

Inviato dal mio XT910 con Tapatalk 2


Offline Phate

  • Utente junior
  • **
  • Post: 123
  • Respect: +6
    • Mostra profilo
  • Dispositivo Android:
    Samsung galaxy S
  • Sistema operativo:
    Windows 7
Re:E' necessario un parser html nel mio caso?E qual'è il migliore?
« Risposta #4 il: 10 Ottobre 2012, 12:27:16 CEST »
0
In effetti facendo tre replaceAll di fila distruggo e ricreo delle stringhe, se fosse possibile usare StringBuilder con replaceAll sarebbe meglio...sapete se si può?

In ogni caso ice tu mi consigli di fare tutto con un unico oggetto Pattern invece di replace all e in effetti hai ragione visto che replaceAll ne ricrea uno ogni volta..ottima info!

Cmq mi confermate tutti che nel mio caso è meglio fare tutto direttamente con le stringhe piuttosto che usare un parser html?
« Ultima modifica: 10 Ottobre 2012, 12:37:47 CEST da Phate »

Offline Sakazaki

  • Utente normale
  • ***
  • Post: 396
  • Respect: +74
    • Mostra profilo
  • Dispositivo Android:
    Sony xperia Z
  • Play Store ID:
    Saka Labs
  • Sistema operativo:
    Windows 8
Re:E' necessario un parser html nel mio caso?E qual'è il migliore?
« Risposta #5 il: 10 Ottobre 2012, 13:14:50 CEST »
0
In effetti facendo tre replaceAll di fila distruggo e ricreo delle stringhe, se fosse possibile usare StringBuilder con replaceAll sarebbe meglio...sapete se si può?

In realtà il replaceAll usa già uno StringBuffer al suo interno.

Offline Phate

  • Utente junior
  • **
  • Post: 123
  • Respect: +6
    • Mostra profilo
  • Dispositivo Android:
    Samsung galaxy S
  • Sistema operativo:
    Windows 7
Re:E' necessario un parser html nel mio caso?E qual'è il migliore?
« Risposta #6 il: 10 Ottobre 2012, 13:47:01 CEST »
0
Si ma il mio codice è tipo:
Codice (Java): [Seleziona]
s = s.replaceAll(..).replaceAll(..).replaceAll(..);quindi ogni volta distruggo e ricreo.

Offline iceweasel

  • Moderatore globale
  • Utente senior
  • *****
  • Post: 878
  • Respect: +147
    • Mostra profilo
  • Dispositivo Android:
    LGE P990 - Google Nexus 5
  • Sistema operativo:
    Linux Debian Sid
Re:E' necessario un parser html nel mio caso?E qual'è il migliore?
« Risposta #7 il: 10 Ottobre 2012, 13:47:33 CEST »
0
La replaceAll compila l'espressione conforme ogni volta e le chiamate successive generano molte stringhe intermedie. Rendere statica la compilazione e accorpare le sostituzioni in un unica StringBuilder (la StringBuffer è leggermente più lenta) rende tutto più veloce e consuma meno memoria.
adb logcat | tee /tmp/logcat | grep TAG

Offline Phate

  • Utente junior
  • **
  • Post: 123
  • Respect: +6
    • Mostra profilo
  • Dispositivo Android:
    Samsung galaxy S
  • Sistema operativo:
    Windows 7
Re:E' necessario un parser html nel mio caso?E qual'è il migliore?
« Risposta #8 il: 10 Ottobre 2012, 16:15:12 CEST »
0
Risolto così, credo vada bene ma attendo giudizi:
Codice (Java): [Seleziona]
public class MyClass{
        private final static Pattern firstPattern = Pattern.compile("regex1");
        private final static Pattern secondPattern = Pattern.compile("regex2");
        private final static Pattern thirdPattern = Pattern.compile("regex3");

        public String applyRegex(String s){
           StringBuilder sb = new StringBuilder(s);
           Matcher m = firstPattern.matcher(sb);
           while(m.find())
                m.replaceAll("replacement");
           m = secondPattern.matcher(sb);
           while(m.find())
            .... e così via per tutti e 3
     
           return sb.toString();
        }

Offline Sakazaki

  • Utente normale
  • ***
  • Post: 396
  • Respect: +74
    • Mostra profilo
  • Dispositivo Android:
    Sony xperia Z
  • Play Store ID:
    Saka Labs
  • Sistema operativo:
    Windows 8
R: E' necessario un parser html nel mio caso?E qual'è il migliore?
« Risposta #9 il: 10 Ottobre 2012, 16:25:52 CEST »
0
Ad occhio e croce direi che farla più rapida di così è veramente difficile.

Inviato dal mio XT910 con Tapatalk 2


Offline iceweasel

  • Moderatore globale
  • Utente senior
  • *****
  • Post: 878
  • Respect: +147
    • Mostra profilo
  • Dispositivo Android:
    LGE P990 - Google Nexus 5
  • Sistema operativo:
    Linux Debian Sid
Re:E' necessario un parser html nel mio caso?E qual'è il migliore?
« Risposta #10 il: 10 Ottobre 2012, 23:02:28 CEST »
+1
Pessimo codice, poco efficiente e commetti due errori, inizializzi la StringBuilder con la stringa di partenza, ha poco senso se vuoi efficienza, deve partire vuota (al massimo fai una stima della grandezza) e poi gli aggiungi i pezzi, il secondo ancora più grave il metodo Matcher.replaceAll ha un loop proprio con find, basta vedere il codice sorgente:

Codice (Java): [Seleziona]
...
public String replaceAll(String replacement) {
        reset();
        StringBuffer buffer = new StringBuffer(input.length());
        while (find()) {
            appendReplacement(buffer, replacement);
        }
        return appendTail(buffer).toString();
    }
...

quindi un algoritmo di complessità N eseguito in N² visto che ci sono due loop annidiati.

Ti faccio vedere come eseguire una sola sostituzione poi sei libero di adattarlo:


Codice (Java): [Seleziona]
class Bar
{
  ...

    private static final Pattern pattern = Pattern.compile("\\banimal\\b");

    public void foot() {

        String text = "The animal jumps over the lazy dog. The animal on the run";     

        StringBuilder builder = new StringBuilder(text.length());
        Matcher matcher = pattern.matcher(text);

        int pos = 0;
        while (matcher.find()) {

            builder.append(text.substring(pos, matcher.start()));
            builder.append("quick brown fox");
            pos = matcher.end();
        }
        builder.append(text.substring(pos, matcher.regionEnd()));

        String result = builder.toString();

       ....
    }
}
adb logcat | tee /tmp/logcat | grep TAG

Offline Phate

  • Utente junior
  • **
  • Post: 123
  • Respect: +6
    • Mostra profilo
  • Dispositivo Android:
    Samsung galaxy S
  • Sistema operativo:
    Windows 7
Re:E' necessario un parser html nel mio caso?E qual'è il migliore?
« Risposta #11 il: 11 Ottobre 2012, 14:44:18 CEST »
0
Grazie mille! Allora, a partire dal tuo codice ho creato questa funzione:
Codice (Java): [Seleziona]
private String replaceAll(Pattern pattern, String original, String replacement){
                StringBuilder sb = new StringBuilder(original.length()+100);
                Matcher m = pattern.matcher(original);
                int pos = 0;
                while(m.find()){
                        sb.append(original.substring(pos, m.start()));
                        sb.append(replacement);
                        pos = m.end();
                }
                sb.append(original.substring(pos, m.regionEnd()));
               
                return sb.toString();
        }

e la invoco così:
Codice (Java): [Seleziona]
str = replaceAll(firstPattern, str,"first");
str = replaceAll(secondPattern, str, "second");
str = replaceAll(thirdPattern, str, "third");
che ne pensi??
« Ultima modifica: 11 Ottobre 2012, 14:59:11 CEST da Phate »

Offline iceweasel

  • Moderatore globale
  • Utente senior
  • *****
  • Post: 878
  • Respect: +147
    • Mostra profilo
  • Dispositivo Android:
    LGE P990 - Google Nexus 5
  • Sistema operativo:
    Linux Debian Sid
Re:E' necessario un parser html nel mio caso?E qual'è il migliore?
« Risposta #12 il: 11 Ottobre 2012, 22:15:01 CEST »
0
Si così va molto meglio, esegui 3 passaggi sui dati. Per fare tutto in un solo passaggio le 3 diverse regole conformi devono essere fuse in una sola, in generale non è sempre possibile.

Crei 3 volte l'oggetto StringBuilder, basta un solo e riciclarlo con "setLength(0)" (azzera gli indici interni senza riallocare la memoria successivamente).
adb logcat | tee /tmp/logcat | grep TAG