2012-05-03 9 views
5

Sto studiando la possibilità di eseguire il porting della libreria Python Beautiful Soup su .NET. Principalmente, perché mi piace molto il parser e non ci sono buoni parser HTML sul framework .NET (Html ​​Agility Pack è obsoleto, buggato, non documentato e non funziona bene a meno che non sia noto lo schema esatto.)Porting di una libreria molto Pythonesque su .NET

Uno di il mio obiettivo principale è ottenere la funzionalità di selezione DOM di base per mettere realmente in parallelo la bellezza e la semplicità di BeautifulSoup, consentendo agli sviluppatori di creare facilmente espressioni per trovare gli elementi che stanno cercando.

BeautifulSoup sfrutta i parametri loose-binding e named per farlo accadere. Ad esempio, per trovare tutti a tag, con un id della test e un title che contiene la parola foo, avrei potuto fare:

soup.find_all('a', id='test', title=re.compile('foo')) 

Tuttavia, C# non ha un concetto di un certo numero arbitrario di nome elementi. .NET4 Runtime ha definito i parametri, tuttavia devono corrispondere a un prototipo di metodo esistente.

La mia domanda: Qual è lo schema di progettazione C# che più somiglia a questo costrutto Pythonic?

Alcune idee:

mi piacerebbe andare dopo questo in base a come io, come sviluppatore, vorrei codice. L'implementazione di questo è fuori dallo scopo di questo post. Un'idea che ho sarebbe di usare tipi anonimi. Qualcosa di simile:

soup.FindAll("a", new { Id = "Test", Title = new Regex("foo") }); 

Anche se questa sintassi corrisponde vagamente l'implementazione di Python, ha ancora alcuni svantaggi.

  1. L'implementazione FindAll dovrebbe utilizzare la reflection per analizzare il tipo anonimo e gestire qualsiasi metadata arbitrario in modo ragionevole.
  2. Il prototipo FindAll dovrebbe prendere uno Object, il che rende poco chiaro come utilizzare il metodo a meno che non si abbia familiarità con il comportamento documentato. Non credo che ci sia un modo per dichiarare un metodo che deve prendere un tipo anonimo.

Un'altra idea che ho avuto è forse un modo più .NET di gestire questo, ma si allontana ulteriormente dalle radici Python della libreria. Quello sarebbe usare un modello fluido. Qualcosa di simile:

soup.FindAll("a") 
    .Attr("id", "Test") 
    .Attr("title", new Regex("foo")); 

Ciò richiederebbe la costruzione di un albero di espressioni e l'individuazione dei nodi appropriati nel DOM.

La terza e ultima idea che ho sarebbe di utilizzare LINQ. Qualcosa di simile:

var nodes = (from n in soup 
      where n.Tag == "a" && 
      n["id"] == "Test" && 
      Regex.Match(n["title"], "foo").Success 
      select n); 

Apprezzerei tutto comprensione da chiunque con esperienza porting di codice Python per C#, o semplicemente raccomandazioni generali sul modo migliore di gestire questa situazione.

+7

Per quanto ami Python, mira sempre al pubblico che lo utilizzerà. Se lo stai scrivendo per .NET, fallo nello stile che usano. Guarda le librerie .NET esistenti e vedi quali sono le pratiche (o aspetti che qualcuno ti dica qui) e le usi - non provare ad abbinare la versione di Python, non stai usando Python. –

+0

sono d'accordo con Lattyware. Se si desidera utilizzare BeautifulSoup da C#, non è possibile eseguirlo tramite IronPyhon? – mata

+0

Non è questo per XPath? –

risposta

1

Hai provato a eseguire il codice all'interno del motore IronPython. Per quanto ne so funziona molto bene e non devi toccare il tuo codice Python.

+1

Questa è una grande idea, tuttavia mi piacerebbe vedere un esempio di come sarebbe in C# per chiamare in un metodo implementato da Python con parametri denominati. IronPython fornisce una storia di interoperabilità per questo scenario? Inoltre, facendo questo indirizza questa domanda a "Come faccio ad usare una libreria Python in .NET?" che non è proprio quello che stavo chiedendo. –

Problemi correlati