Wyłuskiwanie danych z kodu HTML w Pythonie

0

Witam,

dzięki pomocy Shaloma udało mi się w końcu zaimportować potrzebne moduły.

Mam na celu stworzyć program, który automatycznie wyciągnie mi wybrane dane ze strony gratka.pl.

Udało mi się stworzyć skrypt, który pobiera kod HTML podanej w skrypcie strony, wyciąga z niego wszystkie URLe i zapisuje je w podanym pliku:

from bs4 import BeautifulSoup
import urllib2
import re

redditFile = urllib2.urlopen("http://www.gratka.pl/ogloszenia/nieruchomosci/dzialki/lista.html?typ=1")
redditHtml = redditFile.read()
redditFile.close()

path = r"C:\Users\Magda\Desktop\zrodlo.txt"
file = open(path, "w")

soup = BeautifulSoup(redditHtml)
for link in soup.find_all('a'):
    print(link.get("href"))
    file.write(str(link) + "\n")
        
file.close()

Niestety nie wiem jak wyciągnać z kodu dane, które mnie interesują - m.in. powierzchnia działki, cena, ulica itp.
(poniżej fragment kodu)

      </h2>
      <div class="infoLista">
                            <p class="infoDane">
                        <span><b>2000</b> m<sup>2</sup></span>                        <span><b>600</b> PLN/m<sup>2</sup></span>          </p>
                    <p class="infoZajawka">Przepiękna działka w prestiżowej części Podkowy Leśnej. 
Starodrzew na działce. Na działce znajduje się drewniany domek 80m2 
Wszystkie media.

Zachęcam do oglądania ul. Sienkiewicza 6 
Podkowa Leśna

Ogłoszenie bezpośrednie!</p>
                <p class="infoLokalizacja">
            <b>Podkowa Leśna</b>, ul. Sienkiewicza        </p>
        <p class="infoDodatkowe">
                    <span>Dodano: 30-10-2013</span>
          <span>Zaktualizowano: 22-08-2014</span>        </p>
      </div>
                      <p class="ogloszenieCena"><b>1 200 000</b> PLN</p>
              <span data-klucz="dom-ogloszenie-35047246" title="Dodaj do ulubionych ogłoszeń."
                    class="schowekDodaj">
          Dodaj do ulubionych
        </span>

Czy ktoś ma pomysł jak dostać się do tych danych?

Pozdrawiam.

dodanie znacznika <code class="html"> - furious programming

1

Powierzchni to nawet ja tam nie widzę :P Co do reszty to masz przecież class na elementach htmla. Musisz po prostu wyciągnąć dane z tagów z interesującymi cię klasami.

2

Magik w pythonie nie jestem ale po tym kodzie to może być proste jak drut

powice = soup.findAll("p", { "class" : "infoDane" })

Da Ci powierzchnie w pierwszym spanie i cene za m2 w drgim spanie.

powice = soup.findAll("p", { "class" : "ogloszenieCena" })

Da Ci cenę pełną ogłoszenia

powice = soup.findAll("p", { "class" : "infoLokalizacja" })

Da Ci lokalizacje.

0

Dziękuję za wskazówki, już jestem bardzo blisko celu :)

Kod, który podałeś:

powice = soup.findAll("p", { "class" : "infoDane" })

wyświetla wszystkie powierzchnie i cenę za m2, jednak wśród wielu niepotrzebnych tagów, przykład:

<span><b>2330</b> m<sup>2</sup></span> <span><b>773</b> PLN/m<sup>2</sup></span> </p>, <p class="infoDane">

I ja to tak rozumiem, że teraz aby wyłuskać same liczby, to muszę napisać kod, który z tego rezultatu powice pobierze dane z tagów span i b?

Muszę popróbować i pomyśleć.

0

Ok, po przeczytaniu dokumentacji BeautifulSoup4 udało mi się wyłuskać w końcu, to co mnie interesuje :)

Kod:

from bs4 import BeautifulSoup
import urllib2
import re

redditFile = urllib2.urlopen("http://www.gratka.pl/ogloszenia/nieruchomosci/dzialki/lista.html?typ=1")
redditHtml = redditFile.read()
redditFile.close()

path = r"C:\Users\Magda\Desktop\nowyyy.txt"
file = open(path, "w")

soup = BeautifulSoup(redditHtml)
powice = soup.findAll("p", { "class" : "infoDane" })

for child in powice:
    print(child.b)
    file.write(str(child.b) + "\n")

file.close()

Jedyny problem jest taki, że wyniki zapisywane są z tagami b:

<b>1527</b>
<b>3800</b>
<b>9442</b>
<b>2752</b>
<b>2657</b>

Czy wie ktoś co dodać do kodu aby wyłuskać same dane bez tych tagów? Próbowałam na wiele sposobów i niestety nic z tego.

Pozdrawiam : )

1

Chyba z soup też byś wyciął bez b, ale jak coś to może dla uproszczenia regexp? nawet banalny w stylu '([0-9]*)'. Python ma łatne przetwarzanie tekstu więc pewnie z regexem nie było by problemu wyciągnąć.

1

Ja bym to zrobił tak:

for child in powice:
    formatted_child = str(child.b)[3:-4]
    print(formatted_child)
    file.write(formatted_child + "\n")

Ale pewnie można lepiej, no i będziesz miała lipę jak będzie np <strong> zamiast <b> :) [3:-4] oznacza wycięcie od 4 znaku (liczymy od zera) do 4 od końca (tutaj nie liczymy od zera, bo pierwszą ujemną liczbą jest -1).

0

Co do pomysłu Wizzie:

ten sposób chyba nie przejdzie, bo akurat podałam przykłady czterocyfrowych liczb, ale ilość cyfr nie zawsze jest równa 4. No chyba, że jest jakiś sposób by wyciąć łańcuch bez n ostatnich znaków.

No chyba, że zastosuję funkcję len liczącą ilość znaków i jakoś z *if *pokombinuję :)

1

Nie nie, to co ja podałem ucina pierwsze 3 i ostatnie 4 znaki, czyli u ciebie odpowiednio: <b> oraz </b></code>. Tylko jak wspomniałem, działa tylko dla takiego przypadku. Jeśli wyjście zawsze będzie w takiej formie, czyli liczby w tagu <code><b></b>, to będzie działać.

0

No tak, faktycznie, właśnie zauważyłam :) Zaraz wyprobuję :]

0

Ok, cel osiągnięty, dziękuję wszystkim za pomocne wskazówki ! :)

Na koniec wklejam cały kod, być może w przyszłości komuś się przyda:

from bs4 import BeautifulSoup
import urllib2
import re

redditFile = urllib2.urlopen("http://www.gratka.pl/ogloszenia/nieruchomosci/dzialki/lista.html?typ=1")
redditHtml = redditFile.read()
redditFile.close()

path = r"C:\Users\Magda\Desktop\nowyyy.txt"
file = open(path, "w")

soup = BeautifulSoup(redditHtml)
powice = soup.findAll("p", { "class" : "infoDane" })

for child in powice:
    formatted_child = str(child.b)[3:-4]
    print(formatted_child)
    file.write(formatted_child + "\n")

file.close()

Pozdrawiam :)

2

Jeszcze dobra praktyka. Taki kod:

file = open(path, "w")
file.write("foobar")
file.close()

Możesz zastąpić:

with open(path, "w") as file:
    file.write("foobar")

Taka konstrukcja automatycznie zamyka plik. Co do "w", to musisz pamiętać, że ta flaga automatycznie czyści plik, jeśli istnieje.

1 użytkowników online, w tym zalogowanych: 0, gości: 1