<?xml version="1.0" encoding="utf-8"?> 
<rss version="2.0"
  xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd"
  xmlns:atom="http://www.w3.org/2005/Atom">

<channel>

<title>Блог Артёма Агасиева: заметки с тегом Лайфхак</title>
<link>https://agasiev.com/tags/layfhak/</link>
<description>Telegram: @aagasiev</description>
<author>Артём Агасиев</author>
<language>ru</language>
<generator>E2 (v3576; Aegea)</generator>

<itunes:owner>
<itunes:name>Артём Агасиев</itunes:name>
<itunes:email></itunes:email>
</itunes:owner>
<itunes:subtitle>Telegram: @aagasiev</itunes:subtitle>
<itunes:image href="" />
<itunes:explicit></itunes:explicit>

<item>
<title>А нужно ли вообще рассматривать все жалобы в соцсетях?</title>
<guid isPermaLink="false">10</guid>
<link>https://agasiev.com/all/a-nuzhno-li-voobsche-rassmatrivat-vse-zhaloby/</link>
<pubDate>Fri, 24 Mar 2023 02:17:35 +0300</pubDate>
<author>Артём Агасиев</author>
<comments>https://agasiev.com/all/a-nuzhno-li-voobsche-rassmatrivat-vse-zhaloby/</comments>
<description>
&lt;p&gt;Наступает неприятный момент, когда модерация социальной сети начинает задыхаться от наплыва жалоб пользователей на контент.&lt;/p&gt;
&lt;p&gt;Возникает логичный вопрос: &lt;i&gt;Как уменьшить нагрузку на модераторов?&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;Да, можно придумать умных AI помощников, классификации жалоб на группы и т. д. Но может, для начала, нужно спросить себя: &lt;i&gt;А важны ли все жалобы от всех пользователей?&lt;/i&gt;&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://agasiev.com/pictures/unnamed-(2).jpeg" width="512" height="512" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;Многие жалуются просто из-за плохого настроения или просто потому, что не согласны с мнением оппонента в сетевой диванно-позиционной войне. По сути, это может быть нормальный контент, который просто не нравится &lt;i&gt;конкретному&lt;/i&gt; человеку.&lt;/p&gt;
&lt;p&gt;Какой выход? Для определенных типов жалоб нужно создавать видимость того, что пользователь был услышан: временно скрывать контент от жалобщика, т. е. в рамках одной сессии поставить&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;display:none&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;html блоку или вообще удалить его, а саму жалобу отправить в &lt;i&gt; /dev/null&lt;/i&gt;. Если вариантов жалоб несколько, то можно скрыть этот функционал в «Жалобы — Прочее» или прямо так и назвать «Жалобы — Я не согласен с юзером». Работает, проверено.&lt;/p&gt;
&lt;p&gt;В самом крайнем случае, ставить счетчик на количество жалоб на пользователя и его контент и по превышению некоторого порога отправлять на модерацию.&lt;/p&gt;
&lt;p&gt;Исключение — время прохождения модерации при публикации в AppStore или Google Play, в этот момент нужно включать модерацию любого контента на максимум, особенно 18+. Ведь хрен знает, на что может пожаловаться модератор маркета, а релиз, обычно, очень не хочется задерживать из-за возни с какой-то мелочью.&lt;/p&gt;
</description>
</item>

<item>
<title>Передача большого количества картинок между серверами</title>
<guid isPermaLink="false">75</guid>
<link>https://agasiev.com/all/peredacha-bolshogo-kolichestva-kartinok-mezhdu-serverami/</link>
<pubDate>Sun, 13 Dec 2020 15:43:53 +0300</pubDate>
<author>Артём Агасиев</author>
<comments>https://agasiev.com/all/peredacha-bolshogo-kolichestva-kartinok-mezhdu-serverami/</comments>
<description>
&lt;p&gt;Допустим, вам, как и мне сейчас, потребовалось перекинуть пару сотен тысяч картинок с одного сервера на другой. Передача файлов по одному займет неадекватное количество времени. Хочется как-то их все собрать в один файл и передать уже его разом по сети.&lt;/p&gt;
&lt;p&gt;Кажется, что для этого может подойти создание архива из всех доступных файлов. Однако, для картинок, в отличии от текста, это не будет иметь особого смысла, т. к. сжать их еще сильнее не получится, а времени на попытки уйдет уйма.&lt;/p&gt;
&lt;p&gt;Какой есть выход из этой ситуации? Верно, создать архив без сжатия:&lt;/p&gt;
&lt;p&gt;Вот так, если предпочитаете tar:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class="shell"&gt;tar -cf ./archive.tar /path/to/folder&lt;/code&gt;
&lt;/pre&gt;
&lt;p&gt;И так, если больше нравится zip:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class="shell"&gt;zip -qq -0 -r ./archive.zip /path/to/folder&lt;/code&gt;
&lt;/pre&gt;
&lt;p&gt;Но как показывают замеры времени, tar справляется с задачей простой сборки файлов в один в разы быстрее.&lt;/p&gt;
&lt;p&gt;После передачи файла по сети распаковать его можно так:&lt;/p&gt;
&lt;p&gt;Для tar архива:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class="shell"&gt;tar -xf ./archive.tar&lt;/code&gt;
&lt;/pre&gt;
&lt;p&gt;И для zip архива:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class="shell"&gt;unzip -qq ./archive.zip&lt;/code&gt;
&lt;/pre&gt;
</description>
</item>

