Recommended Posts

6/ Появилась необходимость авторизоваться в своём аккаунте через php для парсинга нужных мне данных из сайта opencarforum
Код работает у меня на open server 5.2.2, может кому-то пригодиться для написания своего модуля и т.д.:

Скрытый текст

В корне каталога домена создать файл index.php с кодом и ввести логин и пароль в неём:


<?php
// Log in to Google account and go to account page
$site_login = 'https://opencartforum.com/login/';
$user_agent = 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:49.0) Gecko/20100101 Firefox/49.0';
//$csrfKey = '21bd4226b66a3bd1abba64f4c5a87d51';
$USERNAME = 'user@opencart.pro'; // логин
$PASSWORD = '123456'; // пароль
$remember_me = 1;
$anonymous = 0;
$processLogin = 'usernamepassword';
$COOKIEFILE = 'cookies.txt';

// initialize curl handle used for all requests
$ch = curl_init($site_login);

// set some options on the handle
curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
curl_setopt($ch, CURLOPT_MAXREDIRS, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_COOKIEJAR, $COOKIEFILE);
curl_setopt($ch, CURLOPT_COOKIEFILE, $COOKIEFILE);
curl_setopt($ch, CURLOPT_HEADER, 0);  
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_URL, $site_login);

$data = curl_exec($ch);
//$data = file_get_contents($site_login);
//$data = curl_exec_follow($ch);

// extract form fields from account login page
$formFields = getFormFields($data);

// inject email and password into form
$formFields['csrfKey'] = $formFields['csrfKey'];
$formFields['auth']  = $USERNAME;
$formFields['password'] = $PASSWORD;
$formFields['remember_me'] = $remember_me;
$formFields['anonymous'] = $anonymous;
$formFields['_processLogin'] = $processLogin;

$post_string = http_build_query($formFields, null, '&', PHP_QUERY_RFC3986); // build urlencoded POST string for login
$post_string = str_replace('%40', '@', $post_string);

curl_setopt($ch, CURLOPT_URL, $site_login);
curl_setopt($ch, CURLOPT_POST, 1);
//curl_setopt($ch, CURLOPT_SAFE_UPLOAD, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_string);

// execute login request
$result = curl_exec($ch);

if (!$result) {
    die("Логин или парль введён неверно.");
}

// check for "Redirecting" message in title to indicate success
// based on your language - you may need to change this to match some other string
if (strpos(curl_exec($ch), 'ipsBox_alt') === false) {
    die("Авторизация больше не доступна, скорее всего был изменён стиль страницы, либо метод авторизации.");
}

if (strpos(curl_exec($ch), 'ipsMessage_error') == true) {
    die("Отображаемое имя или email адрес, введённый вами, не принадлежит ни к одному аккаунту. Убедитесь в правильности введённой информации.<br>Ваш логин: " . $USERNAME . "<br>Ваш пароль:" . $PASSWORD);
}

// вывод на экран
echo $result;

function getFormFields($data) {
    if (preg_match('/(<form.*?class=.*?ipsBox_alt.*?<\/form>)/is', $data, $matches)) {
		//var_dump($matches[0]);
        $inputs = getInputs($matches[0]);
		//var_dump($inputs);
        return $inputs;
    } else {
        die('Авторизация больше не доступна, скорее всего был изменён метод авторизации.');
    }
}

// extract all <input fields from a form
function getInputs($form) {
    $inputs = array();

    $elements = preg_match_all('/(<input[^>]+>)/is', $form, $matches);

    if ($elements > 0) {
        for($i = 0; $i < $elements; $i++) {
            $el = preg_replace('/\s{2,}/', ' ', $matches[1][$i]);

            if (preg_match('/name=(?:["\'])?([^"\'\s]*)/i', $el, $name)) {
                $name  = $name[1];
                $value = '';

                if (preg_match('/value=(?:["\'])?([^"\'\s]*)/i', $el, $value)) {
                    $value = $value[1];
                }

                $inputs[$name] = $value;
            }
        }
    }

    return $inputs;
}

