Giava:Ho una grande stringa di codice HTML e devo estrarre il testo href="...".
-
13-09-2019 - |
Domanda
Ho questa stringa contenente una grossa porzione di codice HTML e sto cercando di estrarre il collegamento dalla porzione href="..." della stringa.L'href potrebbe essere in una delle seguenti forme:
<a href="..." />
<a class="..." href="..." />
Non ho davvero problemi con le espressioni regolari, ma per qualche motivo quando utilizzo il seguente codice:
String innerHTML = getHTML();
Pattern p = Pattern.compile("href=\"(.*)\"", Pattern.DOTALL);
Matcher m = p.matcher(innerHTML);
if (m.find()) {
// Get all groups for this match
for (int i=0; i<=m.groupCount(); i++) {
String groupStr = m.group(i);
System.out.println(groupStr);
}
}
Qualcuno può dirmi cosa c'è che non va nel mio codice?Ho fatto queste cose in php ma in Java in qualche modo sto facendo qualcosa di sbagliato...Quello che succede è che stampa l'intera stringa html ogni volta che provo a stamparla...
MODIFICARE:Solo in modo che tutti sappiano con che tipo di stringa ho a che fare:
<a class="Wrap" href="item.php?id=43241"><input type="button">
<span class="chevron"></span>
</a>
<div class="menu"></div>
Ogni volta che eseguo il codice, stampa l'intera stringa...Questo è il problema...
E riguardo all'utilizzo di jTidy...Ci sto lavorando ma sarebbe interessante sapere cosa è andato storto anche in questo caso...
Soluzione
.*
Questa è un'operazione avido che avrà carattere comprese le virgolette.
Prova qualcosa di simile:
"href=\"([^\"]*)\""
Altri suggerimenti
Ci sono due problemi con il codice che hai postato:
In primo luogo il .*
nella vostra espressione regolare è avido. Questo farà sì che per abbinare tutti i caratteri fino a quando l'ultimo carattere "
che può essere trovato. È possibile effettuare questa partita non sia avido modificando questo .*?
.
In secondo luogo, per raccogliere tutte le partite, è necessario mantenere l'iterazione con Matcher.find
, piuttosto che alla ricerca di gruppi. Gruppi consentono di accedere ad ogni sezione tra parentesi della regex. È tuttavia, sta cercando ogni volta l'intera espressione regolare corrisponde.
Mettendo insieme questi si dà la seguente codice che dovrebbe fare quello che ti serve:
Pattern p = Pattern.compile("href=\"(.*?)\"", Pattern.DOTALL);
Matcher m = p.matcher(innerHTML);
while (m.find())
{
System.out.println(m.group(1));
}
Regex è grande, ma non è lo strumento giusto per questo scopo particolare. Normalmente si desidera utilizzare un parser stackbased per questo. Date un'occhiata a Java API HTML parser di come jTidy .
Utilizza un parser integrato.Qualcosa di simile a:
EditorKit kit = new HTMLEditorKit();
HTMLDocument doc = (HTMLDocument)kit.createDefaultDocument();
doc.putProperty("IgnoreCharsetDirective", Boolean.TRUE);
kit.read(reader, doc, 0);
HTMLDocument.Iterator it = doc.getIterator(HTML.Tag.A);
while (it.isValid())
{
SimpleAttributeSet s = (SimpleAttributeSet)it.getAttributes();
String href = (String)s.getAttribute(HTML.Attribute.HREF);
System.out.println( href );
it.next();
}
Oppure usa ParserCallback:
import java.io.*;
import java.net.*;
import javax.swing.text.*;
import javax.swing.text.html.parser.*;
import javax.swing.text.html.*;
public class ParserCallbackText extends HTMLEditorKit.ParserCallback
{
public void handleStartTag(HTML.Tag tag, MutableAttributeSet a, int pos)
{
if (tag.equals(HTML.Tag.A))
{
String href = (String)a.getAttribute(HTML.Attribute.HREF);
System.out.println(href);
}
}
public static void main(String[] args)
throws Exception
{
Reader reader = getReader(args[0]);
ParserCallbackText parser = new ParserCallbackText();
new ParserDelegator().parse(reader, parser, true);
}
static Reader getReader(String uri)
throws IOException
{
// Retrieve from Internet.
if (uri.startsWith("http:"))
{
URLConnection conn = new URL(uri).openConnection();
return new InputStreamReader(conn.getInputStream());
}
// Retrieve from file.
else
{
return new FileReader(uri);
}
}
}
Il Reader potrebbe essere uno StringReader.
Un altro modo semplice e affidabile per farlo è quello di utilizzare Jsoup
Document doc = Jsoup.connect("http://example.com/").get();
Elements links = doc.select("a[href]");
for (Element link : links){
System.out.println(link.attr("abs:href"));
}
è possibile utilizzare una libreria html parser. jtidy ad esempio, si dà un modello DOM del HTML, dal quale è possibile estrarre tutti elementi "a" e leggere la loro attributo "href"
"href=\"(.*?)\""
dovrebbe anche funzionare, ma penso che la risposta di Kugel funzionerà più velocemente.