• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Вопрос Поиск значения на web-странице

Прошу Вашего совета.
Необходимо получить необходимые данные с web страницы.
К примеру , esp8266 нужно узнать погоду в Лондоне с сайта sinoptik.ua/
Создается на esp web-client.
Он отправляет GET запрос на сайт
Погода в Лондоне. Прогноз погоды в Лондоне на сегодня, завтра и неделю. Англия - SINOPTIK.
Открывается страница sinoptik.ua с погодой в Лондоне.
Sinoptik.png
В коде страницы температура находится в теге
Значение.png
Как мне получить это значение " + 13 " ?
 

NeoroN

Member
Код примерно такой:
HTML:
<p class="today-temp">+10°C</p>
вначале надо найти "today-temp" затем от найденной позиции ищем конец тега ">" и запоминаем позицию, потом от найденной позиции ищем начало тега "<" в финале есть две позиции - извлекаем текст между ними.
Регулярными выражениями это сделать очень просто Regex101 - online regex editor and debugger
 

NeoroN

Member
Для начала предоставьте код который получает содержимое страницы в переменную типа String. Мне лень искать этот ваш web-client и переделывать его под ваши нужды.

Код:
String buf = String('<p class="today-temp">+10°C</p>');
unsigned int start = buf.indexOf('>',buf.indexOf("today-temp")+10);
unsigned int end = buf.indexOf('<',start+1);
String temp = buf.substring(start,end);
 
Последнее редактирование:

=AK=

New member
Для начала предоставьте код который получает содержимое страницы в переменную типа String. Мне лень искать этот ваш web-client и переделывать его под ваши нужды.

Код:
String buf = String('<p class="today-temp">+10°C</p>');
unsigned int start = buf.indexOf('>',buf.indexOf("today-temp")+10);
unsigned int end = buf.indexOf('<',start+1);
String temp = buf.substring(start,end);
Проще искать строку
Код:
<p class="today-temp">
при помощи find
 

NeoroN

Member
в Arduino нет <iostream> и соответвенно никаких find
А если писать на LUA то регуляркой проще...
 

pvvx

Активный участник сообщества
Прошу Вашего совета.
Необходимо получить необходимые данные с web страницы.
К примеру , esp8266 нужно узнать погоду в Лондоне с сайта sinoptik.ua/
По началу вам следует проверить, способен ли ESP8266 открыть TLS сессию с данным HTTPS сервером.
Снимок57.gif
Код:
#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>

char ssid[] = "";       // your network SSID (name) 
char password[] = "";  // your network key

WiFiClientSecure client;

void setup() {
  Serial.begin(115200);
  WiFi.mode(WIFI_STA);
  WiFi.disconnect();
  delay(100);
  Serial.print("Connecting Wifi: ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
  }
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  IPAddress ip = WiFi.localIP();
  Serial.println(ip);
}

char host[] = "sinoptik.ua";
void loop() {
  if (client.connect(host, 443)) {
    Serial.println("connected");
    client.println("GET / HTTP/1.1");
    client.print("Host: "); client.println(host);
    client.println("User-Agent: arduino/1.0");
    client.println("");
    delay(1000);
    while (client.available()) {
      char c = client.read();
      Serial.write(c);
    }
    client.stop();
  }
  delay(10000);
}
Код:
WiFi connected
IP address: 
192.168.1.225
connected
HTTP/1.1 302 Moved Temporarily
Server: nginx
Date: Wed, 25 Apr 2018 22:08:59 GMT
Content-Type: text/html
Content-Length: 154
Connection: keep-alive
Set-Cookie: os=UNKNOWN; path=/
Location: https://sinoptik.com.ru/
X-Server-By: sinfe1

<html>
<head><title>302 Found</title></head>
<body bgcolor="white">
<center><h1>302 Found</h1></center>
<hr><center>nginx</center>
</body>
</html>
 
Последнее редактирование:
По началу вам следует проверить, способен ли ESP8266 открыть TLS сессию с данным HTTPS сервером.
Загрузил Ваш скетч в ESP.
WiFi connected
IP address:
192.168.0.113
connected
HTTP/1.1 200 OK
Server: nginx
Date: Wed, 25 Apr 2018 23:24:45 GMT
Content-Type: text/html; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
Set-Cookie: os=UNKNOWN; path=/
X-Powered-By: PHP/5.5.38
X-Frame-Options: DENY
ETag: W/"74f7aed66760fa48be2a2293dd1202c6"
Vary: Accept-Encoding
X-Server-By: sinfe1