// чтобы не применять curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); и не отключать open_basedir
function curl_exec_follow(/*resource*/ $ch, /*int*/ &$maxredirect = null) {
    $mr = $maxredirect === null ? 5 : intval($maxredirect);
    if (ini_get('open_basedir') == '' && ini_get('safe_mode' == 'Off')) {
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, $mr > 0);
        curl_setopt($ch, CURLOPT_MAXREDIRS, $mr);
    } else {
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);
        if ($mr > 0) {
            $newurl = curl_getinfo($ch, CURLINFO_EFFECTIVE_URL);
            $rch = curl_copy_handle($ch);
            curl_setopt($rch, CURLOPT_HEADER, true);
            curl_setopt($rch, CURLOPT_NOBODY, true);
            curl_setopt($rch, CURLOPT_FORBID_REUSE, false);
            curl_setopt($rch, CURLOPT_RETURNTRANSFER, true);
            do {
                curl_setopt($rch, CURLOPT_URL, $newurl);
                $header = curl_exec($rch);

                if (curl_errno($rch)) {
                    $code = 0;
                } else {
                    $code = curl_getinfo($rch, CURLINFO_HTTP_CODE);

                    if ($code == 301 || $code == 302 || $code == 403) {
                        preg_match('/Location:(.*?)\n/', $header, $matches);
                        $newurl = trim(array_pop($matches));
                    } else {
                        $code = 0;
                    }
                }
            } while ($code && --$mr);

            curl_close($rch);

            if (!$mr) {
                if ($maxredirect === null) {
                    trigger_error('Too many redirects. When following redirects, libcurl hit the maximum amount.', E_USER_WARNING);
                } else {
                    $maxredirect = 0;
                } 
 
                return false;
            } 

            curl_setopt($ch, CURLOPT_URL, $newurl);
        }
    }

    return curl_exec($ch);
}

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

7/ Бывают такие хостинги, что при постоянно большом количестве запросов может упасть Mysqli. В OpenCart можно легко сделать много запросов пройдя по ссылке: /index.php?route=product/search&search=&limit=100000 - загружаются все товары.


Чтобы это убрать и ограничить, например до 100 товаров.

Скрытый текст

Для oc2.3
В catalog/controller/product/search.php
Найти (здесь мы запрещаем вывод товара при пустом параметре &search= или &tag=):


		if (isset($this->request->get['search'])) {
			$search = $this->request->get['search'];
		} else {
			$search = '';
		}

		if (isset($this->request->get['tag'])) {
			$tag = $this->request->get['tag'];
		} elseif (isset($this->request->get['search'])) {
			$tag = $this->request->get['search'];
		} else {
			$tag = '';
		}

Заменить на:


		if (!empty($this->request->get['search'])) {
			$search = ($this->request->get['search'] > '' ? $this->request->get['search'] : '');
		} else {
			$search = '';
		}

		if (isset($this->request->get['tag'])) {
			$tag = ($this->request->get['tag'] > '' ? $this->request->get['tag'] : '');
		} elseif (isset($this->request->get['search'])) {
			$tag = ($this->request->get['search'] > '' ? $this->request->get['search'] : '');
		} else {
			$tag = '';
		}

 

Найти (этот пункт выполнить везде категории, производители и т.д. - это мы ограничиваем подсчёт товара, а вывод товара в моделях):


		if (isset($this->request->get['limit'])) {
			$limit = (int)$this->request->get['limit'];
		} else {
			$limit = $this->config->get($this->config->get('config_theme') . '_product_limit');
		}

Заменить на:


		if (isset($this->request->get['limit'])) {
			$limit = ((int)$this->request->get['limit'] > 100 ? 100 : (int)$this->request->get['limit']);
		} else {
			$limit = $this->config->get($this->config->get('config_theme') . '_product_limit');
		}

 

Найти (здесь мы запрещаем вывод товара при пустом параметре &search= или &tag=):


