Data scraping - BeautifulSoup

Data scraping - BeautifulSoup
GR
  • Rejestracja:prawie 8 lat
  • Ostatnio:około 5 lat
  • Postów:14
0

Piszę przykładowy skrypt, który ze strony z ogłoszeniami nieruchomości będzie pobierał tytuł ogłoszenia, kategorię i cenę.

Potrafię pobrać tytuł i kategorię i zapisać jako jedną linię do pliku csv ale mam problem z ceną. W sekcji którą wybrałem jako pojedyncze ogłoszenie, nie pokazuje ceny pomimo, że jak wejdę w źródło strony wygląda, że ta cena tam jest. Poradzi ktoś jaką sekcję wybrać żebym miał w niej powyższe informacje? Lub co zrobić aby dopisać cenę do już zapisanych w pliku linii? Cenę potrafię pobrać osobnym kodem. Kod wraz z adresem do strony wklejam poniżej.

Kopiuj
from urllib.request import urlopen as uReq
from bs4 import BeautifulSoup as soup

my_url = 'https://www.morizon.pl/mieszkania/krakow/'
uClient = uReq(my_url)
page_html = uClient.read()
uClient.close()

'''html parsing'''
page_soup = soup(page_html, 'html.parser')

containers = page_soup.findAll('section', {'class': 'single-result__content single-result__content--height'})

file_name = 'scraping.csv'
f = open(file_name, 'w')
names = 'Location, Category, Price\n'
f.write(names)

for container in containers:
    '''grabs each title'''
    headers = container.findAll('h2', {'class': 'single-result__title'})
    header = headers[0].text.strip()

    '''grabs each category'''
    categories = container.findAll('p', {'class': 'single-result__category'})
    category = categories[0].text.strip()

    prices = page_soup.findAll('p', {'class': 'single-result__price'})
    price = prices[0].text

    f.write(header + ',' + category + ', ' + price + '\n')
KO
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 4 lata
  • Postów:146
0
Grzegooo napisał(a):

Piszę przykładowy skrypt, który ze strony z ogłoszeniami nieruchomości będzie pobierał tytuł ogłoszenia, kategorię i cenę.

Potrafię pobrać tytuł i kategorię i zapisać jako jedną linię do pliku csv ale mam problem z ceną. W sekcji którą wybrałem jako pojedyncze ogłoszenie, nie pokazuje ceny pomimo, że jak wejdę w źródło strony wygląda, że ta cena tam jest. Poradzi ktoś jaką sekcję wybrać żebym miał w niej powyższe informacje? Lub co zrobić aby dopisać cenę do już zapisanych w pliku linii? Cenę potrafię pobrać osobnym kodem. Kod wraz z adresem do strony wklejam poniżej.

Kopiuj
from urllib.request import urlopen as uReq
from bs4 import BeautifulSoup as soup

my_url = 'https://www.morizon.pl/mieszkania/krakow/'
uClient = uReq(my_url)
page_html = uClient.read()
uClient.close()

'''html parsing'''
page_soup = soup(page_html, 'html.parser')

containers = page_soup.findAll('section', {'class': 'single-result__content single-result__content--height'})

file_name = 'scraping.csv'
f = open(file_name, 'w')
names = 'Location, Category, Price\n'
f.write(names)

for container in containers:
    '''grabs each title'''
    headers = container.findAll('h2', {'class': 'single-result__title'})
    header = headers[0].text.strip()

    '''grabs each category'''
    categories = container.findAll('p', {'class': 'single-result__category'})
    category = categories[0].text.strip()

    prices = page_soup.findAll('p', {'class': 'single-result__price'})
    price = prices[0].text

    f.write(header + ',' + category + ', ' + price + '\n')

Może cena jest za javascriptem? Ewentualnie złęgo xpatha podałeś

GR
  • Rejestracja:prawie 8 lat
  • Ostatnio:około 5 lat
  • Postów:14
0

Ogólnie z java scriptem nie miałem nigdy nic wspólnego więc to jest całkiem możliwe. Łapcie wycinek kodu z tej strony. Mój container to jest właśnie section class = single-result... i jak dla mnie to ta cena jest dalej pod p class = single-result__price. Ale jak wyprintuje sobie ten container w pythonie to tej ceny już nie ma. Jest tytuł i kategoria.