А потом в терминал он выдал весь код страницы. Там была искомая строчка с температурой.
Можно эти данные страницы сохранить в ESP и потом выделить это значение ?

Пробовал другие сайты подставлять. Не все работают . Точнее мало кто работает. С чем это может быть связано ?
(Прошу прощения за глупые вопросы. Не силен в программировании)
 

pvvx

Активный участник сообщества
Вам бы надо определиться - вариант делается для себя, с возможностью последующей смены кода, если что, ...
или вариант, который должен разбирать все ошибки?
или вариант универсальный, в качестве библиотеки для других, чтобы сменив пару строк можно было парсить любые сайты?

Я думаю, что первый вариант - написать как можно проще, чтобы как-то работало.
Для такого варианта достаточно найти совпадения любого кол-ва байт с искомым из строки "today-temp", лишь-бы они повторно не встречались до тега с нужной позиции с температурой. И хоть просто по смешению от них брать число температуры.

Для второго варианта вам уже потребуется определять код ответа сервера - разбирать протокол http...

Третьего варианта в Arduino для малых WiFi-SoC не встречается. Это возможно на Linux системах с PHP, Питоном, или ещё чаго.
 
Я думаю первого варианта для меня пока хватит.
Хочется понять алгоритм работы кода .
today-temp в коде страницы встречается всего один раз.
 

pvvx

Активный участник сообщества
Я думаю первого варианта для меня пока хватит.
Хочется понять алгоритм работы кода .
Ну тогда там нечего писать.
Можно простейшим вариантом:
1) читаем побайтно, пока не встретим к примеру символ "<"
2) встретив "<" читаем в буфер до ">" или по ограничению размера буфера для строки '<... "today-temp">'
ищем в буфере 'today-temp'
если не нашли - на п.п.1
если нашли - считываем следующие символы - это и будет температура.
 

pvvx

Активный участник сообщества
Код:
#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>

#include <myAP.h>
//char ssid[] = "";       // your network SSID (name)
//char password[] = "";  // your network key

WiFiClientSecure client;

void setup() {
  Serial.begin(115200);
  WiFi.mode(WIFI_STA);
  WiFi.disconnect();
  delay(100);
  Serial.print("Connecting Wifi: ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
  }
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  IPAddress ip = WiFi.localIP();
  Serial.println(ip);
}

char host[] = "sinoptik.com.ru";
char id_txt[] = "<p class=\"today-temp\">";
int tmp;

int get_tmp(void) {
  char buf[16];
  int i = 0;
  while (client.available()) {
    if (id_txt[i] == client.read()) {
      i++;
      if (i == sizeof(id_txt) - 1) {
        client.read((uint8_t *)buf, sizeof(buf) - 1);
        buf[sizeof(buf) - 1] = 0;
        tmp = atoi(buf);
        return 1;
      }
    }
    else i = 0;
  }
  return 0;
}

void loop() {
  if (client.connect(host, 443)) {
    Serial.println("Connected...");
    client.println("GET / HTTP/1.1");
    client.print("Host: "); client.println(host);
    client.println("User-Agent: arduino/1.0");
    client.println("");
    delay(1000);
    if (get_tmp()) {
      Serial.print("today-temp = ");
      Serial.println(tmp);
    }
    else Serial.println("Error!");
    client.stop();
  }
  // ....
  while(1) delay(10000);
}
Код:
Connecting Wifi: ****
.......
WiFi connected
IP address: 
192.168.1.225
Connected...
today-temp = 6
 
Спасибо большое. У меня тоже получилось , но правда в основном через if и if(string1.equals(string2)) . Но такое в приличном месте показывать нельзя.
И последний вопрос .
Если вводить sinoptik.com.ru - то коннектится.
А если на сайте выбираешь другой город и вставляешь в код строку с браузера , то уже коннектится не хочет .
sinoptik.com.ru/%D0%BF%D0%BE%D0%B3%D0%BE%D0%B4%D0%B0-%D0%BB%D0%BE%D0%BD%D0%B4%D0%BE%D0%BD
В чем может быть причина ? Или это не та строка ?
 

pvvx