if (isset($this->request->get['search']) || isset($this->request->get['tag'])) {

Заменить на:


if ($search || $tag) {

 

В catalog/model/catalog/product.php

Найти (здесь мы ограничиваем вывод товара):


			if ($data['limit'] < 1) {
				$data['limit'] = 20;
			}

Вставить выше:


			if ($data['limit'] > 100 && $data['limit'] > $this->config->get('config_product_limit')) { // fix Buslikdrev
				$data['limit'] = 100;
			}

 


Также есть ограничение на индексацию страниц в robots.txt

Crawl-delay: 0.1

Ставить после Disallow:

0.1 - это секунды запрета посещать боту любую страницу сайта.

Подробности здесь.

 

В google этой задержки нет, только скорость сканирования.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

8/ В OpenCart есть проблема с установкой количества столбцов подкатегорий в категории. Вот решение для главного меню, например:

В стилях stylesheet.css изменить:

Скрытый текст

Это:


#menu .dropdown-inner ul {
    display: table-cell;
}

 

На это:


#menu .dropdown-inner ul {
    display: block;
}
#menu .dropdown-inner ul li {
    display: table-cell;
}

 

Или на это:


#menu .dropdown-inner ul li {
    display: table-cell;
}

 


В скрипте common.js изменить:

Скрытый текст

Это:


var menu = $('#menu').offset();

 

На это:


var menu = $('#menu').parent().offset();

 


В шаблоне header.tpl изменить:

Скрытый текст

Это:


