Получение данных с сайта

funkyby
Offline
Зарегистрирован: 10.01.2018

Доброго дня, делаю сейча на NodeMCU мини проектик, задача, подключаемся к wifi затем стучимся на сайт по урлу и спрашиваем сколько пользователей зарегистрировано на сайте, получаем ответ распаршиваем нужную цифру и выводим на дисплей 1602.

Вопрос вот в чем, к сети подключили по урлу стукнулись и получили информацию с сайта, только получили мы ее с мусором, т.е. помимо цифры нужно получаем еще ответ сервера и прочий мусор, как распарсить и вытащить именно цифру?

funkyby
Offline
Зарегистрирован: 10.01.2018

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

 

#include <LiquidCrystal.h>
#include <FastIO.h>
#include <I2CIO.h>
#include <LCD.h>
#include <LiquidCrystal_SR.h>
#include <LiquidCrystal_I2C.h>
#include <LiquidCrystal_SR3W.h>
#include <LiquidCrystal_SR2W.h>
#include <Wire.h>  
#include <LiquidCrystal_I2C.h> // Using version 1.2.1
 // The LCD constructor - address shown is 0x27 - may or may not be correct for yours
// Also based on YWRobot LCM1602 IIC V1
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  
 
#include <ESP8266WiFi.h>
 
const char* ssid     = "0000АА03";
const char* password = "32112А36DYT6";
 
const char* host = "domain.com";
// Ключи на будущее что бы запрашивать по ним данные
const char* streamId   = "";
const char* privateKey = "key";
 
void setup() {
  Serial.begin(115200);
  delay(10);
{
  lcd.begin(16,2); // sixteen characters across - 2 lines
  lcd.backlight();
  // first character - 1st line
  lcd.setCursor(0,0);
  lcd.print("Thedomain.com");
  // 8th character - 2nd line 
  lcd.setCursor(0,1);
  lcd.print("USERS COUNTER");
}
  // We start by connecting to a WiFi network
 
  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  lcd.setCursor(0,0);
  lcd.print("Connecting to ");
  Serial.println(ssid);
  lcd.setCursor(0,1);
  lcd.println(ssid);
  
  WiFi.begin(ssid, password);
  
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
 
  Serial.println("");
  Serial.println("WiFi connected");  
  Serial.println("IP address: ");
  lcd.setCursor(0,0);
  lcd.println("IP address: ");
  Serial.println(WiFi.localIP());
  lcd.setCursor(0,1);
  lcd.println(WiFi.localIP());
}
 
int value = 0;
 
void loop() {
  delay(50000);
  ++value;
 
  Serial.print("connecting to ");
  Serial.println(host);
  
  // Use WiFiClient class to create TCP connections
  WiFiClient client;
  const int httpPort = 80;
  if (!client.connect(host, httpPort)) {
    Serial.println("connection failed");
    return;
  }
  
  // We now create a URI for the request
  String url = "/11/";
 
    // This will send the request to the server
  client.print(String("GET ") + url + " HTTP/1.1\r\n" +
               "Host: " + host + "\r\n" + 
               "Connection: close\r\n\r\n");
  unsigned long timeout = millis();
  while (client.available() == 0) {
    if (millis() - timeout > 50000) {
      Serial.println(">>> Client Timeout !");
      client.stop();
      return;
    }
  }
  
  // Read all the lines of the reply from server and print them to Serial
  while(client.available()){
    String line = client.readStringUntil('|');
    Serial.print(line);
      lcd.setCursor(0,0);
  lcd.print("TOTAL  | DAY  | HR");
    lcd.setCursor(0,1);
  lcd.print(line);
  }
  
  Serial.println();
  Serial.println("closing connection");
}
 
DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

funkyby пишет:

Вопрос вот в чем, к сети подключили по урлу стукнулись и получили информацию с сайта, только получили мы ее с мусором, т.е. помимо цифры нужно получаем еще ответ сервера и прочий мусор, как распарсить и вытащить именно цифру?

Называть служебные заголовки HTTP мусором - это надо сильно умудриться.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ну, Вы же сами написали что делать:

funkyby пишет:

