„Nie! Sam robię ebooki, z Pythonem!”

Taką odpowiedź usłyszał mój kolega, gdy spytał mnie jak zdobywam potrzebną mi wiedzę.

Zacznijmy od początku.

Mam kolegę, który jak co roku zabiera się za postanowienia noworoczne. Nie śmieję się, bo sam to robię.

Dziwne jest w tym wszystkim zdanie czy raczej pytanie jakie przy okazji tego wypowiedział: „Chciałbym zmienić coś, ale mi się nie chce, bo nie wiem jak?”.

„Hmmm…” odpowiedziałem. Na tyle mnie było stać w tej chwili.

Zauważyłem jednak 1 główny problem mojego kolegi… BRAK WIEDZY. Od tego wyszły wszystkie inne łącznie z brakiem motywacji.

Odpowiedziałem po chwili: „Znajdź odpowiednie ebooki (wiem, że nie lubi papierowych książek), wybierz coś, kup, przeczytaj i zastosuj”.

Spytał mnie: „Ty tak robisz?”.

Już chciałem odpowiedzieć, że tak. To byłoby jednak zbyt oczywiste.

Przypomniał mi się mój projekt i odpowiedziałem przekornie: „Nie! Sam robię ebooki, z Pythonem”.

Jeśli jesteś osobą jak mój kolega, która chce być BARDZIEJ, mieć WIĘCEJ, żyć LEPIEJ, ale myśli sobie: „BRAKUJE MI WIEDZY!”.

Ten post jest dla Ciebie. Program, który tutaj pokazuje jest dla Ciebie.

Bez znaczenia jaki problem masz. Jakiej zmiany chcesz dokonać.

Zdobędziesz wiedzę z dowolnej dziedziny a Python Ci w tym pomoże.

Klucze Willa Smitha

Zaczniemy od Willa Smitha, którego chyba nie muszę Ci przedstawiać. W tym krótkim wideo poniżej Will zdradza 2 Klucze Do Życia. Posłuchaj.

Will Zdradza 2 Klucze Do Życia

Pierwszy z nich to… BIEGANIE. Nie samo bieganie jako takie. Chodzi o walkę z samym sobą. Pokonywanie wewnętrznego głosu w Tobie: „Nie dam rady! Już dosyć! Wystarczy!”.

Drugi klucz to…CZYTANIE. Na naszej planecie, żyje około 7 843 000 000 ludzi. Sprawdź tutaj jak szybko nas przybywa.

Łączy nas wiele. Mamy te same: problemy, radości, zmartwienia, pragnienia i potrzeby.

Masz jakiś problem? Dobra wiadomość. Ktoś też już kiedyś go miał.

Najlepsze jest jednak to, że go rozwiązał. Mało tego. Napisał o tym książkę. Podzielił się rozwiązaniem.

BUM…

To jest prawdziwy LIFEHACK. Skrót, z którego możemy korzystać.

Masz wątpliwości? Zobacz jaki stosunek do czytania ma Elon Musk (punk 2: Czego jeszcze nie wiesz o Elonie Musku?).

Podsumowując. Masz problem? Znajdź kogoś kto miał ten problem, rozwiązał go i opisał.

Wykorzystujesz rozwiązanie. Nie wymyślasz koła na nowo. Szkoda czasu, zdrowia i pieniędzy.

Myślisz sobie: „No tak, ale za wiedzę się płaci!”. Bo skoro mowa o CZYTANIU, to mowa o książkach. Skoro książki to trzeba płacić.

Niekoniecznie.

Dzisiaj pokażę Ci jak zrobić książkę a ściślej ebooka z wiedzą jaką chcesz.

Zacznijmy od źródła wiedzy.

Darmowa Wiedza

Źródłem darmowej wiedzy są… ?

Blogi.

Oczywiście są jeszcze podcasty, filmy i wiele wiele innych źródeł skąd można czerpać wiedzę.

Jesteśmy jednak przy 2 Kluczu Willa, czyli przy CZYTANIU.

Zaznaczę tutaj coś co myślę, że jest bardzo ważne.

Darmowa wiedza to nie znaczy bezwartościowa.

Wiele osób dzieli się swoimi doświadczeniami za darmo. Szanujmy to, respektując prawa autorskie.

Dlatego ja dla celów tego wpisu zapytałem o zgodę na wykorzystanie materiałów z innego bloga.

Pokazuje Ci sposób na zdobywanie wiedzy, ale wykorzystuj go rozważnie.

Dziś każdy może być twórcą. Wiele osób uczy, dzieli się doświadczeniem. Chwała im za to. Często stajemy na barkach osób, które pokonały to co jest przed nami. Dzięki temu osiągamy więcej i szybciej. Odkrywamy w pełni Nasze Możliwości.