Kopiuj
<section class="single-result__content single-result__content--height">
<header>
<meta itemprop="category" content="Mieszkanie na sprzedaż"/>
<a href="https://www.morizon.pl/oferta/sprzedaz-mieszkanie-krakow-debniki-63m2-mzn2026902513" title=""
class="property_link" itemprop="url">
<div class="row">
<div class="col-xs-8">
<h2 class="single-result__title">
Kraków, Dębniki </h2>
<p class="single-result__category" itemprop="name">
Mieszkanie na sprzedaż, dodane: 03-07-2018 </p>
</div>
<div class="col-xs-4">
<p class="single-result__price">296&nbsp;100&nbsp;zł</p><p class="single-result__price single-result__price--currency">4700 zł/m&#178;</p> <meta itemprop="price" content="296100.00">
<meta itemprop="priceCurrency" content="PLN">
</div>
</div>
</a>
</header>
<div class="info-description single-result__info">
<ul class="param list-unstyled list-inline">
<li><b>3</b> pokoje</li> <li><b>63</b> m²</li> <li><b>2017</b> rok</li> </ul>
</div>
<div class="description single-result__description" itemprop="description">
<p>Prestige City Osiedle zostało tak zaprojektowane by każdy mieszkaniec znalazł tu coś dla siebie. Wiemy że dla każdego człowieka ważne są inne aspekty życia, Jedni chcą prowadzić aktywny styl życia, inni nastawiają się na zdrowie. Część najbardziej ceni sobie bezpieczeństwo, a jeszcze inni mają bzika na punkcie technologii. My zaprojektowaliśmy WSZYSTKIE pożądane cechy osiedla mieszkaniowego w ramach jednego kompletnego projektu. TWORZĄC </p>
</div>
</section>
0

Pokaz co wypluje z samym price = prices[0] bez .text

V6
  • Rejestracja:około 7 lat
  • Ostatnio:ponad rok
  • Lokalizacja:<a href="https://megatool.pl">sklep</a>
  • Postów:49
0

Rozumiem, że w tej chwili masz coś takiego tylko bez ceny?

Kopiuj
Location, Category, Price 
Kraków, Dębniki,Mieszkanie na sprzedaż, dodane: 03-07-2018, 296 100 zł
Kraków, Prądnik Czerwony, ul. Reduta 26,Mieszkanie na sprzedaż, dodane: 02-07-2018, 296 100 zł
Kraków, Prądnik Czerwony, ul. Reduta 26,Mieszkanie na sprzedaż, dodane: 11-05-2018, 296 100 zł
.
.
.
Kraków, Bieżanów-Prokocim, ul. Braci Czeczów/ul. Opalowa Pokaż legendę,Mieszkanie na sprzedaż, dodane: 06-08-2018, 296 100 zł
Kraków, Bieżanów-Prokocim, ul. Braci Czeczów/ul. Opalowa Pokaż legendę,Mieszkanie na sprzedaż, dodane: 06-08-2018, 296 100 zł

.
.
.


edytowany 2x, ostatnio: vitz666
GR
  • Rejestracja:prawie 8 lat
  • Ostatnio:około 5 lat
  • Postów:14
0
Biały Szewc napisał(a):

Pokaz co wypluje z samym price = prices[0] bez .text

wyrzuca błąd "list index out of range"

GR
  • Rejestracja:prawie 8 lat
  • Ostatnio:około 5 lat
  • Postów:14
0
vitz666 napisał(a):

Rozumiem, że w tej chwili masz coś takiego tylko bez ceny?

Kopiuj
Location, Category, Price 
Kraków, Dębniki,Mieszkanie na sprzedaż, dodane: 03-07-2018, 296 100 zł
Kraków, Prądnik Czerwony, ul. Reduta 26,Mieszkanie na sprzedaż, dodane: 02-07-2018, 296 100 zł
Kraków, Prądnik Czerwony, ul. Reduta 26,Mieszkanie na sprzedaż, dodane: 11-05-2018, 296 100 zł
.
.
.
Kraków, Bieżanów-Prokocim, ul. Braci Czeczów/ul. Opalowa Pokaż legendę,Mieszkanie na sprzedaż, dodane: 06-08-2018, 296 100 zł
Kraków, Bieżanów-Prokocim, ul. Braci Czeczów/ul. Opalowa Pokaż legendę,Mieszkanie na sprzedaż, dodane: 06-08-2018, 296 100 zł

.
.
.

Dokładnie tak. To jest przykładowa linia mojego outputu

Kopiuj
Kraków, Podgórze, Krasickiego,Mieszkanie na sprzedaż, dodane: 21-09-2018
edytowany 1x, ostatnio: Grzegooo
V6
  • Rejestracja:około 7 lat
  • Ostatnio:ponad rok
  • Lokalizacja:<a href="https://megatool.pl">sklep</a>
  • Postów:49
0

Coś takiego mi działa i daje rezultat taki jak pisałem wyżej

Kopiuj
from urllib.request import urlopen as uReq
from bs4 import BeautifulSoup as soup
import io

my_url = 'https://www.morizon.pl/mieszkania/krakow/'
uClient = uReq(my_url)
page_html = uClient.read()
uClient.close()

'''html parsing'''
page_soup = soup(page_html, 'html.parser')

containers = page_soup.findAll('section', {'class': 'single-result__content single-result__content--height'})

