attrs python html parser
Transkrypt
attrs python html parser
ASDL: wyciąganie literatury budowa serwisu Kamil Herba Juliusz Sompolski 2 marca 2009 Co trzeba zrobić? Wybrać język i narzędzia programowania. Wymyślić jak rozpoznawać które elementy stron na Ważniaku są literaturą, prawidłowo wyciągać co jest tytułem, co autorem etc. Zapewnić jakieś zaplecze do przechowywania i prezentowania tych informacji, zbudować serwis WWW Jaki język programowania? Python! ● „Batteries included” Python Do Pythona istnieje dużo bibliotek do szybkiej i sprawnej realizacji potrzebnych nam funkcjonalności: Wysyłanie żądań do stron WWW i otrzymywanie odpowiedzi – urllib, httplib Obrabianie tych stron np. wyrażeniami regularnymi aby wyciągnąć z nich interesujące nas dane – re, sgmllib Prezentacja tych danych użytkownikowi w postaci własnego serwisu WWW – framework django Requestowanie stron WWW urllib – biblioteka obsługująca wiele popularnych protokołów bardzo prosty odczyt danych ze stron obsługa skryptów cgi obsługa https httplib – druga biblioteka nieco bardziej niskopoziomowa urllib do obsługi http korzysta z niej Przykłady urllib – funkcja odczytująca kod strony o podanym adresie def getWebPage(urlString): handle = urllib.urlopen(urlString) return handle.read() httplib – podobna funkcja: def getWebPage2(urlString): url = urlparse(urlString) conn = httplib.HTTPConnection(url.hostname) conn.request("GET", urlString) r = conn.getresponse() return r.read() Ciekawy formularz z Buw <h2>Wyszukiwanie przez słowa w opisach</h2> <table> <tr><td> </td><td>Wpisz termin wyszukiwawczy:</td><td>Wybierz kategorię:</td></tr> <tr> <td> </td> <td><input tabindex="0" name="t1" size="16" maxlength="40" > </td> <td><select name="u1"> <option value="4" >Tytuł</option> <option value="1003" >Autor</option> <option value="12210" >Hasło przedmiotowe pol.</option> <option value="12211" >Hasło przedmiotowe ang.</option> <option value="7" >ISBN</option> <option value="8" >ISSN</option> <option value="1035" >Wszystko</option> </select> </td> urllib – formularze POST Funkcja szukająca danej książki w BUW: def findTitleInBuwList(title): params = urllib.urlencode({'t1': title, 'u1': '4', 'submittheform': 'Search', "beginsrch" : "1", "function" : "INITREQ"}) f = urllib.urlopen("https://opac.buw.uw.edu.pl/cgi bin/gw_46_6/chameleon", params) return f.read() praktyczne użycie - FindBookInBuw.py Przedmioty na Ważniaku Zebrane w postaci linków na głównej stronie, w sekcjach zatytułowanych „Pierwszy stopień” oraz „Drugi stopień”. Nietrudno powinno być z tego wyciągnąć listę przedmiotów na Ważniaku, a literaturę przyporządkowywać do przedmiotów na stronach których została znaleziona. Aby obejść strony wykładu trzeba tylko chodzić po odpowiednich linkach. Literatura na Ważniaku W większości zebrana w sekcji „Literatura” na głównej stronie danego wykładu, czasem też głębiej na stronach poszczególnych wykładów. Zebrana w postaci listy wypunktowanej lub wynumerowanej – co może ułatwić wyciąganie poszczególnych elementów literatury Często jednak dodatkowe „śmieci”, takie jak podział sekcji literatura na podsekcje, komentarze do literatury. Najprostszy przypadek Podział na podsekcje Dodatkowy tekst W kodzie... <div class="editsection" style="float:right;margin-left:5px;">[<a href="/index.php? title=Metody_numeryczne&action=edit&section=7" title="Edit section: Literatura">Edytuj</a>]</div><a name="Literatura"></a><h3> Literatura </h3> <ul><li> D. Kincaid, W. Cheney, <cite>Analiza numeryczna</cite>, Wydawnictwa NaukowoTechniczne, Warszawa 2006. <a href="/index.php? title=Specjalna:Booksources&isbn=832043078X" class="internal">ISBN 83-204-3078X</a> </li><li> A. Björck, G. Dahlquist, <cite>Metody numeryczne</cite>, Państwowe Wydawnictwo Naukowe, Warszawa 1987. <a href="/index.php? title=Specjalna:Booksources&isbn=8301042761" class="internal">ISBN 83-01-04276-1</a> </li></ul> <div class="editsection" style="float:right;margin-left:5px;">[<a href="/index.php? title=Metody_numeryczne&action=edit&section=8" title="Edit section: Moduły">Edytuj</a>]</div><a name="Modu.C5.82y"></a><h2> Moduły </h2> W kodzie... <div class="editsection" style="float:right;margin-left:5px;">[<a href="/index.php? title=MN04&action=edit&section=7" title="Edit section: Literatura">Edytuj</a>]</div><a name="Literatura"></a><h2>Literatura</h2> <p>W celu dogłębnego zapoznania się z omawianym na wykładzie materiałem, przeczytaj <b>rozdział 2.3</b> w </p> <ul><li> D. Kincaid, W. Cheney <cite>Analiza numeryczna</cite>, Wydawnictwa Naukowo-Techniczne, Warszawa 2006, <a href="/index.php?title=Specjalna:Booksources&isbn=832043078X" class="internal">ISBN 83-204-3078-X</a>. </li></ul> <p>Warto także przejrzeć rozdział 2 w </p> <ul><li> <span style="font-variant:small-caps">P. Deulfhard, A. Hohmann</span>, <cite>Numerical Analysis in Modern Scientific Computing</cite>, Springer, 2003, </li></ul> <p>omawiający zagadnienia uwarunkowania i numerycznej poprawności algorytmów. Nieocenioną monografią na ten temat jest </p> <ul><li> <span style="font-variant:small-caps">N. Higham</span>, <cite>Accuracy and Stability of Numerical Algorithms</cite>, SIAM, 2002. </li></ul> <!-- Saved in parser cache with key osilek1:pcache:idhash:12611-0!0!0!0!!pl!2 and timestamp 20090227155421 --> <div class="printfooter"> W kodzie... <div class="editsection" style="float:right;margin-left:5px;">[<a href="/index.php? title=Bazy_danych&action=edit&section=7" title="Edit section: Literatura">Edytuj</a>]</div><a name="Literatura"></a><h3> Literatura </h3> <ul><li> <b>Wykłady</b>: <ul><li> Date C. J., An Introduction to Database System, vol. II, Adison-Wesley Pub. Comp., również WNT – W-wa, (seria: Klasyka Informatyki), 2000 </li>(...)</ul> </li><li><b>Laboratoria</b>: <ul><li> M. Szeliga: ABC języka SQL. HELION. </li>(...)</ul> </li></ul> <div class="editsection" style="float:right;margin-left:5px;">[<a href="/index.php? title=Bazy_danych&action=edit&section=8" title="Edit section: Moduły">Edytuj</a>]</div><a name="Modu.C5.82y"></a><h2> Moduły </h2> Od strony technicznej biblioteka sgmlib – parser html odczytywanie linków do przedmiotów znajdowanie listy literatury Rozpoznawanie listy literatury na podstawie tagów html. Zwracanie wpisów literatury w całości, bez podziału na autora, tytuł etc. Inne możliwości Inne biblioteki – htmllib, HTMLParser – o podobnej funkcjonalności, trochę innym interfejsie sgmlib - przykład from sgmllib import SGMLParser class LiteratureLister(SGMLParser): def reset(self): SGMLParser.reset(self) self.list = [] self.literatureSection = False self.literatureElement = False def start_a(self, attrs): for t in attrs: if t == ('name', 'Literatura'): self.literatureSection = True def start_div(self, attrs): self.literatureSection = False def start_li(self, attrs): if(self.literatureSection): self.literatureElement = True self.elementBuffer = '' def end_li(self): if(self.literatureElement): if(self.elementBuffer.endswith("\n")): self.elementBuffer = self.elementBuffer.replace("\n","") self.list.append(self.elementBuffer) self.literatureElement = False def handle_data(self, text): if(self.literatureElement): self.elementBuffer += text Literatura na Ważniaku Poszczególne wpisy różniące się diametralnie formatem Czasem „autor, tytuł”, czasem „tytuł, autor”, Autorzy czasem z pełnym imieniem, czasem z inicjałem, Poszczególne elementy wpisu zazwyczaj oddzielone przecinkami, ale bywa np. „autor: tytuł”, Rzadko takie dane jak ISBN Przykłady wpisów B. Kernighan, D. Ritchie, Język ANSI C, Wydawnictwa Naukowo-Techniczne, Warszawa 2004. Adams Andrew A., McCrindle Rachel, Pandora's Box: Social and Professional Issues of the Information Age, John Wiley & Sons Ltd, Chichester, 2008. Marwedel P., Embedded System Design, Kluwer Academic Publishers, Boston 2003, ISBN 1-4020-7690-8 M. Szeliga: ABC języka SQL. HELION. Materiały firmowe - dokumenty techniczne dostępne w sieci WWW - MIPS, Intel, AMD Wprowadzenie do algorytmów, Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, Clifford Stein, Wydawnictwa Naukowo - Techniczne, 2004. Od strony technicznej re – moduł do obsługi wyrażeń regularnych analiza danych z listy literatury – co jest książką, co autorem, co rokiem i numerem wydania, etc. analiza danych ze stron księgarni internetowych (wyszukiwanie wyrażeń typu nakład wyczerpany, cena, pozycja dostępna, etc.) Wyrażenia regularne... Jeszcze tego nie zrobiliśmy :-) Powinno się jednak dać. Budowa serwisu Framework django Pośredniczy w komunikacji z bazą danych przez obiektowy interfejs, nie wymagający pisania z palca SQLi Obsługuje wygląd stron poprzez prosty język template'ów Oddziela go od logiki poprzez pisanie widoków. Django - początek jullass@hermes:~/proj/algint$ django-admin.py startproject asdl jullass@hermes:~/proj/algint/asdl$ ls __init__.py manage.py settings.py urls.py jullass@hermes:~/proj/algint/asdl$ django-admin.py startapp getliterature jullass@hermes:~/proj/algint/asdl/getliterature$ ls __init__.py models.py views.py settings.py – ustawienia projektu models.py – modele bazy danych views.py – widoki urls.py – powiązania widoków z adresami Templates reklamodawca.html: <html><head> <title>Wylistuj literaturę</title> <meta httpequiv=ContentType content="text/html; charset=UTF8"> </head><body> <h1>Wylistuj literaturę</h1> <form action="." method="POST"> {{ form.as_p }} <p><input type="submit" value="Wyślij"></p> </form> <hr> {% if error %} <p>Nie udało się otworzyć strony {{ url }}.</p> {% else %}{% if results %} {% if books %} <p>Elementy literatury znalezione na stronie {{ url }}:</p> <ul> {% for book in books %} <li>{{ book }}</li> {% endfor %} </ul> {% else %} <p>Na stronie {{ url }} nie znaleziono żadnych elementów literatury.</p> {% endif %}{% endif %}{% endif %} </body></html> Views views.py: from django import forms from getwebpage import getWebPage from literaturelister import LiteratureLister from django.shortcuts import render_to_response class LiteratureForm(forms.Form): url = forms.URLField(label='Podaj URL:', widget=forms.TextInput(attrs={'size':'100'})) def getLiterature(request): context = {} if request.method == 'POST': form = LiteratureForm(request.POST) if form.is_valid(): context["url"] = form.cleaned_data['url'] try: data = getWebPage(form.cleaned_data['url']) lister = LiteratureLister() lister.feed(data) context["results"] = True context["books"] = lister.list except IOError: context["error"] = True else: form = LiteratureForm() context["form"] = form return render_to_response('literature.html', context) Modele models.py: from django.db import models class Book(models.Model): title = models.CharField(maxlength=1024) author = models.CharField(maxlength=1024) # etc... def __str__(self): return str(self.author)+', '+str(self.title) settings.py: DATABASE_ENGINE = 'sqlite3' DATABASE_NAME = 'db' Shell: jullass@hermes:~/proj/algint/asdl$ ./manage.py syncdb (...) Creating table getliterature_book Modele Python: >>> from asdl.getliterature.models import * >>> b = Book(title='Wprowadzenie do algorytmow', author='T. Cormen') >>> b.save() >>> c = Book(title='Thinking in Java', author='Bruce Eckel') >>> c.save() >>> d = Book(title='Wprowadzenie do blabla', author='Foobar') >>> d.save() >>> Book.objects.all() [<Book: T. Cormen, Wprowadzenie do algorytmow>, <Book: Bruce Eckel, Thinking in Java>, <Book: Foobar, Wprowadzenie do blabla>] >>> Book.objects.filter(title__startswith="Wprowadzenie") [<Book: T. Cormen, Wprowadzenie do algorytmow>, <Book: Foobar, Wprowadzenie do blabla>] Podłączenie tego urls.py: urlpatterns = patterns('', (r'^$', 'asdl.getliterature.views.getLiterature'), ) No i odpalić... jullass@hermes:~/proj/algint/asdl$ ./manage.py runserver Ta-dam!