Compare commits

..

No commits in common. "stable" and "1.0.0" have entirely different histories.

12 changed files with 30 additions and 188 deletions

View File

@ -1,43 +1,2 @@
# Parser of products from [rossko.ru](https://krsk.rossko.ru)
# parser_from_rossko
* Saves products from an excel file with products sent to email from [rossko.ru](https://krsk.rossko.ru) in SQlite3
* Downloads images directly from the [rossko.ru](https://krsk.rossko.ru) website for all products
* Generates excel documents formatted for the [drom.ru](https://drom.ru) and [avito](https://avito.ru) trading platforms with the added reseller markup
## Installation
### NGINX
1. Example of NGINX server file
```nginx
location / {
try_files $uri $uri/ /index.php;
}
# Excel-files
location ~ /(?<type>drom|avito)(?<file>/avaiable|/order)?$ {
root /var/www/parser_from_rossko/mirzaev/parser_from_rossko/system/storage/$type$file;
add_header Content-Disposition "attachment; filename=$type.xlsx";
try_files /export.xlsx =404;
}
# Images
location ~ /(?<nomenclature>[A-z0-9]+)/(?<image>[0-9]+\.[jJ][pP][gG])$ {
root /var/www/parser_from_rossko/mirzaev/parser_from_rossko/system/storage/images/$nomenclature;
add_header Content-Disposition "attachment; filename=$image";
try_files /$image =404;
}
location ~ \.php$ {
...
}
```
2. Issue yourself an SSL/TLS certificate using Certbot: `sudo certbot --nginx`
### SystemD (or any alternative you like)
1. Execute: `sudo cp rossko.service /etc/systemd/system/rossko.service`
*before you execute the command think about **what it does** and whether the **paths** are specified correctly*<br>
*the configuration file is very simple and you can remake it for any alternative to SystemD that you like*

View File

@ -241,11 +241,9 @@ while ($product = $products->fetchArray()) {
Пункт выдачи находится в г.Красноярске по адресу Дудинская 2Б
Часы работы: 10:00-19:00
Отправка запчастей и деталей по всей России.
Не является публичной офертой
TXT,
(int) ($product['cost_rossko'] + ($product['cost_rossko'] * 0.21)),
implode('|', $images),
(int) ($product['cost_rossko'] + ($product['cost_rossko'] * 0.23)),
implode(' ', $images),
'Новое',
'Оригинал',
'Красноярск, Дудинская улица, 2Б',

View File

@ -32,22 +32,20 @@ $db = new db(STORAGE . DIRECTORY_SEPARATOR . 'products.db');
// Инициализация товаров
$products = $db->query('SELECT * FROM product;');
// Инициализация директории со всем, что связано с Drom
// Инициализация директории с документом Drom
define('DROM', STORAGE . DIRECTORY_SEPARATOR . 'drom');
// Инициализация хранилища фотографий товаров
define('IMAGES', STORAGE . DIRECTORY_SEPARATOR . 'images');
// Инициализация таблиц
$spreadsheet_avaiable = excel::create(['export']);
$spreadsheet_order = excel::create(['export']);
// Инициализация таблицы
$spreadsheet = excel::create(['export']);
// Инициализация рабочих листов
$worksheet_avaiable = $spreadsheet_avaiable->sheet();
$worksheet_order = $spreadsheet_order->sheet();
// Инициализация рабочего листа
$worksheet = $spreadsheet->sheet();
// Инициализация заголовков
$headers = [
$worksheet->writeHeader([
'Артикул',
'Наименование товара',
'Новый или б/у',
@ -70,9 +68,7 @@ $headers = [
'Наличие',
'Сроки доставки',
'Фотография'
];
$worksheet_avaiable->writeHeader($headers);
$worksheet_order->writeHeader($headers);
]);
while ($product = $products->fetchArray()) {
// Перебор товаров
@ -127,11 +123,8 @@ while ($product = $products->fetchArray()) {
// Форматирование названия
$product['description'] = trim(preg_replace('/\|.*/', '', $product['description']), ' ');
// Товар в наличии? (доставка 2 часа)
$avaiable = $product['delivery'] === 0 && $product['amount'] > 0;
// Генерация строки
$row = [
// Запись строки
$worksheet->writeRow([
$product['code'],
$product['description'],
'Новый',
@ -148,19 +141,14 @@ while ($product = $products->fetchArray()) {
'',
'',
'',
'По запчастям уточняйте наличие и цену по телефону или через кнопку "спросить", ТАК КАК ОН МОЖЕТ БЫТЬ ПРОДАН В ТЕЧЕНИИ ДНЯ ИЛИ НАХОДИТЬСЯ В РЕЗЕРВЕ, часть запчастей находится на складе, на перемещение может потребоваться от 2 часов. Не является публичной офертой',
$product['amount'],
(int) ($product['cost_rossko'] + ($product['cost_rossko'] * 0.21)),
$avaiable ? 'В наличии' : 'Под заказ',
$product['delivery'] === 0 ? '2 часа' : $product['delivery'],
'По запчастям уточняйте наличие по телефону или через кнопку "спросить", ТАК КАК ОН МОЖЕТ БЫТЬ ПРОДАН В ТЕЧЕНИИ ДНЯ ИЛИ НАХОДИТЬСЯ В РЕЗЕРВЕ, часть запчастей находится на складе, на перемещение может потребоваться от 2 часов',
rand(1, 6),
(int) ($product['cost_rossko'] + ($product['cost_rossko'] * 0.23)),
'В наличии',
1,
implode(' ', $images)
];
// Запись строки в документ
if ($avaiable) $worksheet_avaiable->writeRow($row);
else $worksheet_order->writeRow($row);
]);
}
// Сохранение файлов
$spreadsheet_avaiable->save(DROM . DIRECTORY_SEPARATOR . 'avaiable' . DIRECTORY_SEPARATOR . 'export.xlsx');
$spreadsheet_order->save(DROM . DIRECTORY_SEPARATOR . 'order' . DIRECTORY_SEPARATOR . 'export.xlsx');
// Сохранение файла
$spreadsheet->save(DROM . DIRECTORY_SEPARATOR . 'export.xlsx');

View File

@ -141,7 +141,7 @@ if (!empty($document) ?? file_exists($document)) {
$response = $client->send($request);
// Инициализация изображений
$images = json_decode((string) $response->getBody(), true)['mainPart']['images'] ?? null;
$images = json_decode((string) $response->getBody(), true)['mainPart']['images'];
foreach ($images ?? [] as $image) {
// Перебор изображений

View File

@ -1,95 +0,0 @@
<?php
/*
declare(strict_types=1);
namespace mirzaev\parser_from_rossko;
use GuzzleHttp\Client as client,
GuzzleHttp\Psr7\Request as request;
use DOMDocument as dom,
DOMXPath as xpath;
ini_set('error_reporting', E_ALL);
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
define('VIEWS', realpath('..' . DIRECTORY_SEPARATOR . 'views'));
define('STORAGE', realpath('..' . DIRECTORY_SEPARATOR . 'storage'));
define('INDEX', __DIR__);
// Автозагрузка
require __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php';
// Инициализация клиента Guzzle
$client = new client(['cookies' => true]);
function auth(int $attempts = 5)
{
global $client;
if (--$attempts <= 0) return false;
$request = new request('GET', 'https://krsk.rossko.ru/');
return $client->sendAsync($request)
->then(function ($response) {
$dom = new dom;
@$dom->loadHTML((string) $response->getBody());
$xpath = new xpath($dom);
// Кнопка "ВХОД" ('ul[class="header-top__menu-inner"] > li:nth-child(3)')
$entries = $xpath->query('/html/body/div[1]/header/div[2]/div/div/nav/ul/li[5]/div/a/span');
if (!empty($entries[0])) {
// Аутентифицирован
echo 'Аутентифицирован: ' . $entries[0]->textContent . "\n";
return false;
} else {
// Не аутентиффицирован
// Кнопка "ВХОД" ('ul[class="header-top__menu-inner"] > li:nth-child(3)')
$entries = $xpath->query('/html/body/div[1]/header/div[2]/div[1]/div/nav/ul/li[3]/div/a/span');
return $entries[0]->textContent === 'Вход';
}
})
->then(function ($guest) use ($attempts, $client) {
if ($guest) {
// Не аутентифицирован
echo "Не аутентифицирован\n";
// Инициализация данных аккаунта [mail => '', password => '']
$account = require(__DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'settings' . DIRECTORY_SEPARATOR . 'rossko.php');
// Инициализация запроса для аутентификации
$request = new request(
'POST',
'https://krsk.rossko.ru/utils/',
[
'Content-Type' => 'application/x-www-form-urlencoded; charset=UTF-8'
],
'auth%5Bemail%5D=' . urlencode($account['mail']) . '&auth%5Bpassword%5D=' . urlencode($account['password']) . '&action=auth&type=header'
);
$promise = $client->sendAsync($request)->then(function ($response) use ($attempts) {
auth($attempts);
});
$promise->wait();
} else {
// Аутентифицирован (подразумевается) !!! могут быть ошибки
return true;
}
});
}
// Аутентификация (проверяет или аутентифицирует)
auth()->wait();
echo (123); */

View File

@ -0,0 +1,8 @@
<?php
return [
'endpoint' => 'unix:///var/run/arangodb3/arango.sock',
'database' => 'parser_from_rossko',
'name' => 'parser_from_rossko',
'password' => ''
];

View File

@ -1,6 +0,0 @@
<?php
return [
'mail' => '@gmail.com',
'password' => ''
];

View File

@ -1,2 +1 @@
!.gitignore
products.db
images

View File

@ -1,2 +0,0 @@
!.gitignore
/*

View File

@ -1,3 +0,0 @@
!.gitignore
/avaiable/*
/order/*

View File

@ -1,2 +0,0 @@
!.gitignore
/*

View File

@ -1,2 +0,0 @@
!.gitignore
/*