1. подключаемся к wifi
2. затем стучимся на сайт по урлу
3. и спрашиваем сколько пользователей зарегистрировано на сайте,
4. получаем ответ
5. распаршиваем нужную цифру
6. и выводим на дисплей 1602.

А на деле п. 5 пропустили. Сделайте его и всё будет окей.

funkyby
Offline
Зарегистрирован: 10.01.2018

ЕвгенийП пишет:

Ну, Вы же сами написали что делать:

funkyby пишет:

1. подключаемся к wifi
2. затем стучимся на сайт по урлу
3. и спрашиваем сколько пользователей зарегистрировано на сайте,
4. получаем ответ
5. распаршиваем нужную цифру
6. и выводим на дисплей 1602.

А на деле п. 5 пропустили. Сделайте его и всё будет окей.

Это понятно я для того и написал сюда, может кто сбросит пример распарсинга страницы и отлавливания нужной информации из нее, вчера на ночь глядя ничего дельного не нагуглил, как правило люди наоборот Ардуина передает данные, а мне просто забрать число, я думал уже в XML завернуть и его парсить если будет быстрее, но что-то тоже дельного не нагуглил )

Penni
Penni аватар
Offline
Зарегистрирован: 18.01.2015

Если для своего сайта делаете, то проще скриптик php оформить который будет возвращать только нужное число без всяких там обрамлений.

funkyby
Offline
Зарегистрирован: 10.01.2018

Penni пишет:

Если для своего сайта делаете, то проще скриптик php оформить который будет возвращать только нужное число без всяких там обрамлений.

Это служебные заголовки, они по любому будут, так браузер общается с сервером, сейчас там отдается одна голая цифра, вот ее и хотелось бы спарсить, в планах получать 3 параметра (Всего пользователей, за день, за час) и бипер прикрутить на регистрацию пользователя, это проект для стартапа, что бы мотивировать команду, когда кто-то регистрируется на сайте мы получаем бип и статистику на экране в любое время суток по росту аудитории.

Nosferatu
Offline
Зарегистрирован: 04.11.2012

Огласите весь список пожалуйста ©, из чего нужно вылавливать цифру, дабы узреть точку опоры. Ибо если нету точки опоры надо её создать, в виде уникального кода, перед требуемой вам цифрой.

sadman41
Offline
Зарегистрирован: 19.10.2016

У nodeMCU памяти до дури, вроде? Тогда самое дешевое решение, на мой взгляд: http://blog.benoitblanchon.fr/arduino-json-v4-0/

 

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Короче, ребята: мы просто хотим погуглить готовое решение, как обычно :) Мы не хотим просто взять, и прочитать самые основы протокола HTTP, чтобы понять, что данные собственно ответа начинаются с двойного перевода строки. Реалии двадцать первого века - вся надежда, что кто-то уже сделал за нас :)

sadman41
Offline
Зарегистрирован: 19.10.2016

Ну так человек сразу написал, что ему попроще надо. Попроще - это ловить тело страницы и кидать его в JSON parser.

Если хотите, то можете в тысячный раз объяснять как парсить строку крафтовыми саброутинами, любовно изготовленными на кристально честном Си, но, думаю, в данном случае это не имеет ни малейшего смысла.

b707
Offline
Зарегистрирован: 26.05.2017

sadman41 пишет:

Ну так человек сразу написал, что ему попроще надо. Попроще - это ловить тело страницы и кидать его в JSON parser.

 

Садман, ну зачем здесь JSON. Раз страница принадлежит автору, самое простое решение - вставить в ответ сервера уникальные строки. Типа "Number of registered users = " .

И тогда все просто как дважды-два:

- читаем строку из ответа

- если строка начинается с "Number of registered users = " - извлекаем число после знака равенства

- если строка другая - отбрасываем

Весь код наверняка в десять строк уложится без всякого JSON

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

 

sadman41
Offline
Зарегистрирован: 19.10.2016

Потому что на бэкенде с JSON как-то постандартней. Есть стандартные средства генерации, есть  валидаторы, перспектива расширения. В конце-концов там может быть и стандартное API, в котором уже всё есть и отдающее JSON-ом, как нынче модно.