Tym zgrabnym sposobem nawiązałem do strony Karola Pasierba.

Strona Karola Pasierba - Nasze Możliwości
Nasze Możliwości – Blog Karola Pasierba

Badanie Źródła

Aby czerpać z źródła musimy je sprawdzić. Zobaczmy jak zbudowana jest strona:

  • Jakie są znaczniki?
  • Jakie atrybuty?
  • Jaka jest ich budowa?
  • Gdzie jest treść?

Plan jest taki:

  • Robimy ebooka więc szukamy kategorii, z której sobie ją zrobimy. Wybrałem kategorię: Książki. Zrobię książkę z podsumowaniami z innych książek. Potrzebny będzie adres strony z kategorią.
karolpasierb.pl/category/ksiazki
Adres Kategorii z Książkami
Strona Kategorii Książki
Strona Kategorii: Książki
  • Sprawdzam jak zbudowana jest strona z kategorią (prawy przycisk myszy „Zbadaj” na stronie). Szukam znacznika gdzie jest zawartość (content) strony. Mamy div z id="primary„.
Badanie Strony z Kategorią
Badanie Strony z Kategorią
  • Sprawdzam jak wiele stron ma dana kategoria. Przechodzę na ostatnią stronę, czyli najstarsze wpisy w danej kategorii. Wyszło, że tylko 2 strony.
karolpasierb.pl/category/ksiazki/page/2/
Liczba Stron w Kategorii
  • Pora na analizę strony z postem. Gdzie jest tytuł postu (prawy przycisk „Zbadaj” na stronie)? Znacznik h1 z atrybutem class="entry-title".
Tytuł Wpisu W Znaczniku H1
Tytuł Wpisu w Znaczniku H1
  • Gdzie jest zawartość(content)? Znacznik div z atrybutem class="entry-content".
Treść Wpisu w Znaczniku DIV
Treść Wpisu w Znaczniku DIV
  • Są elementy, które chciałbym pominąć a znajdują się w atrybucie <div class="entry-content">. Zanotuje je sobie wykorzystując atrybut class np. 'heateor_sss_sharing_ul'.
  • Mam wszystko co potrzebne. Ogólny szkielet. Zaraz dopracujemy detale. Tworzę sobie plik config.py, gdzie zbieram to co już wiem.
# ======== KAROL PASIERB https://www.karolpasierb.pl/ ========

# USTAWIENIA DLA EBOKA W PDF
AUTOR_EBOOKA = 'Karol Pasierb'

TYTUL_EBOOKA = 'Nasze Możliwości'

PODTYTUL_EBOOKA= 'Zainspiruj się! Możesz Osiągnąć Więcej! Rozwój osobisty, osiąganie celów, organizacja.'

# DANE DOTYCZĄCE WYBRANEJ KATEGORII
URL_KATEGORIA = 'https://www.karolpasierb.pl/category/ksiazki/'
URL_ILOSC_STRON_KATEGORIA = 2

KATEGORIA_ID_CONTENT= 'primary'
KATEGORIA_TAG_CONTENT= 'div'

# DANE DOTYCZĄCE KONKRETNEGO POSTA
TYTUL_POSTA_TAG = 'h1'
CONTENT_POSTA_TAG = 'div'
TYTUL_POSTA_CLASS = 'entry-title'
CONTENT_POSTA_CLASS = 'entry-content'

# WYKLUCZONE KLASY 'CLASS' Z PRZESZUKIWANIA
KLASY_POMINIETE = ['heateor_sss_sharing_ul']

Mamy strukturę: kategorii i pojedynczego wpisu. Wiemy już gdzie jest wiedza. Czas ją zebrać.

Gromadzenie i Łączenie Wiedzy

Python, jako główny rozgrywający zajmie się tworzeniem książki. Potrzebujemy pomocników.

Pomocnik 1

Do gry wkracza 1 pomocnik, biblioteka Beautiful Soup.

Najprościej rzecz ujmując pozwala wyciągać dane ze stron internetowych (z ang. Web Scrapping). Innymi słowami: czyta znaczniki HTML-a, ich atrybuty i oczywiście tekst.

Ok, jedną ręką czytam, drugą piszę. Czyli czytam co jest na stronie i zapisuje gdzieś. Tylko gdzie?

Hmm… skoro ebook… to pdf?

Teoretycznie moglibyśmy to zrobić. Są do tego biblioteki np. PyPDF2. Z niej skorzystam by dodać „wisienkę na tort”.

Chodzi o to, że nie chcę tylko skopiować tekst i wkleić go pdf-a.