<item>
<title>Обрабатываем некорректно сохраненные в лог JSON данные</title>
<guid isPermaLink="false">74</guid>
<link>https://agasiev.com/all/obrabatyvaem-nekorrektno-sohranennye-v-log-json-dannye/</link>
<pubDate>Thu, 10 Dec 2020 18:15:29 +0300</pubDate>
<author>Артём Агасиев</author>
<comments>https://agasiev.com/all/obrabatyvaem-nekorrektno-sohranennye-v-log-json-dannye/</comments>
<description>
&lt;p&gt;С месяц назад, при записи JSON данных в лог, забыл отформатировать их json.dumps из питоновского dict’a в нормальный вид, а просто записал его при форматной печатью, преобразовав dict в str. Само собой, получил кучу данных в неудобоваримом виде,  эх.&lt;/p&gt;
&lt;p&gt;Как исправить? Стандартный json.loads теперь не воспримет такую строку как корректный JSON, т. к. с точки зрения формата она не валидна. Можно решить эту проблему при помощи функции &lt;a href="https://docs.python.org/3/library/ast.html#ast.literal_eval"&gt;ast.literal_eval&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Она безопасно преобразует строку, содержащую символы или стандартные структуры питона в нужный элемент или объект. В нашем случае, строковое представление словаря в сам словарь. А значит, так можно пробежаться по всем логам и преобразовать их в корректный вид.&lt;/p&gt;
&lt;p&gt;Пример работы:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class="python"&gt;
import ast
import json

# Наш преобразованный в строку dict()
s = "{'a': 'Text with \\'quotes\\''}"
j = json.loads(s)
# Получаем ошибку парсинга из-за одинарных кавычек
&gt;&gt; json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes: line 1 column 2 (char 1)

# Парсим строку в dict
j = ast.literal_eval(s)
print(j)
&gt;&gt; {'a': "Text with 'quotes'"}
# Теперь уже дампим данные корректно
print(json.dumps(j))
&gt;&gt;{"a": "Text with 'quotes'"}
&lt;/code&gt;
&lt;/pre&gt;
</description>
</item>

<item>
<title>Keras 2.3 &amp;amp; TensorFlow 2</title>
<guid isPermaLink="false">65</guid>
<link>https://agasiev.com/all/keras-2-3-tensorflow-2/</link>
<pubDate>Sat, 13 Jun 2020 03:31:30 +0300</pubDate>
<author>Артём Агасиев</author>
<comments>https://agasiev.com/all/keras-2-3-tensorflow-2/</comments>
<description>
&lt;p&gt;При обновлении до Keras &gt;= 2.3 и Tensorflow &gt;= 2.0 в старых многопоточных приложениях может начать выскакивать ошибка:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;AttributeError: '_thread._local' object has no attribute 'value'&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Решить ее можно заменив импорты&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;from keras import что_нужно&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;на&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;from tensorflow.keras import что_нужно&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;b&gt;UPD&lt;/b&gt;: Если после обновления появилось вот такое:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;Error : Failed to get convolution algorithm. This is probably because cuDNN failed to initialize, so try looking to see if a warning log message was printed above.&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Весьма вероятно, что cuDNN теперь не подходит по версии для TensorFlow ибо старовата. Найти нужную версию можно &lt;a href="https://www.tensorflow.org/install/source#linux"&gt;тут&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;UPD 2&lt;/b&gt;: При обновлении cuDNN еще можно заметить, что в &lt;a href="https://docs.nvidia.com/deeplearning/sdk/cudnn-install/index.html#installlinux-tar"&gt;официальной инструкции установки на linux из архива&lt;/a&gt; не указано, что после копирования нужно сделать симлинки на so’шники. Иначе после sudo ldconfig будет ошибка (далее, вместо библиотеки версии 7, подставьте свою):&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;/usr/local/cuda/lib64/libcudnn.so.7 is not a symbolic link&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Т. е. надо:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;$ cd /usr/local/cuda/lib64/

$ ls -lha libcudnn*
-rwxr-xr-x 1 root root 374M июн 13 04:27 libcudnn.so
-rwxr-xr-x 1 root root 374M июн 13 04:27 libcudnn.so.7
-rwxr-xr-x 1 root root 374M июн 13 04:27 libcudnn.so.7.6.5
-rw-r--r-- 1 root root 373M июн 13 04:27 libcudnn_static.a

