Разработка JS парсера с сохранением результата в SQLite

Разработка JS парсера с сохранением результата в SQLite

Метки:
  1. Support Денис
    Начиная с версии 1.2.152 в A-Parser появилась возможность работать с БД SQLite.
    В данной статье мы рассмотрим разработку JavaScript парсера, который будет парсить курсы валют из сайта finance.i.ua и сохранять их в БД, если там этих записей нет, либо обновлять существующие записи.

    Идентификатор подключения к бд сделаем константой и присвоим ей значение перед описанием класса.
    Код:
    const db = 'results/myexchange.sqlite';
    В парсере будет две переменных в результате:
    1. текущий курс доллара в украинских гривнах (USD_UA)
    2. текущий курс евро в украинских гривнах (EUR_UA)
    Обьявление этих переменных будет выглядеть следующим образом:
    Код:
    results: {
         flat: [
              ['USD_UA', 'USD finance.i.ua'],
              ['EUR_UA', 'EUR finance.i.ua'],
          ]
    },
    Начнем с описания метода init, в котором будут создаваться таблицы если их нет, а также если таблица currencies пустая, то заполнять её.
    Код:
     /*Если в бд нет таблиц, то создаем их, также если в таблице  currencies нет записей то добавляем их*/
        init() {
            tools.sqlite.run(db, `CREATE TABLE IF NOT EXISTS currencies(
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                name varchar(50)
            )`);
    
            tools.sqlite.run(db, `CREATE TABLE IF NOT EXISTS exchange_rates(
              id INTEGER PRIMARY KEY AUTOINCREMENT,
              rate FLOAT NOT NULL,
              currency_id INTEGER
            )`);
    
            if(!tools.sqlite.get(db, 'SELECT COUNT(*) AS count FROM currencies').count) {
                tools.sqlite.run(db, 'INSERT INTO currencies(name) VALUES("USD"), ("EUR")');
            };
        }
    
       
    Теперь напишем метод, который будет делать запрос, выбирать из тела страницы интересующую нас информацию и возращать эти данные в хеше.
    Код:
    /*метод собирающий курс доллара и  евро с сайта*/
        *getFinanceIUa(currencies) {
            let rates = {};
    
            let response = yield this.request('GET', 'https://finance.i.ua/converter/', {}, {
                check_content: ['<\/html>'],
                decode: 'auto-html',
            });
    
            if (response.success) {
                for(const currency of currencies) {
                    const regex = new RegExp(`"${currency}":\\{"buy":(.*?),`);
                    const matches = response.data.match(regex);
                    if(matches) {
                        rates[currency] = matches[1];
                    };
                };
                return rates;
            }
    
            return false;
        }
    
    
    Сама база данных будет состоять из двух таблиц:
    1. currencies в которой будут храниться виды валют
    2. exchange_rates в которой будут храниться курсы валют
    Следующим шагом будет описание метода, который возвращает строку записи из таблицы курсов exchange_rates, или false, если такой записи нет. Принимать в качестве параметра он будет id валюты.
    Код:
     /*метод который  ищет по таблице exhange_rates есть ли запись для такой валюты*/
        getCurrencyExchangeId(db, currency_id) {
            const result = tools.sqlite.get(db, 'SELECT id FROM exchange_rates WHERE currency_id = ?', currency_id);
            if (result) {
                return result.id;
            }
            return false;
        }
    
    И в завершение, опишем в методе parse логику работы нашего парсера. В зависимости от наличия записи о данной валюте в таблице либо обновляем значение, либо добавляем новое.
    Код:
    *parse(set, results) {
            /*получаем массив валют*/
            const currencies = tools.sqlite.all(db, 'SELECT * FROM currencies');
            /*получаем данные по этим валютам с сайта*/
            const rates = yield* this.getFinanceIUa(currencies.map(el => el.name));
            if(rates) {
                results.success = 1;
                /*перебираем в цикле массив валют и в каждом витке цикла либо обновляем значение в таблице, либо добавляем если такого значения нет*/
                for(const currency of currencies) {
                    const id = this.getCurrencyExchangeId(db, currency.id);
                    if(id) {
                        tools.sqlite.run(db, 'UPDATE exchange_rates SET rate = ? WHERE id = ?', rates[currency.name], id);
                    }
                    else {
                        tools.sqlite.run(db, 'INSERT INTO exchange_rates(currency_id, rate) values(?, ?)', currency.id, rates[currency.name]);
                    };
                  
                    results[currency.name + '_UA'] = rates[currency.name];
                };
            };
    
            return results;
        }
        
    Пресет с уже готовым парсером опубликован в Каталоге по этой ссылке.