Chcę aby ebook cieszył oko, żeby było przyjemnie go otwierać i przekręcać nieszeleszczące na ekranie kartki. Jednym słowem ma być sformatowany. Profesjonalnie.

Pomocnik 2

Do gry wkracza 2 pomocnik. Biblioteka PyLaTeX, która pozwala tworzyć i kompilować pliki LaTeX-a.

Pytasz czym zatem jest sam LaTeX?

To taki automat do składania tekstu. Definiujesz reguły, dodajesz do tego tekst i zapisujesz wszystko w pliku z rozszerzeniem '*.tex'. Taki plik następnie kompilujesz by dostać ślicznego pdf-a.

Inaczej jak w tradycyjnym Wordzie, gdzie sam wszystko ustawiasz ręcznie.

Przypominasz sobie może jakąś większą pracę napisaną w Wordzie? Pamiętasz frustrację kiedy niby wszystko jest sformatowane, chcesz coś wydrukować a tu wszystko się „roz…jechało”.

W LaTeX-u akurat tego problemu nie ma.

Mała galeria możliwości LaTeX-a.

Potrzebujemy kompilatora, który zamieni plik *.tex na *.pdf.

W zależności od systemu jaki masz powinieneś wybrać coś z tej listy i zainstalować na swoim sprzęcie. Gdyby były problemy z kompilacją warto też zainstalować PERL-a (zwłaszcza dla Windowsów). Linuxy często mają go już na pokładzie.

Wracamy do PyLaTeX-a. Tworzyć będziemy plik *.tex z poziomu Pythona i zamienimy go ostatecznie w plik *.pdf.

Do Jednej Bramki

Dwóch pomocników gra teraz do jednej bramki.

Beautiful Soup czyta stronę a PyLaTeX zapisuje do pliku *.tex.

Scenariusz gry jest taki:

  • pobieramy linki do wszystkich wpisów z wybranej kategorii,
  • odwracamy ich kolejność od najstarszych do najnowszych bo chcemy mieć wiedzę po kolei,
  • otwieramy stronę z każdym wpisem,
  • czytamy tytuł wpisu (znacznik h1) i zapisujemy jako nazwę jako rozdział książki,
  • odnajdujemy nagłówki niższego rzędu (znaczniki h2 i h3), będą to nazwy podrozdziałów,
  • wreszcie czytamy akapity (znaczniki p) oraz wszystkie listy (znaczniki ol i ul).
  • wszystko zgrabnie zbieramy w jednym pliku *.tex.

Plik html_read.py poniżej to wynik gry zespołowej.

from pylatex import Command, NoEscape, Itemize, Enumerate, Figure
import requests
from bs4 import BeautifulSoup

# pobieramy sobie adresy do wszystkich wpisów z wybranej kategorii
def pobierz_linki(url_kategoria,ilosc_stron, tag_contentu,id_contentu):

    linki_do_postow = []

    for licznik in range(ilosc_stron,0,-1):
        url = url_kategoria +'/page/'+str(licznik)
        response = requests.get(url)
        soup = BeautifulSoup(response.text, 'lxml')
        kategoria_content = soup.find(tag_contentu,attrs={'id': id_contentu})
        lista_linkow_ze_strony = []
        for link in kategoria_content.find_all('a'):
            if link.parent.name == 'h2':
                lista_linkow_ze_strony.append(link.get('href'))
        # odwracamy linki aby mieć od pierwszych postów z bloga
        lista_linkow_ze_strony.reverse()
        linki_do_postow += lista_linkow_ze_strony
    return linki_do_postow

# czytamy i zapisujemy akapit
def p_tag(element, document):
    for string in element.strings:
        if string.parent.name == 'strong':
            document.append(Command('textbf',string))
            document.append(NoEscape(r'\space'))
        else:
            document.append(string)
        if string.next_element.name == 'br':
            document.append(Command('newline'))
    document.append(Command('par'))

#czytamy i zapisujemy nagłówek h2
def h2_tag(element,document):
    for string in element.strings:
        document.append(NoEscape(r'\subsection{'+string +'}'))

#czytamy i zapisujemy nagłówek h3
def h3_tag(element,document):
    for string in element.strings:
        document.append(NoEscape(r'\subsubsection{'+string +'}'))

#czytamy i zapisujemy akapit z cytowaniem
def p_tag_blockquote(element, document):
    if element.parent.name == 'blockquote':
        document.append(NoEscape(r'\begin{quote}'))
        p_tag(element,document)
        document.append(NoEscape(r'\end{quote}'))
    else:
        p_tag(element,document)
        