$ sudo rm libcudnn.so libcudnn.so.7
$ sudo ln libcudnn.so.7.6.5 libcudnn.so.7
$ sudo ln libcudnn.so.7 libcudnn.so
$ sudo ldconfig&lt;/code&gt;&lt;/pre&gt;</description>
</item>

<item>
<title>Экспресс пиар</title>
<guid isPermaLink="false">58</guid>
<link>https://agasiev.com/all/ekspress-piar/</link>
<pubDate>Sat, 10 Aug 2019 02:24:24 +0300</pubDate>
<author>Артём Агасиев</author>
<comments>https://agasiev.com/all/ekspress-piar/</comments>
<description>
&lt;p&gt;&lt;a href="https://www.artlebedev.ru/express-design/"&gt;Экспресс-дизайн&lt;/a&gt; от студии Артемия Лебедева — просто охуенная штука. Всего за 100000 рублей можно хорошо попиариться на всю страну развеселым логотипом, получить гору трафика на сайт и повысить узнаваемость бренда.&lt;/p&gt;
&lt;p&gt;Убиваем сразу три зайца одним выстрелом:&lt;/p&gt;
&lt;ol start="1"&gt;
&lt;li&gt;Студия экспериментирует, ищет новые подходы в дизайне &lt;i&gt;за деньги заказчика&lt;/i&gt; и не сильно беспокоится о его мнении насчет получившегося результата.&lt;/li&gt;
&lt;li&gt;Название студии все время на слуху.&lt;/li&gt;
&lt;li&gt;Заказчик получает бурление говн в соцсеточках, с упоминанием названия компании и ссылками на его сайт. А значит будет трафик и рост ссылочной массы, что неплохо повлияет на поисковую выдачу в будущем.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;А на сам логотип, в целом, всем плевать.&lt;/p&gt;
</description>
</item>

<item>
<title>Мы вам обязательно перезвоним</title>
<guid isPermaLink="false">50</guid>
<link>https://agasiev.com/all/mi-vam-obyazatelno-perezvonim/</link>
<pubDate>Thu, 13 Jun 2019 13:05:26 +0300</pubDate>
<author>Артём Агасиев</author>
<comments>https://agasiev.com/all/mi-vam-obyazatelno-perezvonim/</comments>
<description>
&lt;p&gt;На моем сайте есть форма обратной связи, через которую клиенты могут оставить свой телефон. Однако, возникает интересная ситуация — в половине случаев при звонке на указанный номер трубку никто не берет. Мало того, иногда даже сбрасывают звонок. Согласен, все мы бываем заняты. Перезваниваю через какое-то время — эффект тот же.&lt;/p&gt;
&lt;p&gt;Стал думать: что тут может быть не так? Идей особо не было, так что вначале воспринял это как специфику рынка. Но потом как-то в облачной АТС закончились деньги, и я решил набрать такой сбрасывающий номер с  сотового телефона. И... о чудо! Трубку подняли, разговор успешно состоялся.&lt;/p&gt;
&lt;p&gt;Провел небольшой эксперимент, и оказалось, что даже на разные коды городов реагируют по-разному. В порядке уменьшения вероятности принятия звонка:&lt;br&gt;&lt;br&gt;&lt;/p&gt;
&lt;ol start="1"&gt;
&lt;li&gt;Сотовый номер с кодом региона абонента&lt;/li&gt;
&lt;li&gt;Сотовый номер из любого другого региона&lt;/li&gt;
&lt;li&gt;8-800, 495, 812, 499&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Если клиент сам решает позвонить вам, то ситуация меняется: люди любят «официальные» городские номера, в особенности, бесплатный для них 8-800. Так распределились номера в порядке убывания вероятности звонка:&lt;br&gt;&lt;br&gt;&lt;/p&gt;
&lt;ol start="1"&gt;
&lt;li&gt;8-800&lt;/li&gt;
&lt;li&gt;495, 812, 499&lt;/li&gt;
&lt;li&gt;Сотовый номер с кодом региона абонента&lt;/li&gt;
&lt;li&gt;Сотовый номер из любого другого региона&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Видимо, людей задолбали телефонные спамеры и холодные звонки, поэтому многие просто не отвечают, когда видят на экране входящий звонок с городского номера. А звонить на сотовые номера боятся из-за ощущения кустарности и ненадежности предприятия. Особенно, если клиенту предлагается купить дорогой товар или услугу.&lt;/p&gt;
&lt;p&gt;Таким образом, для обратной связи лучше оставлять номер с кодом 8-800 или 495/812, а самому звонить с сотового телефона.&lt;/p&gt;
</description>
</item>


</channel>
</rss>