# 🔪 Data scraping / Skrobanie danych ze stron

**URL:** <https://ai-speaker.discourse.group/t/data-scraping-skrobanie-danych-ze-stron/2230>\
**Category:** faq\
**Created:** [22 Październik 2021 15:05 UTC](https://ai-speaker.discourse.group/t/data-scraping-skrobanie-danych-ze-stron/2230 "2021-10-22T15:05:42Z")\
**Posts on this page:** 17\
**Page:** 1

<div class="post-metadata">

**Autor:** ![jolka](https://yyz2.discourse-cdn.com/free1/user_avatar/ai-speaker.discourse.group/jolka/32/5_2.png) [@jolka](https://ai-speaker.discourse.group/u/jolka)\
**Data wpisu:** [22 Październik 2021 15:05 UTC](https://ai-speaker.discourse.group/t/data-scraping-skrobanie-danych-ze-stron/2230/1 "2021-10-22T15:05:42Z")

</div>

# Data scraping / Skrobanie danych

🔪  
po angielsku chyba lepiej brzmi 😉

Pokażę jak w bardzo łatwy spsób można pobierać dane ze stron bo np. nie ma api a wiemy, że jest jakaś informacja na stronie i chcemy ją mieć w HA.  
Scraping nie jest do końca legalny… omijamy reklamy itd.. robimy to czysto edukacyjnie 🙂

Zrobimy to na bramce w JavaScript - NodeJS:

 ![image](https://global.discourse-cdn.com/free1/uploads/ai_speaker/original/2X/b/b76bea0a77d2290364d5a482dbb70488dee574e3.jpeg)

Załużmy, że chcemy pobrać kurs miedzi ze strony bankier.pl

 ![image](https://global.discourse-cdn.com/free1/uploads/ai_speaker/original/2X/a/a085a6678c140fc7790727894353e3ea50e9d45b.png)

# Selektor css

w tym celu otweiramy w przeglądarce źródło strony i lokalizujemy element z ceną:

 ![image](https://global.discourse-cdn.com/free1/uploads/ai_speaker/original/2X/8/80d157225d6d1fe95d6a69228654bd4512cda186.png)

jak widać jest to `div.profilLast`

# Program w nodejs

Teraz napiszemy programik który będzie te dane skrobał (echh) ze strony cenę miedzi.  
W konsoli przechodzimy do AIS i tworzymy folder programy

```auto
cd ~/AIS
mkdir programy
cd programy

```

dodajemy plik miedz.js

```auto
nano miedz.js

```

z takim kodem:

```auto
const axios = require('axios');
const jsdom = require('jsdom');
const {JSDOM} = jsdom;

(async () => {
 const html = await axios.get('https://www.bankier.pl/inwestowanie/profile/quote.html?symbol=MIEDZ');
 const dom = new JSDOM(html.data);

 const cena = dom.window.document.querySelector('div.profilLast');

 if (cena) {
   console.log(cena.textContent)
 }
})();

```

zapisujemy plik, instalujemy 2 biblioteki:

```auto
npm install axios
npm install jsdom

```

teraz możemy już wywołać nasz program wpisując w konsoli:

```auto
node miedz.js 

```

# Pomocnik w aplikacji

dodajemy pomocnika w aplikacji - to w nim będziemy zpisywali cenę miedzi

 ![image](https://global.discourse-cdn.com/free1/uploads/ai_speaker/original/2X/e/ec79c2cded127e8c36dd769fea4ec748c7998b81.png)

kopujemy identyfikator encji nowego pomocnika

 ![image](https://global.discourse-cdn.com/free1/uploads/ai_speaker/original/2X/9/90be551f0d5742c05a9bdf893a77baa15c4c2900.png)

i dodajemy go na stronę w aplikacji

 ![image](https://global.discourse-cdn.com/free1/uploads/ai_speaker/original/2X/0/07c97c96723148bec19f29375d52e444cd928a09.png)

# Wywołanie programu z usługi

```auto
service: ais_shell_command.execute_command
data:
  command: node ~/AIS/programy/miedz.js
  entity_id: input_text.cena_miedzi

```

 ![image](https://global.discourse-cdn.com/free1/uploads/ai_speaker/original/2X/8/836facd65bdf6193078fd6dfc65a80ed31db1316.png)

# Automatyzacja

To już wiadomo - możemy wywołać uslugę z automatyzacji i sprawdzać cenę codziennie automatycznie.

> ⚠ Data scraping nie jest legalnym sposobem na dostęp do danych i dlatego ten post ma charakter czysto edukacyjny - żeby pokazać jak technicznie działa skrobanie danych ze stron.

---

<div class="post-metadata">

**Autor:** ![Cezary.K](https://avatars.discourse-cdn.com/v4/letter/c/a88e4f/32.png) [@Cezary.K](https://ai-speaker.discourse.group/u/Cezary.K)\
**Data wpisu:** [22 Październik 2021 17:36 UTC](https://ai-speaker.discourse.group/t/data-scraping-skrobanie-danych-ze-stron/2230/2 "2021-10-22T17:36:44Z")

</div>

Bardzo dziękuję za przykład. Edukacja trwa 😉

O ile w konsoli otrzymuję prawidłowy wynik zeskrobanej ceny miedzi,  
 ![obraz](https://global.discourse-cdn.com/free1/uploads/ai_speaker/original/2X/4/41863081d2a61f736946a2ccdbcf3425b68b83e5.png)

o tyle w HA jest jakiś kwiatek przy karcie encji.

 ![obraz](https://global.discourse-cdn.com/free1/uploads/ai_speaker/original/2X/3/3283d38a1ddc787c960018d1cda3eb0aaaad626e.png)

W narzędziach deweloperskich podobnie:

 ![obraz](https://global.discourse-cdn.com/free1/uploads/ai_speaker/original/2X/3/3c6dc7299c6c0cf26d5e771f5d5b40c742ac87a1.png)

---

<div class="post-metadata">

**Autor:** ![damu](https://yyz2.discourse-cdn.com/free1/user_avatar/ai-speaker.discourse.group/damu/32/8476_2.png) [@damu](https://ai-speaker.discourse.group/u/damu)\
**Data wpisu:** [22 Październik 2021 19:41 UTC](https://ai-speaker.discourse.group/t/data-scraping-skrobanie-danych-ze-stron/2230/3 "2021-10-22T19:41:55Z")

</div>

Kod \xc2\xa0 w kodowaniu UTF-8 to tzw. niełamliwa spacja. trzeba by to odfiltrować 🙂

---

<div class="post-metadata">

**Autor:** ![Stravi](https://avatars.discourse-cdn.com/v4/letter/s/e9c0ed/32.png) [@Stravi](https://ai-speaker.discourse.group/u/Stravi)\
**Data wpisu:** [22 Październik 2021 19:59 UTC](https://ai-speaker.discourse.group/t/data-scraping-skrobanie-danych-ze-stron/2230/4 "2021-10-22T19:59:14Z")

</div>

Tu jest trochę więcej śmieci:

1. b’…’ - to raczej jest dodane przez serwis Jolki więc tego nie naprawisz
2. \xx - można obejść regexem który kasuje non-ASCI znaki
3. \n - koniec linii odczytany przez serwis Jolki i tam chyba powinien być ogarnięty, ewentualnie można napisać np. `process.stdout.write(cena.textContent);` zamiast `console.log(cena.textContent)`

---

<div class="post-metadata">

**Autor:** ![Cezary.K](https://avatars.discourse-cdn.com/v4/letter/c/a88e4f/32.png) [@Cezary.K](https://ai-speaker.discourse.group/u/Cezary.K)\
**Data wpisu:** [22 Październik 2021 20:16 UTC](https://ai-speaker.discourse.group/t/data-scraping-skrobanie-danych-ze-stron/2230/5 "2021-10-22T20:16:59Z")

</div>

Tylko jak to jest, że u @jolka jest czysty wynik a u mnie śmieci? Nie jestem programistą ale ciekawi mnie skąd taka różnica?

---

<div class="post-metadata">

**Autor:** ![damu](https://yyz2.discourse-cdn.com/free1/user_avatar/ai-speaker.discourse.group/damu/32/8476_2.png) [@damu](https://ai-speaker.discourse.group/u/damu)\
**Data wpisu:** [22 Październik 2021 22:32 UTC](https://ai-speaker.discourse.group/t/data-scraping-skrobanie-danych-ze-stron/2230/6 "2021-10-22T22:32:49Z")

</div>

b’xxxx’ to klasa typu bytes z Python:

```auto
>>> text = b"9\xc2\xa0748,25 USD/tona\n"
>>> type(text)
<class 'bytes'>
>>> print(text)
b'9\xc2\xa0748,25 USD/tona\n'
>>> print(text.decode('UTF-8'))
9 748,25 USD/tona

```

po metodzie decode() w Phyton na print() mamy już bez “farfocli” 🙂

---

<div class="post-metadata">

**Autor:** ![Acid](https://yyz2.discourse-cdn.com/free1/user_avatar/ai-speaker.discourse.group/acid/32/9047_2.png) [@Acid](https://ai-speaker.discourse.group/u/Acid)\
**Data wpisu:** [23 Październik 2021 07:52 UTC](https://ai-speaker.discourse.group/t/data-scraping-skrobanie-danych-ze-stron/2230/7 "2021-10-23T07:52:49Z")

</div>

Witam .  
A czy ktoś może znalazł by czas żeby łopatologicznie wyłożyć jak zrobić takie pobieranie danych w przypadku jeżeli trzeba się zalogować na stronę i dopiero pobrać wyświetlane dane.

---

<div class="post-metadata">

**Autor:** ![macek](https://yyz2.discourse-cdn.com/free1/user_avatar/ai-speaker.discourse.group/macek/32/4936_2.png) [@macek](https://ai-speaker.discourse.group/u/macek)\
**Data wpisu:** [23 Październik 2021 08:16 UTC](https://ai-speaker.discourse.group/t/data-scraping-skrobanie-danych-ze-stron/2230/8 "2021-10-23T08:16:12Z")

</div>

Jeżeli strona do scrapingu jest prosta można skorzystać z oficjalnej integracji [Scrape - Home Assistant](https://www.home-assistant.io/integrations/scrape/), jest też możliwość autentykacji (podania loginu i hasła). Przy konieczności logowania do strony bardzo często można skorzystać z [RESTful - Home Assistant](https://www.home-assistant.io/integrations/rest/).

---

<div class="post-metadata">

**Autor:** ![Mdk](https://yyz2.discourse-cdn.com/free1/user_avatar/ai-speaker.discourse.group/mdk/32/8754_2.png) [@Mdk](https://ai-speaker.discourse.group/u/Mdk)\
**Data wpisu:** [25 Październik 2021 13:18 UTC](https://ai-speaker.discourse.group/t/data-scraping-skrobanie-danych-ze-stron/2230/9 "2021-10-25T13:18:43Z")

</div>

Cześć, może pomógłby mi ktoś w ogarnięciu odczytu danych z mojego invertera pv ze strony [foxesscloud.com](http://foxesscloud.com) chodzi dokładnie o dwa odczyty tzn: bieżąca produkcja i chwilowa moc .  
Na stronę trzeba się oczywiście logować,

 ![produkcja 1](https://global.discourse-cdn.com/free1/uploads/ai_speaker/original/2X/c/c2487a5055164f3592940fb44de844028c68207c.png)  
 ![produkcja 2](https://global.discourse-cdn.com/free1/uploads/ai_speaker/original/2X/d/da12ebb8258a93e6b73308cbc556b557f9dad421.png)  
[Fox Cloud API Protocol.pdf](https://ai-speaker.discourse.group/uploads/short-url/dsvdB1Ze9Fm1oywG19Jku82OEHp.pdf) (451,0 KB) ![Zrzut ekranu (9)](https://global.discourse-cdn.com/free1/uploads/ai_speaker/original/2X/5/5fd7fc4ca85846b111384efe2db4736f5c557fbd.png)

---

<div class="post-metadata">

**Autor:** ![Stravi](https://avatars.discourse-cdn.com/v4/letter/s/e9c0ed/32.png) [@Stravi](https://ai-speaker.discourse.group/u/Stravi)\
**Data wpisu:** [25 Październik 2021 14:01 UTC](https://ai-speaker.discourse.group/t/data-scraping-skrobanie-danych-ze-stron/2230/10 "2021-10-25T14:01:51Z")

</div>

Scraping tutaj nie ma sensu bo masz API, tylko musisz je skonfigurować.  
Na dodatek jest opcja z MQTT więc “dzień dobry XXI wiek”

---

<div class="post-metadata">

**Autor:** ![Mdk](https://yyz2.discourse-cdn.com/free1/user_avatar/ai-speaker.discourse.group/mdk/32/8754_2.png) [@Mdk](https://ai-speaker.discourse.group/u/Mdk)\
**Data wpisu:** [25 Październik 2021 14:08 UTC](https://ai-speaker.discourse.group/t/data-scraping-skrobanie-danych-ze-stron/2230/11 "2021-10-25T14:08:52Z")

</div>

Fajnie… Tylko kurka jak to osiągnąć?

---

<div class="post-metadata">

**Autor:** ![Tomasz](https://yyz2.discourse-cdn.com/free1/user_avatar/ai-speaker.discourse.group/tomasz/32/286_2.png) [@Tomasz](https://ai-speaker.discourse.group/u/Tomasz)\
**Data wpisu:** [25 Październik 2021 16:10 UTC](https://ai-speaker.discourse.group/t/data-scraping-skrobanie-danych-ze-stron/2230/12 "2021-10-25T16:10:23Z")

</div>

> [@Mdk](#):
>
> [foxesscloud.com](http://foxesscloud.com)

widzę że jest integracja [custom\_components](https://ai-speaker.discourse.group/t/bramka-wlasny-komponent-w-asystencie-domowym/68):  
[GitHub - macxq/foxess-ha: Home Assistant & FoxESS integration (cdnweb.icu)](https://github.cdnweb.icu/macxq/foxess-ha/releases)  
ale faktycznie jak jest możliwość przez MQTT to najlepsze rozwiązanie, zacznij od ustawienia tego:

 ![image](https://global.discourse-cdn.com/free1/uploads/ai_speaker/original/2X/f/f41c3a3f7701960b6022b4a23a8fe00c9df56e67.png)  
gdzie “Broker Addres” to adres ip twojej bramki

potem wykorzystując [MQTT Explorer](https://ai-speaker.discourse.group/t/wyjasnienie-jak-dziala-komunikacja-urzadzen-z-bramka-mqtt-explorer-fajne-narzedzie-do-mqtt/213) zobacz czy spływają jakieś dane po MQTT

---

<div class="post-metadata">

**Autor:** ![Cezary.K](https://avatars.discourse-cdn.com/v4/letter/c/a88e4f/32.png) [@Cezary.K](https://ai-speaker.discourse.group/u/Cezary.K)\
**Data wpisu:** [25 Październik 2021 16:41 UTC](https://ai-speaker.discourse.group/t/data-scraping-skrobanie-danych-ze-stron/2230/13 "2021-10-25T16:41:19Z")

</div>

Może załóż nowy temat, jak zainstalować niestandardowy komponent masz opisane na forum…

@Tomasz - 👍  
może ten link z instrukcją będzie bardziej czytelny (ta sama integracja).

> **[GitHub - macxq/foxess-ha: Home Assistant & FoxESS integration](https://github.com/macxq/foxess-ha)**
>
> Home Assistant & FoxESS integration. Contribute to macxq/foxess-ha development by creating an account on GitHub.

---

<div class="post-metadata">

**Autor:** ![Mdk](https://yyz2.discourse-cdn.com/free1/user_avatar/ai-speaker.discourse.group/mdk/32/8754_2.png) [@Mdk](https://ai-speaker.discourse.group/u/Mdk)\
**Data wpisu:** [25 Październik 2021 16:54 UTC](https://ai-speaker.discourse.group/t/data-scraping-skrobanie-danych-ze-stron/2230/14 "2021-10-25T16:54:23Z")

</div>

![image](https://global.discourse-cdn.com/free1/uploads/ai_speaker/original/2X/f/f41c3a3f7701960b6022b4a23a8fe00c9df56e67.png)  
powiedz co to jest?  
masz to gdzieś w ustawieniach invertera a może w chmurze [foxesscloud.com](http://foxesscloud.com/)?  
ja to tak rozumiem, że gdzieś w ustawieniach invertera wpisujesz adres swojego serwera mqtt czyli twojej bramki i wtedy bramka wykrywa sensory z invertera, coś na zasadzie jak z [Iot link](https://ai-speaker.discourse.group/t/integracja-komputera-za-pomoca-iot-link-ai-speaker-home-assistant/389)

---

<div class="post-metadata">

**Autor:** ![Cezary.K](https://avatars.discourse-cdn.com/v4/letter/c/a88e4f/32.png) [@Cezary.K](https://ai-speaker.discourse.group/u/Cezary.K)\
**Data wpisu:** [25 Październik 2021 17:03 UTC](https://ai-speaker.discourse.group/t/data-scraping-skrobanie-danych-ze-stron/2230/15 "2021-10-25T17:03:04Z")

</div>

Zacznij od przeczytania lektury aby zrozumieć jak działa MQTT:

> **[Broker MQTT działający na bramce | AI-Speaker](https://ai-speaker.com/docs/ais_bramka_mqtt/)**
>
> Asystent domowy ma wbudowany broker MQTT.

> [@Wyjaśnienie jak działa komunikacja urządzeń z bramką. MQTT Explorer - Fajne narzędzie do MQTT](https://ai-speaker.discourse.group/t/wyjasnienie-jak-dziala-komunikacja-urzadzen-z-bramka-mqtt-explorer-fajne-narzedzie-do-mqtt/213):
>
> Broker MQTT Na bramce AIS dom działa [broker MQTT Mosquitto](https://mosquitto.org/) Klient MQTT MQTT Explorer MQTT Explorer to klient MQTT, który pozwala na przegląd tematów MQTT i pozwala na wysyłanie komunikatów do brokera MQTT Połączenie z bramką AIS dom z klienta MQTT Tak możemy połączyć się z brokerem MQTT z programu MQTT Explorer : (jeżeli nasz system nie obsługuje mDNS to zamiast nazwy hosta ais-dom.local podajemy IP bramki w lokalnej sieci) Wysłanie widomości do bramki z kleinta MQTT W MQTT wiado…

Postaraj się zrozumieć i załóż osobny temat, to w nim Ci pomożemy. Szoka robić off-topic.

---

<div class="post-metadata">

**Autor:** ![Mdk](https://yyz2.discourse-cdn.com/free1/user_avatar/ai-speaker.discourse.group/mdk/32/8754_2.png) [@Mdk](https://ai-speaker.discourse.group/u/Mdk)\
**Data wpisu:** [25 Październik 2021 17:40 UTC](https://ai-speaker.discourse.group/t/data-scraping-skrobanie-danych-ze-stron/2230/16 "2021-10-25T17:40:53Z")

</div>

Dobra, jak przetrawię tę wszystkie informacje i się trochę w tym ogarnę to założę nowy temat i tam będę drążył go dalej. Na tą chwilę podziękować wam muszę za pomoc!

---

<div class="post-metadata">

**Autor:** ![jolka](https://yyz2.discourse-cdn.com/free1/user_avatar/ai-speaker.discourse.group/jolka/32/5_2.png) [@jolka](https://ai-speaker.discourse.group/u/jolka)\
**Data wpisu:** [27 Październik 2021 10:31 UTC](https://ai-speaker.discourse.group/t/data-scraping-skrobanie-danych-ze-stron/2230/17 "2021-10-27T10:31:36Z")

</div>

> [@Cezary.K](#):
>
> o tyle w HA jest jakiś kwiatek przy karcie encji.

faktycznie zwracamy obiekt w bajtach a nie tekst

![image](https://global.discourse-cdn.com/free1/uploads/ai_speaker/original/2X/6/6f5ae3178c23fc1646810104a5f7751856db7d3a.png)

zwraca

![image](https://global.discourse-cdn.com/free1/uploads/ai_speaker/original/2X/8/8fa29dd90f8b065aa24593b03e7bd26eccdf9c88.png)

w python żeby przerobić obiekt w bajtach na string trzeba zrobić `decode("utf-8")`  
trzeba dopisać coś takiego w pliku integracji ais\_shell\_command który jest na bramce

 ![image](https://global.discourse-cdn.com/free1/uploads/ai_speaker/original/2X/2/26432bf80e82900c1b5fcd55c7148736ba9090b7.png)

Poprawimy to w kolejnym wydaniu i opiszemy dokładniej usługę `execute_command` bo ona może mieć więcej parametrów (dotychczas używaliśmy ją tylko wewnętrznie) i może się to komuś przydać.

 ![image](https://global.discourse-cdn.com/free1/uploads/ai_speaker/original/2X/3/329a23e4111e852ed9dee253f66aa0e356af906d.png)

```auto
service: ais_shell_command.execute_command
data:
  command: echo "123 EUR"
  entity_id: input_text.cena_miedzi
  friendly_name: Aktualna cena miedzi
  icon: mdi:cash-100

```

ważne żeby zrozumieć działanie:

 ![image](https://global.discourse-cdn.com/free1/uploads/ai_speaker/original/2X/3/372659364678da5439de94673fcf19ca35da7411.png)

* * *

PS

Oczywiście można to zrobić w inny sposób, np. przez “asynchroniczny interfejs plikowy”. Czyli tak:

1. Nasz program (w dowolnym języku który jest na bramce), robi jakąś “magię” i zapisuje wynik do pliku ~/AIS/programy/sensor1.txt

np. powyższy program który napisaliśmy w nodejs  
możemy przekirować wyjście do pliku a nie bezpośrednio do encji w aplikacji, coś takiego

```auto
service: ais_shell_command.execute_command
data:
  command: node ~/AIS/programy/miedz.js > ~/AIS/programy/sensor1.txt

```

po wywołaniu takiej usługi

 ![image](https://global.discourse-cdn.com/free1/uploads/ai_speaker/original/2X/a/ab728eaa397ce430eade5d827455bafd1c4d85b0.png)

możemy sprawdzić w konsoli efekt:

```auto
cat ~/AIS/programy/sensor1.txt

```

![image](https://global.discourse-cdn.com/free1/uploads/ai_speaker/original/2X/a/abbcca82cffaa5a60a8875654a94186533f525a1.png)

1. Dodajemy w AIS/HA sensor który zaczytuje dane z pliku

```YAML
sensor:
  - platform: file
    file_path: ~/AIS/programy/sensor1.txt

```

Wszystko się dzieje asynchronicznie, nikt na nikogo nie czeka.

W efekcie mamy dane w encji nowego sensora, o te dane możemy pytać asystenta głosowo komendą:

- `status ... `
- `jaka jest ...`
- `jaki jest ...`  
…