<?php foreach (array_chunk($category['children'], ceil(count($category['children']) / $category['column'])) as $children) { ?>

 

На это:


<?php foreach (array_chunk($category['children'], $category['column']) as $children) { ?>

 


Дело в том, что array_chunk() разбивает массив так, что выходит, что мы задаём не количество ожидаемых массивов (столбцов), а максимальное количество данных (строк) которые могут содержать полученные массивы (столбцы).

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

9/ Регистронезависимый поиск изображения


10/ узнаём примерную скорость выполнения php кода.

Скрытый текст

Вариант 1


define('ST_T', microtime()); // старт времени.
// тут наш код
printf('Время выполнения скрипта: %.5f сек.', microtime()-ST_T); // стоп время и вычисление разницы.


Вариант 2


$start = microtime(true); // старт времени.
// тут наш код
echo 'Время выполнения скрипта: ' . round(microtime(true) - $start, 4) . ' сек.'; // стоп время и вычисление разницы.

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
13 часа назад, Yoda сказал:

Сделай отдельный скрипт!

Разделил

 

13 часа назад, Yoda сказал:

Во вторых за crawl-delay 120, необходимо голову откусывать по пятки!

Это считай убить индексацию магазина.

Каждый выбирает сам сколько ему секунд устанавливать и устанавливать-ли это ограничение вообще. Добавил ссылки на подробную информацию.

 

Спасибо за помощь.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
8 часов назад, BuslikDrev сказал:

Каждый выбирает сам сколько ему секунд устанавливать и устанавливать-ли это ограничение вообще. Добавил ссылки на подробную информацию.

Вот мил человек, ты хороший парень. Стараешься. Я очень ценю.

Но за 120 сек краул дилей,  я бы тебе дал ремня и поставил на горох.

В школе надо было учить математику.

 

Берем магазин на 1000 товаров. на каждой странице магазина/категории у нас пусть 100 изображений.
Получаем пусть 100 000 элементов которые надо просканировать ботам...


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

А теперь бери 100 000 * 120. Ну реально солнце раньше потухнет, пока бот увидит сайт.

 

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

Есть один единственный способ сделать нормальную индексацию - это правильная настройка роботса и быстрый магазин. Все....

Все остальное - это от лукавого.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
2 часа назад, Yoda сказал:

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

 

Ответственность не вешаю и никого не понуждаю. Ваше замечание было учтено (добавлены дополнительные ссылки на изучение) - оно видно всем. Также для вас и др. сменил значение на 0.1 сек. Оптимального значения для crawl-delay от вас не было озвучено, т.к. вы вообще против использования crawl-delay. 

 

2 часа назад, Yoda сказал:

Есть один единственный способ сделать нормальную индексацию - это правильная настройка роботса и быстрый магазин. Все....


Будем считать, что robots настроен правильно в сборке.pro, а если магазин не быстрый (к примеру финансов нет)?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

10/ при генерации ссылок от названия, добавляйте id к ссылке, чтобы исключить их дубли.
Пример: http://site.ru/25-category/2544-tovar

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

11/ полезная статья для определения какие кавычки использовать - разница есть и нет такого: "кому какие нравятся".

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

12/ доступ в админку через фтп:

Скрытый текст

Помещаем это код, например, в controller/common/header.php


$this->session->data['token'] = token(32);
$this->session->data['user_id'] = 1; // порядковый номер админа
echo $this->session->data['token'];

Открываем сайт, копируем токен и подставляем к нашей админке:
http://site.ru/admin/index.php?route=common/dashboard&token=сюда

Опосайтесь такого рода кода в коде вашего сайта.

 

 

13/ Совет по модулю строения для уменьшения лишних запросов к БД:

Скрытый текст

Для моего модуля не требуется выполнение стандартных запросов: выборка настроек из БД, языка, сеопро и т.д. OpenCart.pro при загрузки пустого контроллера делает около 12 sql-запросов к БД, а это около 25мс к загрузке и естественно лишняя нагрузка на сервер, когда, например, 1000 пользователей одновременно будут юзать ваш модуль, который загружается на отдельной странице, например, какая-нибудь карта сайта или подгружается через метод ajax.

 

Так вот, рекомендую устанавливать условия для загрузки нужных вам контроллеров и не создавать модули как отдельный php файл со своим подключением к БД:


<?xml version="1.0" encoding="utf-8"?>
<modification>
	<code>BuslikDrev</code>
    <name>.Правки от BuslikDrev</name>
    <version>0.1</version>
    <author>BuslikDrev</author>
    <link>https://liveopencart.ru/buslikdrev</link>
    <file path="system/engine/action.php">
        <operation skip="error">
            <search index="0">
			<![CDATA[function execute($registry]]>
            </search>
            <add position="after">
			<![CDATA[		if (isset($_POST['route']) && isset($_POST['ajax'])) {
			if ($_POST['route'] == 'extension/module/mymodule') {
				$stop = false;

				if ($this->route == 'startup/session') {
					//$stop = true;
				}
				if ($this->route == 'startup/startup') {
					$stop = true;
				}
				if ($this->route == 'startup/error') {
					$stop = true;
				}
				if ($this->route == 'startup/event') {
					$stop = true;
				}
				if ($this->route == 'startup/maintenance') {
					$stop = true;
				}
				if ($this->route == 'startup/seo_url') {
					$stop = true;
				}
				if ($this->route == 'startup/seo_pro') {
					$stop = true;
				}

				if ($stop) {
				    return;
				}
			}
		}

		if (isset($_GET['route']) && isset($_POST['ajax'])) {
			if ($_GET['route'] == 'extension/module/mymodule') {
				$stop = false;

				if ($this->route == 'startup/session') {
					//$stop = true;
				}
				if ($this->route == 'startup/startup') {
					$stop = true;
				}
				if ($this->route == 'startup/error') {
					$stop = true;
				}
				if ($this->route == 'startup/event') {
					$stop = true;
				}
				if ($this->route == 'startup/maintenance') {
					$stop = true;
				}
				if ($this->route == 'startup/seo_url') {
					$stop = true;
				}
				if ($this->route == 'startup/seo_pro') {
					$stop = true;
				}

				if ($stop) {
				    return;
				}
			}
		}]]>
            </add>
        </operation>
    </file>
    <file path="system/engine/loader.php">
        <operation skip="error">
            <search index="0">
			<![CDATA[function library(]]>
            </search>
            <add position="after">
			<![CDATA[		if (isset($_POST['route']) && isset($_POST['ajax'])) {
			if ($_POST['route'] == 'extension/module/mymodule') {
				return;
			}
		}

		if (isset($_GET['route']) && isset($_POST['ajax'])) {
			if ($_GET['route'] == 'extension/module/mymodule') {
				return;
			}
		}]]>
            </add>
        </operation>
    </file>
  </modification>

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Гость
Ответить в тему...

×   Вы вставили отформатированное содержимое.   Удалить форматирование

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Сейчас на странице   0 пользователей

    Нет пользователей, просматривающих эту страницу