На стороне нодемцу - это копипаст в код с изменением JSON-ключей. И потом какие угодно поля там бери, складывай, перемножай. С обычной 328-й еще бы стоило писать деревянный, нерасширябельный код. А тут, когда памяти много - не вижу никакого смысла. Разве что в качестве тренировки.

Впрочем, я же не заставляю его брать именно этот вариант.

b707
Offline
Зарегистрирован: 26.05.2017

sadman41 пишет:

Потому что на бэкенде с JSON как-то постандартней. Есть стандартные средства генерации, есть  валидаторы, перспектива расширения. В конце-концов там может быть и стандартное API, в котором уже всё есть и отдающее JSON-ом, как нынче модно.

ну кому что, как говорится... Я на ПК парсеры сам пишу, "на честном перле". Годами устойчиво работают на чужих сайтах. Вот, к примеру, 2 года собирал статистику о билетах в испанские музеи из скрытых полей сайта Ticketmaster.es

sadman41
Offline
Зарегистрирован: 19.10.2016

В перловых JSON парсерах XS обставляет PP ;) Конечно это не так заметно на малых деревьях и нечастых вызовах, да и вообще есть множество влияющих факторов. Впрочем, это уже вопросы для другого форума.

b707
Offline
Зарегистрирован: 26.05.2017

sadman41 пишет:

В перловых JSON парсерах XS обставляет PP ;) Конечно это не так заметно на малых деревьях и нечастых вызовах, да и вообще есть множество влияющих факторов. Впрочем, это уже вопросы для другого форума.

вы не поняли, я парсю сайты голым перлом, через регеспы, без JSON-a :)

или я не понял. что вы имели в виду?

sadman41
Offline
Зарегистрирован: 19.10.2016

b707 пишет:

или я не понял. что вы имели в виду?

Может и не поняли - откуда ж мне знать...

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

Penni
Penni аватар
Offline
Зарегистрирован: 18.01.2015

Вот стандартный пример ESP8266 Arduino IDE

/**
 * BasicHTTPClient.ino
 *
 *  Created on: 24.05.2015
 *
 */

#include <Arduino.h>

#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>

#include <ESP8266HTTPClient.h>

#define USE_SERIAL Serial

ESP8266WiFiMulti WiFiMulti;

void setup() {

    USE_SERIAL.begin(115200);
   // USE_SERIAL.setDebugOutput(true);

    USE_SERIAL.println();
    USE_SERIAL.println();
    USE_SERIAL.println();

    for(uint8_t t = 4; t > 0; t--) {
        USE_SERIAL.printf("[SETUP] WAIT %d...\n", t);
        USE_SERIAL.flush();
        delay(1000);
    }

    WiFiMulti.addAP("SSID", "PASSWORD");

}

void loop() {
    // wait for WiFi connection
    if((WiFiMulti.run() == WL_CONNECTED)) {

        HTTPClient http;

        USE_SERIAL.print("[HTTP] begin...\n");
        // configure traged server and url
        //http.begin("https://192.168.1.12/test.html", "7a 9c f4 db 40 d3 62 5a 6e 21 bc 5c cc 66 c8 3e a1 45 59 38"); //HTTPS
        http.begin("http://192.168.1.12/test.html"); //HTTP

        USE_SERIAL.print("[HTTP] GET...\n");
        // start connection and send HTTP header
        int httpCode = http.GET();

        // httpCode will be negative on error
        if(httpCode > 0) {
            // HTTP header has been send and Server response header has been handled
            USE_SERIAL.printf("[HTTP] GET... code: %d\n", httpCode);

            // file found at server
            if(httpCode == HTTP_CODE_OK) {
                String payload = http.getString();
                USE_SERIAL.println(payload);
            }
        } else {
            USE_SERIAL.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
        }

        http.end();
    }

    delay(10000);
}

Если запросить какой-нибудь my.php вида

<?php
  echo "100"
?>

то в payload вы получите 100 без всякого мусора.

Ну а если вы хотите парсить громоздкие страницы то советов вам уже понадавали.

funkyby
Offline
Зарегистрирован: 10.01.2018
<?php
2   echo "100"
3 ?>

К сожалению это не поможет, все равно есть заголовки, но вот идея про два перевода строки мне понравилась, сейчас попробую отследить.

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