#czytamy i zapisujemy listę nieuporządkowaną
def ul_tag(element,document):
    with document.create(Itemize()) as itemize:
        for item in element.findAll():
            if item.name == 'li':
                itemize.add_item(item.get_text())
        itemize.append(Command("ldots"))

#czytamy i zapisujemy listę uporządkowaną
def ol_tag(element, document):
    with document.create(Enumerate()) as enum:
        for item in element.findAll():
            if item.name == 'li':
                enum.add_item(item.get_text())

#funkcja zbiorcza do powyzszych funkcji
def read_html(element,document):
    if element.name == 'p':
        p_tag_blockquote(element, document)
    elif element.name == 'h2':
        h2_tag(element, document)
    elif element.name == 'h3':
        h3_tag(element, document)
    elif element.name == 'ul':
        ul_tag(element, document)
    elif element.name == 'ol':
        ol_tag(element, document)

Dystrybucja Wiedzy

Najtrudniejsza część za nami. Jesteśmy już naprawdę blisko.

To co zdefiniowaliśmy w pliku config.py, html_read.py spinamy w jedną funkcję main.

import config
import html_read
import requests
from bs4 import BeautifulSoup
from pylatex import Document, Package,NoEscape, Command
from PyPDF2 import PdfFileMerger

if __name__ == '__main__':

    # stworzenie nowego dokumentu LaTeX i początkowe ustawienia
    document = Document()
    document.preamble.append(Package('parskip'))
    document.append(NoEscape(r'\title{' + config.TYTUL_EBOOKA + r'\\'+  r'\large '+config.PODTYTUL_EBOOKA +'}'))
    document.preamble.append(Command('author', config.AUTOR_EBOOKA))
    document.preamble.append(NoEscape(r'\date{}'))
    document.append(NoEscape(r'\clearpage\maketitle'))
    document.append(NoEscape(r'\thispagestyle{empty}'))
    document.append(NoEscape(r'\newpage'))

    linki = html_read.pobierz_linki(config.URL_KATEGORIA,config.URL_ILOSC_STRON_KATEGORIA,config.KATEGORIA_TAG_CONTENT,
                                    config.KATEGORIA_ID_CONTENT)
    licznik = 0
    for link in linki:
        url = link
        response = requests.get(url)
        soup = BeautifulSoup(response.text, 'lxml')
        tytul_posta = soup.find(config.TYTUL_POSTA_TAG,attrs={'class': config.TYTUL_POSTA_CLASS})
        post_content = soup.find(config.CONTENT_POSTA_TAG, attrs={'class': config.CONTENT_POSTA_CLASS})

        document.append(NoEscape(r'\section{'+tytul_posta.get_text().rstrip() +'}'))

        elements_set = []
        elements = post_content.findAll()
        licznik+=1

        for element in elements:
            if element.get('class') is not None:
                S1 = set(element.get('class'))
                S2 = set(config.KLASY_POMINIETE)
                if S1.difference(S2):
                    html_read.read_html(element,document)
            else:
                html_read.read_html(element, document)

        document.append(NoEscape(r'\newpage'))
    try:
        document.generate_pdf(config.TYTUL_EBOOKA, compiler='pdflatex')
    except UnicodeDecodeError:
        print('Błąd Unicode!')

Mamy gotowego ebooka.

Pierwsza Strona Ebooka
Pierwsza Strona Naszego Ebooka

Gotowa Książka

Prawie gotowego.

To co teraz robię nie jest kluczowe. Mamy w sumie to co nam potrzeba: WIEDZĘ.

Chciałbym Ci jeszcze tylko pokazać prosty sposób na łączenie pdf-ów.

Pierwszym z nich jest już nasz ebook, drugim przygotowana w Canvie okładka.

 # robimy ebooka z okladka
    pdfy = ['cover.pdf', config.TYTUL_EBOOKA + '.pdf']

    merger = PdfFileMerger()

    for pdf in pdfy:
        merger.append(pdf)

    merger.write("Nasze Możliwości Cover.pdf")
    merger.close()

Ostatecznie wygląda to tak.

Okładka i Tytuł Ebooka
Okładka i Tytuł Ebooka

To Dopiero Początek

Chociaż jesteśmy to końcu to dopiero początek.

Pamiętasz jak napisałem: „Od wiedzy wszystko się zaczyna?”

Samo posiadanie wiedzy jeszcze niczego nie zmienia. Bo dopiero jej implementacja, wdrożenie w życie zmienia wszystko.

Jeśli chcesz wyodrębnić esencję ze swojego nowego ebooka. Tutaj masz praktyczny sposób: Król Dyplomacji Na Google Drive.

Życzę Ci powodzenia w implementacji. W wygrywaniu z samym sobą bo na tym to polega.

Taktyka Killera