file_name = 'scraping.txt'
with io.open(file_name,'w',encoding='utf8') as f:
    names = 'Location, Category, Price \n'
    f.write(names)

    for container in containers:
        '''grabs each title'''
        headers = container.findAll('h2', {'class': 'single-result__title'})
        header = headers[0].text.strip()

        '''grabs each category'''
        try:
            categories = container.findAll('p', {'class': 'single-result__category'})
            category = categories[0].text.strip()
        except:
            category = "no_category"

        prices = page_soup.findAll('p', {'class': 'single-result__price'})
        price = prices[0].text


        f.write(str(header) + ',' + str(category) + ', ' + str(price) +'\n' )


GR
  • Rejestracja:prawie 8 lat
  • Ostatnio:około 5 lat
  • Postów:14
0
vitz666 napisał(a):

Coś takiego mi działa i daje rezultat taki jak pisałem wyżej

Kopiuj
from urllib.request import urlopen as uReq
from bs4 import BeautifulSoup as soup
import io

my_url = 'https://www.morizon.pl/mieszkania/krakow/'
uClient = uReq(my_url)
page_html = uClient.read()
uClient.close()

'''html parsing'''
page_soup = soup(page_html, 'html.parser')

containers = page_soup.findAll('section', {'class': 'single-result__content single-result__content--height'})

file_name = 'scraping.txt'
with io.open(file_name,'w',encoding='utf8') as f:
    names = 'Location, Category, Price \n'
    f.write(names)

    for container in containers:
        '''grabs each title'''
        headers = container.findAll('h2', {'class': 'single-result__title'})
        header = headers[0].text.strip()

        '''grabs each category'''
        try:
            categories = container.findAll('p', {'class': 'single-result__category'})
            category = categories[0].text.strip()
        except:
            category = "no_category"

        prices = page_soup.findAll('p', {'class': 'single-result__price'})
        price = prices[0].text


        f.write(str(header) + ',' + str(category) + ', ' + str(price) +'\n' )

Tak, kod rzeczywiście działa, tylko do każdej linii podaje tą samą cenę. On po prostu wyszukuje wszystkie ceny na stronie i do każdej linii wrzuca pierwszą pozycję z listy.

Ciągle nie wiem czemu nie mogę rozpisać wyszukiwania ceny tak jak nagłówków i kategorii ;/

V6
  • Rejestracja:około 7 lat
  • Ostatnio:ponad rok
  • Lokalizacja:<a href="https://megatool.pl">sklep</a>
  • Postów:49
0

Faktycznie nie spojrzałem na to, że wszędzie cena jest ta samo


V6
  • Rejestracja:około 7 lat
  • Ostatnio:ponad rok
  • Lokalizacja:<a href="https://megatool.pl">sklep</a>
  • Postów:49
1

Teraz musi działać

Kopiuj
from urllib.request import urlopen as uReq
from bs4 import BeautifulSoup as soup
import io

my_url = 'https://www.morizon.pl/mieszkania/krakow/'
uClient = uReq(my_url)
page_html = uClient.read()
uClient.close()

'''html parsing'''
page_soup = soup(page_html, 'html.parser')

containers = page_soup.findAll('section', {'class': 'single-result__content single-result__content--height'})

file_name = 'scraping.txt'
with io.open(file_name,'w',encoding='utf8') as f:
    names = 'Location, Category, Price \n'
    f.write(names)

    for container in containers:
        '''grabs each title'''
        headers = container.findAll('h2', {'class': 'single-result__title'})
        header = headers[0].text.strip()

        '''grabs each category'''
        try:
            categories = container.findAll('p', {'class': 'single-result__category'})
            category = categories[0].text.strip()
        except:
            category = "no_category"

        try:
            prices = container.findAll('p', {'class': 'single-result__price'})
            price = prices[0].text.strip()
        except:
            price = "no_price"


        print(str(header) + ',' + str(category) + ', ' + str(price) +'\n' )


GR
  • Rejestracja:prawie 8 lat
  • Ostatnio:około 5 lat
  • Postów:14
0

@vitz666: Jesteś wielki! Działa jak należy. Dziękuje bardzo za pomoc! Zabieram się za analizę :)

V6
  • Rejestracja:około 7 lat
  • Ostatnio:ponad rok
  • Lokalizacja:<a href="https://megatool.pl">sklep</a>
  • Postów:49
0
  1. Sprawdź sobie jeszcze czy jak jest podana cena "od - do" to działa, bo sądze ze może nie działać i wpisywać "no_price".
  2. Reklama to też kontener i można go pewnie jakoś pominąć -> Chcesz wziąć kredyt i potrzebujesz porady?,Nowa oferta morizon.pl dla osób rozważających wzięcie kredytu., no_price
  3. Separator warto zmienić na inny np ";" zamiast przecinka, bo adresy są nim oddzielane.
  4. Do zapisu CSV warto wykorzystać inne libki a nie zwykły zapis >>txt, chyba ze program w ktorym to analizujesz łyka taki format jak mas obecnie

edytowany 1x, ostatnio: vitz666
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)