Strona używa cookies (ciasteczek). Dowiedz się więcej o celu ich używania i zmianach ustawień. Korzystając ze strony wyrażasz zgodę na używanie cookies, zgodnie z aktualnymi ustawieniami przeglądarki.    X

Wyciąganie danych ze stron - lxml

Nie raz zdarza się nam że potrzebujemy jakiś danych z jakiś stron. Co jednak gdy na stronie jest dużo różnych elementów nam całkowicie niepotrzebnych lub potrzebujemy pobrać z wielu podstron ? Z pomocą przychodzi nam biblioteka lxml

1. lmxl - Co to takiego?

Jest to biblioteka dla języka Python która pozwala nam przetwarzać dane z plików XML i HTML. Można znaleźć ją w standardowych repozytoriach dystrybucji z rodziny Linux lub pobrać z strony projektu

2. Jak zacząć zabawę?

Pierwszym krokiem trzeba będzie zaimportować do naszego skryptu tą bibliotekę a robimy to następująco

import lxml.html

Teraz pozostaje nam wybrać źródło którym mogą być strony na dysku bądź gdzieś zdalnej lokacji korzystając np z biblioteki urllib2 lub podobnej

3. Co dalej?

Aby można było przetwarzać dane za pomocą lxml trzeba sprowadzić je do postaci stringa a następnie użyć:

szkielet = lxml.html.fromstring(dane).

Gdzie zmienna "dane" oznaczają nazwę zmiennej przechowującą surową strukturę pliku

Dla przykładu teraz jeśli chcemy pobrać nazwy i linki z wszystkich tagów <a> na portalu

for element in szkielet.cssselect('a'): print element.text # Zwraca zawartość każdego tagu print element.attrib['href'] # zwraca atrybut każdego tagu gdzie w nawiasach musi być nazwa tego atrybutu

ale co jeśli chcemy pobrać tylko jeden?

Wtedy stosujemy zamiast pętli takie coś: element = szkielet.cssselect('a')[0] print element.text print element.attrib['href']

4. Wyciąganie elementów z rozbudowanych struktur

W poprzednich akapitach mogliście zobaczyć jak się pobiera wszystkie linki ze strony. Co jeśli jednak potrzebujemy tylko tego konkretnego ?

Na warsztat weźmiemy taki fragment pliku HTML:

<div> <span> jakiś tekst</span> <a href=http://dobreprogramy.pl>Nasz portal</a> </div> <div> <span> jakiś tekst</span> <div id='zly'> <a href=http://zleprogramy.pl>Konkurencyjny portal</a> </div> </div>

Naszym zadaniem jest pobranie linki z tagu "div" z identyfikatorem "zly"

element = szkielet.cssselect('div#zly a')[0] print element.attrib['href']

Tu wprowadzamy w cssselect "div#zly" gdyż zły jest identyfikatorem ale jeśli w miejsce id było by class wtedy stosujemy "div.zly

Pamiętajmy aby ostrożnie stosować poruszanie się po dynamicznych stronach gdyż bez zabezpieczonego skryptu przed wykryciem wyjątku w razie braku jakiegokolwiek tagu może dojść do awarii skryptu a co za tym idzie nieprawidłowego działania i wprowadzenia danych

5. Wyciąganie tytułów wpisów z blogu

import urllib2 import lxml.html dane = urllib2.urlopen('http://www.dobreprogramy.pl/sylwek3100').read() #pobieramy dane z mojego bloga szkielet = lxml.html.fromstring(dane) #ładujemy je do szkieletu for artykul in szkielet.cssselect('article'): #inicjujemy pętle pobierającą wszystkie tagi <article> tytul = artykul.cssselect('header a')[0] #wyciągamy linka z wewnątrz tagu <header> print tytul.text #wyswietlamy zawartość linka

Dziękuje wszystkim za uwagę.  

programowanie

Komentarze

0 nowych
wojtex   10 #1 25.11.2012 15:11

Na pewno się tym zainteresuję, ale do manipulowania danymi ze stron używam BASH-a. Możliwości jakie daje nam grep, sed, awk, cut, tr i tak dalej są chyba nieograniczone :-)

Pozdro.

sylwek3100   3 #2 25.11.2012 15:15

@TuskVN Tak ale jeśli chcesz robić baze np sqlite z jakimiś danymi to bash odpada bo to by było rozwiązanie nieergonomiczne albo gdy musimy to na jakiś inny np binarny format przetworzyć. Poza tym do większej ilość różnych złożonych danych bash się nie nadaje

Kintoki   6 #3 25.11.2012 15:27

Jakie są zalety/wady/różnice w stosunku do np BeautifulSoup

sylwek3100   3 #4 25.11.2012 15:30

@Kintoki Szybsze jest (bo to jest natywna), ponoć potrafi nawet z uszkodzonych stron (np niedomkniętych tagów) pobierać dane a np BeautifulSoup się przy tym krzaczy

Autor edytował komentarz.
bachus   20 #5 25.11.2012 15:31

@Kintoki: nie jestem programistą, ale między innymi wdrażam systemy monitoringu. Z tego, co widzę od programistów, BeautifulSoup w stosunku do lmxl jest koszmarnie wolny.

mikolaj_s   14 #6 25.11.2012 15:41

Całkiem fajna biblioteka. Osobiście korzystam najczęściej ze Scali, która ma wbudowaną obsługę XML i pracuje się bardzo wygodnie, ale jakbym musiał pisać coś w Pythonie to może być fajna możliwość.
Zastanawiam się czy nie dałoby się wykorzystać tej biblioteki żeby zrobić framework webowy w Pythonie, który zamiast umieszczać kod w tagach przetwarzałby HTML z plików (coś jak w Lift)

kwpolska   6 #7 25.11.2012 18:18

Plus http://python-requests.org/ dla zdrowia psychicznego.
@bachus: http://www.crummy.com/software/BeautifulSoup/bs4/doc/#installing-a-parser i masz lxml z ładniejszym API.

Demagog   4 #8 25.11.2012 19:45

BeautifulSoap jest wolny to fakt, ale podobna lepiej przerabia html nawet ten uszkodzony.

@TuskVN Chyba ktoś zapomniał ci powiedzieć, że regexpy nie są dobrą rzeczą przy parsowaniu htmla.
Są lepsze rzeczy. A co do Pythona jest niezły pyquery.

LordRuthwen   6 #9 26.11.2012 09:30

O widzisz, przyda się bo akurat muszę parser stron napisać :)

LamConcept   5 #10 26.11.2012 12:00

Czy istnieje możliwość łatwego pobierania zawartości archiwum stron google? Tak aby wszystkie podstrony były zachowane i zapisane?

sylwek3100   3 #11 26.11.2012 14:55

@LamConcept Google nie zapisuje i nie indeksuje w wielu wypadach wszystkich podstron wiec nie wiem czy to jest możliwe

iluzion   5 #12 27.11.2012 07:36

@mikolaj_s

W bibliotece standardowej Pythona też masz wbudowane moduły do obsługi XML, np. xml.etree:

http://docs.python.org/3.3/library/xml.etree.elementtree.html