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>&nbsp;</td><td>Wpisz termin wyszukiwawczy:</td><td>Wybierz
kategorię:</td></tr>
<tr>
<td>&nbsp;</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&amp;action=edit&amp;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&amp;isbn=832043078X" class="internal">ISBN 83-204-3078X</a>
</li><li> A. Bj&ouml;rck, G. Dahlquist, <cite>Metody numeryczne</cite>, Państwowe
Wydawnictwo Naukowe, Warszawa 1987. <a href="/index.php?
title=Specjalna:Booksources&amp;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&amp;action=edit&amp;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&amp;action=edit&amp;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&amp;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&amp;action=edit&amp;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&amp;action=edit&amp;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 http­equiv=Content­Type content="text/html; charset=UTF­8">
</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!

Podobne dokumenty