Machine Learning pl

Pozyskiwanie danych do analizy — scraper

Zajmując się zagadnieniami machine learning, często stoimy przed problemem pozyskania wartościowych danych. Nie zawsze bowiem mamy dostęp do profesjonalnych baz, zasilonych treścią dokładnie taką, na jakiej nam zależy.

Pomocnym staje się wtedy budowa automatu (scrapera), który pobierze interesujące nas treści z Internetu.

Pisząc artykuł Jak nauczyć program rozumienia języka polskiego, musiałem dysponować dużą ilością tekstów w języku polskim, aby wytrenować/nauczyć model rozumienia polskiej mowy potocznej.

W tym celu napisałem aplikację, która hurtowo pobrała wpisy z jednego z popularnych serwisów agregujących opinie o firmach i zapisała je w bazie. Użyłem go również, aby pozyskać bazę aktualnie wystawionych na sprzedaż mieszkań z Warszawy.

Kod źródłowy udostępniam pod tym adresem. Jest on całkowicie darmowy, tak więc możesz używać go dowolnie.

Ale do brzegu, przeanalizujmy jak to działa

Większość operacji związanych z pobieraniem danych, odbywać się będzie się w głównym pliku aplikacji, w klasie main, w metodzie uruchomieniowej run. Okresowo sięgać będziemy do innych klas, w których przechowujemy inne, przydatne metody.

Na początek utwórzmy obiekt klasy http_connect_class

from modules import http_request

http_request_obj = http_request.http_connect_class()

i pobierzmy zawartość całej strony portalu do zmiennej soup

def get_html(self, url):
    request = urllib.request.Request(url)
    response = urllib.request.urlopen(request)
    soup = BeautifulSoup(response, 'html.parser')
    return soup

soup = http_request_obj.get_html(url)

W kodzie portalu, liczba gwiazdek oraz tekst recenzji, w uproszczeniu wygląda tak:

<span class='review positive'>5</span>
 
<div class='text'>
  <span>Przesyłka na czas. Produkt zgodny z opisem. Polecam :)</span>
</div>

lub

<span class='review negative'>1</span>
 
<div class='text'>
  <span>Bateria w telefonie trzyma pół dnia. Nie polecam!</span>
</div>

Przy użyciu biblioteki BeautifulSoup parsujemy kod i budujemy listy zawierające ocenę oraz tekst opisu. Tu ciekawostka: nazwa biblioteki pochodzi od tego, że świetnie radzi sobie również z tzw. “zupą tagów”, czyli niechlujnie napinanym kodem HTML z niedomkniętymi lub przenikającymi się krzyżowo tagami.

from bs4 import BeautifulSoup
import re

rating_star_list = soup.findAll('span', {'class': re.compile("^review*")})
text_review_list = soup.findAll("div", {"class": "text"})

Z uwagi na to, że użyliśmy wyrażenia regularnego ^review* zapisujemy do listy zarówno tagi review negative jak i review positive.

Teraz powołujemy nową instancję klasy db_sql_lite_class,

from modules import sqlite

db_obj = sqlite.db_sql_lite_class()

otwieramy podręczną bazę SQLite

def open_database(self, db_path):   
    try:
        conn = sqlite3.connect(db_path)
    except:
        print("Blad otwarcia bazy:", db_path)        
    return conn

conn = db_obj.open_database(db_path)

i zapisujemy przechowywane w zmiennych dane z portalu.

def save_data_in_database(self, conn, db_path, rating_star, text_review):     
    try:
        conn = sqlite3.connect(db_path)     
        sql = '''INSERT INTO reviews VALUES 
                 ('''+str(rating_star)+''',"'''+text_review+'''"); '''
        c = conn.cursor()
        c.execute(sql)
        c.execute('commit')
        conn.close()    
    except:  
        print("Blad zapisu do bazy", db_path)

db_obj.save_data_in_database(conn, db_path, rating_star, text_review)

Praca scrapera została wykonana a dane zostały zapisane do bazy: