2010-09-07 11 views
0

En travaillant sur Android SDK, c'est Java moins certaines choses.Extraire tout sauf les balises d'une page Web sans analyseur - en utilisant un scanner et une regex?

J'ai une solution qui extrait deux motifs regex à partir de pages Web. Les problèmes que j'ai, c'est que c'est de trouver des choses dans les balises HTML. J'ai essayé jTidy, mais c'était trop lent sur Android. Je ne sais pas pourquoi, mais ma solution de rechange Scanner regex le fouille plusieurs fois.

actuellement, je prends la source de la page dans un IntputStream

is = uconn.getInputStream(); 

et le match et l'extrait comme ceci:

Scanner scanner = new Scanner(in, "UTF-8"); 
String match = ""; 
while (match != null) { 
    match = scanner.findWithinHorizon(extractPattern, 0); 
    if (match != null) { 
     String matchit = scanner.match().group(grp); 

cela fonctionne très bien et est rapide.

Mon modèle regex est déjà un peu fou, en fait deux modèles dans un ou comme celui-ci (p1 | p2)

Toutes les idées sur la façon dont je le fais «mais pas à l'intérieur des balises HTML » ou exclure des balises HTML au début ? Si je peux exclure des balises HTML de ma source, cela accélèrera considérablement mon interface car j'ai d'autres choses à faire avec les données brutes.

+0

Rien de tel que [parsing HTML le chemin Cthulhu] (http://www.codinghorror.com/blog/2009/11/parsing-html-the-cthulhu-way.html), hein? – NullUserException

Répondre

1

Une chose que vous pouvez faire est d'ajouter un test avant de l'équerre de fermeture:

(p1|p2)(?![^<>]*+>) 

L'idée est, une fois que vous trouver un match que vous scannez un peu en avant; Si vous trouvez un crochet de fermeture sans voir d'abord un crochet d'ouverture, la correspondance doit avoir eu lieu à l'intérieur d'une étiquette, alors rejetez-la. Mais sachez que même dans le HTML bien formé, il y a beaucoup de choses qui peuvent vous déranger, comme les commentaires SGML, les sections CDATA, ou même les chevrons dans les valeurs d'attributs.

Une autre approche serait de faire correspondre les balises et ignorer ces matches:

((?:<[^<>]++>)++)(p1|p2) 

Ensuite, vous tester si c'était le groupe n ° 1 qui correspondait:

MatchResult match = scanner.match(); 
if (match.start(1) != -1) { 
    // keep searching 
} 

Mais encore une fois, comme générale solution est trop fragile, pour les raisons que j'ai citées plus haut. Vous ne devez utiliser qu'une seule de ces solutions (ou toute solution regex) si vous êtes sûr que c'est compatible avec les pages particulières sur lesquelles vous travaillez.