Можно с помощью программы enca
.
Устанавливаем:
$ sudo apt install -y enca
Запускаем:
$ enca myfile.txt
Видим результат, например, такой:
Universal transformation format 8 bits; UTF-8
Doubly-encoded to UTF-8 from ISO-8859-5
Можно с помощью программы enca
.
Устанавливаем:
$ sudo apt install -y enca
Запускаем:
$ enca myfile.txt
Видим результат, например, такой:
Universal transformation format 8 bits; UTF-8
Doubly-encoded to UTF-8 from ISO-8859-5
Встретил такую ошибку. Использовал образ https://hub.docker.com/r/mdillon/postgis
Выяснилось, что образ обновил postgis до версии 2.5 (2.4 был полностью убран).
Чтобы все починить, просто выполните команду внутри контейнера /usr/local/bin/update-postgis.sh
- это обновит postgis с версии 2.4 до версии 2.5 внутри вашего контейнера. Возможно, придется перезагрузить его, но у меня все заработало.
Сегодня узнал о крутой защите от ботов. Блокирует не только традиционными способами, но и активно используя машинное обучение.
Называется она - Distil Networks
Если использовать вместе с рекапчей от гугла, то на сайт вообще практически невозможно пробиться автоматизированными путями. Да, селениум тоже заблокирует. Да, может не с первого раза, но на 2-3 заблокирует.
Кому очень надо, вот здесь ребята с реддит уверяют, что могут обойти защиту https://www.reddit.com/r/webdev/comments/5q1ypx/what_is_your_approach_on_scraping_distil_networks/
Скачать пример файлом - example_chromedriver.zip
Структура папок и файлов:
wrapper/Dockerfile
wrapper/requirements.txt
wrapper/main.py
docker-compose-yml
Содержимое docker-compose.yml
:
version: "2"
services:
web:
build: wrapper
restart: always
command: python main.py
Содержимое wrapper/Dockerfile
:
FROM python:3.6
ENV PYTHONUNBUFFERED 1
# install google chrome
RUN wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -
RUN sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google-chrome.list'
RUN apt-get -y update
RUN apt-get install -y google-chrome-stable
# install chromedriver
RUN apt-get install -yqq unzip
RUN wget -O /tmp/chromedriver.zip http://chromedriver.storage.googleapis.com/`curl -sS chromedriver.storage.googleapis.com/LATEST_RELEASE`/chromedriver_linux64.zip
RUN unzip /tmp/chromedriver.zip chromedriver -d /usr/local/bin/
# set display port to avoid crash
ENV DISPLAY=:99
RUN mkdir /code
WORKDIR /code
COPY . /code/
RUN pip install -r requirements.txt
Содержимое wrapper/requirements.txt
:
selenium==3.8.0
Содержимое wrapper/main.py
:
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import time
chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument('--no-sandbox')
chrome_options.add_argument('--headless')
chrome_options.add_argument('--disable-gpu')
driver = webdriver.Chrome(chrome_options=chrome_options)
driver.implicitly_wait(10)
while True:
print('start')
driver.get("http://www.python.org")
assert "Python" in driver.title
elem = driver.find_element_by_name("q")
print('elem', elem)
elem.clear()
elem.send_keys("pycon")
elem.send_keys(Keys.RETURN)
assert "No results found." not in driver.page_source
print('all ok')
time.sleep(3)
driver.close()
Источник: https://github.com/joyzoursky/docker-python-chromedriver
Вот таким образом можно сделать табличный вид заказа с торговыми предложениями и самими товарами в письме. Для вывода таблицы в шаблоне нового заказа необходимо использовать переменную #ORDER_TABLE_ITEMS#
. Картинки тоже прилагаются.
Файл init.php
:
<?
AddEventHandler("sale", "OnOrderNewSendEmail", "ModifyOrderSaleMails");
function ModifyOrderSaleMails($orderID, &$eventName, &$arFields) {
if(CModule::IncludeModule("sale") && CModule::IncludeModule("iblock")) {
$strOrderList = "";
$dbBasketItems = CSaleBasket::GetList(
array("NAME" => "ASC"),
array("ORDER_ID" => $orderID),
false,
false,
array("PRODUCT_ID", "ID", "NAME", "QUANTITY", "PRICE", "CURRENCY")
);
$strOrderList = "
<style>
table.example {
border-collapse: collapse;
width: 585px;
}
table.example td {
border:1px solid black;
}
table.example td.num {
width: 30px;
text-align: center;
}
</style>
<table class=\"example\">
<tr>
<td class=\"num\" align=\"center\">№</td>
<td align=\"center\">Фото товара</td>
<td align=\"center\">Наименование</td>
<td align=\"center\">Количество</td>
<td align=\"center\">Цена, руб.</td>
<td align=\"center\">Cумма, руб.</td>
</tr>";
$i = 0;
while ($arProps = $dbBasketItems->Fetch()) {
$i += 1;
// image
$offer = CIBlockElement::GetById(IntVal($arProps["PRODUCT_ID"]))->GetNext();
$pictureId = $offer["PREVIEW_PICTURE"];
if (is_null($pictureId)) {
$realProductInfo = CCatalogSku::GetProductInfo(IntVal($arProps["PRODUCT_ID"]));
$realProduct = CIBlockElement::GetById(IntVal($realProductInfo["ID"]))->GetNext();
$pictureId = $realProduct["PREVIEW_PICTURE"];
}
$thumb = CFile::ResizeImageGet(
$pictureId,
array("width" => 200, "height" => 200),
BX_RESIZE_IMAGE_PROPORTIONAL,
false
);
$thumb = $thumb["src"];
// sum
$summ = $arProps['QUANTITY'] * $arProps['PRICE'];
$strOrderList .= "<tr><td class=\"num\">".$i."</td><td><img src=\"http://".$_SERVER['SERVER_NAME'] . $thumb."\"></td><td>".$arProps['NAME']."</td><td>".$arProps['QUANTITY']."</td><td>".number_format((float)$arProps['PRICE'], 2, '.', '')."</td><td>".number_format((float)$summ, 2, '.', '')."</td><tr>";
}
echo "</table>";
// пишем в переменную для письма
$arFields["ORDER_TABLE_ITEMS"] = $strOrderList;
}
}
?>
Подобным образом можно добавить и другие переменные к письму.
Написал плейбук для создания нового сервера для небольших сайтов на хостинге https://vscale.io.
Работает следующим образом:
vars.yml
директорию.docker-compose up -d
на сервере.Найти последнюю версию можно здесь https://github.com/crusat/ansible_vscale_new_server, также прикрепил здесь версию на момент создания статьи.
Для начала надо скачать все модули, которые перечислены в requirements.txt. Проще всего через докер.
$ docker run -it --rm --name my -v "$PWD":/tmp/pip_cache python:3.6 pip download -r /tmp/pip_cache/requirements.txt -d /tmp/pip_cache/
Обратите внимание на версию. Тут используется 3.6 - она должна совпадать с той версией питона, который установлен на сервере. Иначе Pillow, psycopg2 и т.п. скомпилированные модули не поставятся.
Затем можно залить их и установить с помощью такой команды:
$ pip install -r requirements.txt -f /path/to/pip/cache/ --no-index
Все, после этого можно использовать.
HTTP
server {
listen 80;
server_name www.example.com;
location /.well-known/acme-challenge/ {
root /home/garpix/www/example.com/;
}
location / {
return 301 https://$host$request_uri;
}
}
HTTPS (letsencrypt)
server {
listen 443 ssl;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
server_name www.example.com;
return 301 https://example.com$request_uri;
}
Если вы скопируете файл, содержащий в названии эту замечательную букву с Linux-машины на MacOS-машину и обратно, то
попытавшись обнаружить этот файл, вы, скорее всего, уже не сможете этого сделать (ответом будет File not found):
$ ls *й*
Учитывая, что при простом отображении файлов в директории, вы его увидите:
$ ls
Это происходит потому, что букву Й можно закодировать в UTF-8 как один или два символа. И эти две системы делают это
по-разному. При копировании на MacOS файл кодируется по-другому и при копировании обратно, он не будет уже тем старым
добрым Й, который вы знали на Linux-машине. Короче, аккуратнее с этими вещами.
Спасибо человеку, ответившему на тот же вопрос, с которым я столкнулся: http://ru.stackoverflow.com/a/481109
Для проксирования запросов через nginx “куда-то еще” можно использовать подобный скрипт. Это называется “reverse proxy”.
В случае ниже, nginx слушает 80 порт для example.com и перенаправляет запрос на http://127.0.0.1:1000. При этом, он сохранит server_name и IP посетителя.
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://127.0.0.1:1000;
proxy_set_header Host $server_name;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 60;
proxy_send_timeout 60;
proxy_read_timeout 60;
send_timeout 60;
}
}