funkyby пишет:

 но вот идея про два перевода строки мне понравилась

Идея про два перевода строки - это не идея, это стандарт протокола HTTP :)

Lion777
Offline
Зарегистрирован: 20.05.2016

что там отслеживать, идут заголовки далее они отделяются \r\n\r\n и сама страница и дальше рабираете данные.

funkyby
Offline
Зарегистрирован: 10.01.2018

DIYMan пишет:

funkyby пишет:

 но вот идея про два перевода строки мне понравилась

Идея про два перевода строки - это не идея, это стандарт протокола HTTP :)

я просто об этом даже не подумал что-то только не думал, хотел считать символы, хотел распаршивать, хотел переносы считать, а до самого очевидного не додумался )

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

funkyby пишет:
до самого очевидного не додумался )

А стандарт почитать Клапауций запретил

funkyby
Offline
Зарегистрирован: 10.01.2018

Да кстати, вот так выглядит получаемая информация со страницы даже при пустом файле с цифрой, даже при echo 100 и т.д.

connecting to domain.com
HTTP/1.1 200 OK
Server: nginx/1.0.15
Date: Wed, 10 Jan 2018 20:12:34 GMT
Content-Type: text/html
Connection: close
X-Powered-By: PHP/5.4.45
Vary: Accept-Encoding,User-Agent
Content-Length: 3
 
100
closing connection
т.е. получили хидеры, получили цифру и закрыли конект
funkyby
Offline
Зарегистрирован: 10.01.2018

Ворота пишет:

funkyby пишет:
до самого очевидного не додумался )

А стандарт почитать Клапауций запретил

я же рукожоп начинающий, я только начинаю ковырять ардуинку, до этого если писал что-то на си и подобных то в универе, а сейчас после работы вечерами ковыряю разные игрушки с китая для общего развития, я больше по вебу, для него собственно и делается задумка для отслеживания конверсии объявлений и мотивации команды )

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Ворота пишет:

funkyby пишет:
до самого очевидного не додумался )

А стандарт почитать Клапауций запретил

Да, Клапа это может одной силой мысли, он такой :)

funkyby
Offline
Зарегистрирован: 10.01.2018

funkyby
Offline
Зарегистрирован: 10.01.2018

Немного костыльно но получилось, обрезал readStringUntil('\r\n\r\n'); и дополнил исходник большим количеством данных и сейчас выводится все гут, единсвтенное во время обновления информации с сайта пробегает лишняя информация на дисплее но на 1 секунду, а потом выводятся нужные цифры.

funkyby
Offline
Зарегистрирован: 10.01.2018

Спасибо за помощь, пойду читать как распаршивать данные т.е. как вообще вырезать все лишнее, оставив только нужные цифры.

Voodoo Doll
Voodoo Doll аватар
Offline
Зарегистрирован: 18.09.2016

funkyby, вот здесь почитайте. Масса полезного.

funkyby
Offline
Зарегистрирован: 10.01.2018

Voodoo Doll пишет:

funkyby, вот здесь почитайте. Масса полезного.

ага спасибо, там пост не совсем про то, но в комментах много дельного.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

funkyby пишет:
делается задумка для отслеживания конверсии объявлений и мотивации команды )

А ардуина-то зачем? Почему обычный компьютер не может это отслеживать?

funkyby
Offline
Зарегистрирован: 10.01.2018

ЕвгенийП пишет:

funkyby пишет:
делается задумка для отслеживания конверсии объявлений и мотивации команды )

А ардуина-то зачем? Почему обычный компьютер не может это отслеживать?

Может, но отдельное устройство во первых интереснее сделать чем скрипт сбора информации, во вторых всю стату можно видеть не включая компьютер или телефон, просто сразу. В третьих скрипт подробной аналитики удет в вебе, а тут только вывод ключевых параметров развиитя проекта для мотивации. Можно конечно заморочиться, взять комп, купить телик на стену, купить chromecast и транслировать на телик ключевые показатели чреез приложение, но это уже уровень покруче, для проектов с хорошими деньгами, да и есть уже готовые решения, а хотелось бы самому поковыряться.