Активный участник сообщества
Если вводить sinoptik.com.ru - то коннектится.
А если на сайте выбираешь другой город и вставляешь в код строку с браузера , то уже коннектится не хочет .
sinoptik.com.ru/%D0%BF%D0%BE%D0%B3%D0%BE%D0%B4%D0%B0-%D0%BB%D0%BE%D0%BD%D0%B4%D0%BE%D0%BD
В чем может быть причина ? Или это не та строка ?
Это вопрос к сайту. Какое они хотят оформление страниц такое и делают... Считывать значение температур со старниц, которые могут меняться каждый день как-то не очень. Там надо уже ИИ с распознаванием... :)
Более стабильно считывать с информеров SINOPTIK: Информер погоды, красивый погодный информер на сайт. Виджет погоды для сайта
 

Алексей.

Active member
Для сайта он отдает полтора килограмма html кода :)
Код:
curl -v -L 'https://sinoptik.com.ru/informers_js.php?lang=en&cities=100524901'
*   Trying 212.42.76.150...
* Connected to sinoptik.com.ru (212.42.76.150) port 443 (#0)
* found 148 certificates in /etc/ssl/certs/ca-certificates.crt
* found 597 certificates in /etc/ssl/certs
* ALPN, offering http/1.1
* SSL connection using TLS1.2 / ECDHE_RSA_AES_256_GCM_SHA384
*     server certificate verification OK
*     server certificate status verification SKIPPED
*     common name: sinoptik.uk (matched)
*     server certificate expiration date OK
*     server certificate activation date OK
*     certificate public key: RSA
*     certificate version: #3
*     subject: OU=Domain Control Validated,OU=PositiveSSL Multi-Domain,CN=sinoptik.uk
*     start date: Mon, 06 Nov 2017 00:00:00 GMT
*     expire date: Tue, 06 Nov 2018 23:59:59 GMT
*     issuer: C=GB,ST=Greater Manchester,L=Salford,O=COMODO CA Limited,CN=COMODO RSA Domain Validation Secure Server CA
*     compression: NULL
* ALPN, server accepted to use http/1.1
> GET /informers_js.php?lang=en&cities=100524901 HTTP/1.1
> Host: sinoptik.com.ru
> User-Agent: curl/7.47.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Server: nginx
< Date: Thu, 26 Apr 2018 07:57:08 GMT
< Content-Type: application/json
< Transfer-Encoding: chunked
< Connection: keep-alive
< Set-Cookie: os=UNKNOWN; path=/
< X-Powered-By: PHP/5.5.38
< Expires: 0
< Cache-Control: must-revalidate, post-check=0, pre-check=0
< Pragma: no-store, no-cache, must-revalidate
< Vary: Accept-Encoding
< X-Server-By: sinfe1
<
var siCss=document.createElement('link');siCss.setAttribute('rel','stylesheet');siCss.setAttribute('type','text/css');siCss.setAttribute('href','//sinst.fwdcdn.com/css/informers2.css?v=1');document.getElementsByTagName('head')[0].appendChild(siCss);function siClickCount(){var siCount=document.createElement('script');siCount.setAttribute('type','text/javascript');siCount.setAttribute('src','//sinoptik.com.ru/click/informers/ru.html?rnd='+new Date().valueOf());document.getElementsByTagName('head')[0].appendChild(siCount);}function LoadInformer(data){if(document.getElementById('siHeader')){document.getElementById('siHeader').innerHTML=data.date};for(var i=0;i< data.body.length;i++){if(data.body[i]!=null){if(document.getElementById('siT'+i)){document.getElementById('siT'+i).innerHTML=data.body[i].temp};if(document.getElementById('weatherIco'+i)){document.getElementById('weatherIco'+i).className='weatherIco '+data.body[i].img};if(document.getElementById('vl'+i)){document.getElementById('vl'+i).innerHTML=data.body[* Connection #0 to host sinoptik.com.ru left intact
i].rh};if(document.getElementById('dav'+i)){document.getElementById('dav'+i).innerHTML=data.body[i].p};if(document.getElementById('wind'+i)){document.getElementById('wind'+i).innerHTML=data.body[i].ws};}}document.getElementById('SinoptikInformer').style.display='block';}LoadInformer( {date:'26.04.18, morning', body:[{"temp":"+11&deg;","wt":null,"ws":"4.8 , <span class=\"wind wind-S\" title=\"south\"><\/span>","p":"734 ","rh":"88%","img":"d430"}]} )
полезное из него только в самом конце
body:[{"temp":"+11&deg;","wt":null,"ws":"4.8 , <span class=\"wind wind-S\" title=\"south\"><\/span>","p":"734 ","rh":"88%","img":"d430"}]} )
 
Сверху Снизу