Позднее Ctrl + ↑

Скрипт ответа охраны, в нерабочее время

В не рабочее время организации на звонки отвечает сотрудник охраны. У него есть скрипт-инструкция.

Скрипт представляет много листов, с примерами разговоров. Пользоваться такой инструкцией не удобно.

Исходный материал — все фразы на месте, большой объем, дублирование информации. Для работы со скриптом, охраннику нужно перелистывать страницы.

Появляется идея оформить скрипт-инструкцию как разговор в чате

Инструкция получилась на один лист, ее можно распечатать, заламинировать и положить на охрану.

Записали номер для экстренной связи, теперь не нужно искать его. Раньше охранник искал этот номер в справочнике или в телефоне.

В бланк заносится основная информация о клиенте: имя, номер телефона, запрос. Утром менеджеры смогут позвонить и решить запрос.

Авторизация на сайте через питон

По материалам статьи: Python requests. Авторизация на сайте

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

Для авторизации нужно поддерживать активную сессию в модуле requests, через session.get()

session.get(url) вместо requests.get(url)
import requests
import re
from bs4 import BeautifulSoup
import pandas as pd

url = 'https://freelance.ru/login/'

# Важно. По умолчанию requests отправляет вот такой 
# заголовок 'User-Agent': 'python-requests/2.22.0 ,  а это приводит к тому , что Nginx
# отправляет 404 ответ. Поэтому нам нужно сообщить серверу, что запрос идет от браузера  

user_agent_val = 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.104 Safari/537.36'

# Создаем сессию и указываем ему наш user-agent
session = requests.Session()
r = session.get(url, headers = {
    'User-Agent': user_agent_val
})

# Указываем referer. Иногда , если не указать , то приводит к ошибкам. 
session.headers.update({'Referer':url})

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

_xsrf = session.cookies.get('_xsrf', domain=".freelance.ru")

Дальше посылаем post-запрос

login = "xxxx"
passwd = "xxxx"

post_request = session.post(url, {
    'login': login ,
    'passwd': passwd,
    "check_ip": "on",
    "submit": "%C2%F5%EE%E4",
    "auth": "auth",
    "return_url": "/login/"
})

Для того чтобы узнать пост запрос, нужно зайти в инспектор кода, вкладка сеть, и найти запрос который посылается

В submit я подставил значение из не декодированного вида.

Теперь переходим в закрытый раздел, обновляем сессию и снимаем данные

url = "https://freelance.ru/setup/"
r = session.get(url)
soup = BeautifulSoup(r.text, "lxml")
soup
Мой рейтинг на этом сервисе.

Дальше можно снимать нужную информацию, используя BeautifulSoup

Для библиотеки Requests, есть хорошие статьи от Александра, pythonru

Краткое руководство по библиотеке Python Requests — рассказывает кратко, как пользоваться библиотекой.

Продвинутое руководство по библиотеке Python Requests — дополнительная информация, по объектам session, сертификатам SSL, прокси.

Москва в снегу

Когда в Москве выпадает снег, передвигаться сложно.

Коммунальные службы во всю работают
Автомобилям тяжело по таким сугробам
Кто-то хочет в отпуск с пивом и рыбой

Как ускорить видео в интернете?

Удобно смотреть лекции и семинары на скорости 1,7 — 2,5, используя расширение для браузера Video Speed Controller, работает в Опере и Хроме.

Работает с ютубом, вимио и почти всеми платформами видеовещания. Смотрю мастер-класс Дмитрия Шатрова «Lightroom classic: все новинки 2018 — 2021» на скорости 2,2

Можно использовать горячие клавиши, например: S — замедление, D — ускорение.

Скриншоты с официального гитхаба проекта. Можно поменять настройки скорости, задать стандартные скорости видеороликов.

Парсинг сайтов через питон модулем selenium

Работа идет через модуль selenium, для него нужно скачать Chrome driver и браузер Chrome.
Важно чтобы версия браузера и Chrome driver была одна и та же

Версию браузера смотрим Справка → О браузере, и сверяемся с версией хром драйвер.

Чтобы точно быть уверенным, что все работает установите библиотеку selenium, импортируйте ее и запустите браузер через хром драйвер.

pip install selenium
from selenium.webdriver import Chrome
browser = Chrome ("d:\del\chromedriver_win32\chromedriver.exe")
Если все корректно, запускается хром в режиме: «Браузером управляет тестовое ПО»

В тестовом браузере будут выполнятся все команды.

Импортируем необходимые библиотеки

from selenium.webdriver import Chrome
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait as wait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import NoSuchElementException
from bs4 import BeautifulSoup
from time import sleep

Переход на сайт

url = "https://bus.gov.ru/registry"
browser.get(url)
В тестовом браузере открылся сайт https://bus.gov.ru/registry

Нужно ввести в строке поиска «онкологический диспансер»

Способ 1

input_el = browser.find_element_by_tag_name("input")
input_el.send_keys("онкологический диспансер")
Вводится наименование в поле input

Нажать энтер или кнопку найти.

Нажатие кнопки энтер:

input_el.send_keys(Keys.ENTER)

Нажатие кнопки найти:

browser.find_element_by_xpath("/html/body/div[2]/ui-view/form/div[2]/div/div[2]/div/button").click()
После выполнения кода браузер ищет диспансеры

Дальше работаем как при простом парсинге сайта

soup = BeautifulSoup(browser.page_source, "lxml")
soup
В переменной soup вся текущая страница

Смотрим где содержится название учреждения и ссылка на него

soup.find ("a", class_="result__button").get("href")
soup.find("a",class_="result__title").text
Для получения части ссылки используем запрос get, для названия text

Чтобы не искать по всей странице, можно оставить информацию которая нам нужна, она содержится к контейнере c классом results

orgs=soup.findAll("div",class_="result")
orgs
Содержимое всех контейнеров result

Обработка текущей страницы

data = []
for el in orgs:
    name = el.find("a", class_="result__title").text
    link = "https://bus.gov.ru/registry" + el.find("a", class_="result__button").get("href")
    #print (name, link)
    data.append([name,link])
data
Названия учреждений и ссылка на страницу с описанием

Нужно нажимать на страницу «следующая»

next_button = browser.find_element_by_class_name("pagination__next")
next_button.click()

Код нажимает на элемент с классом pagination__next

Готовый код для сбора всей информации

url = 'https://bus.gov.ru/registry'
browser.get(url)
sleep(5)
input_el = browser.find_element_by_tag_name('input')
input_el.send_keys('онкологический диспансер')
input_el.send_keys(Keys.ENTER)
sleep(5)

data = []


for i in range(10):
    
    soup = BeautifulSoup(browser.page_source, "lxml")
    orgs = soup.findAll('div', class_='result')
    
    for el in orgs:
        name = el.find('a', class_='result__title').text
        link = "https://bus.gov.ru"+el.find('a', class_='result__button').get('href')
        print(name, link)
        

        data.append([name, link])
        
    print(len(data))
    try:
        next_button = browser.find_element_by_class_name('pagination__next')
        next_button.click()
    except NoSuchElementException:
        continue
    sleep(6)
Все данные попадают в таблицу data, в ней столбец с наименованием и ссылка
Подробный вебинар про модуль selenium, используется среда разработки Анаконда с модулем Юпитер. Во второй части парсится сайт с судебными решениями.

Парсинг сайтов через питон

Устанавливаем и импортируем библиотеки в питон

pip install requests
pip install pandas
import requests
from bs4 import BeautifulSoup
import pandas as pd
from time import sleep

Переменной url присваиваем ссылку на страницу кинопоиска, в переменную r результат гет запроса к этой странице

url = "https://www.kinopoisk.ru/s/type/film/list/1/find/%F1%E5%EA%F1/"
r = requests.get(url)
Текстовое содержимое страницы сайта — r.text

Переведем содержимое страницы в формат кода

soup = BeautifulSoup(r.text, "lxml")
Содержимое переменной — soup
При помощи инспектора кода находим контейнеры с названием фильма, годом, названием на языке оригинала и баллом кинопоиска
russian_name = soup.find('div',class_ = "element").find('div', class_ = "info").find('a', class_ = "js-serp-metrika").text
russian_name
original_name = soup.find('div',class_ = "element").find('span', class_ = "gray").text
original_name
year = soup.find('div',class_ = "element").find('span', class_ = "year").text
year
kinopoisk = soup.find('div',class_ = "element").find('div', class_ = "rating").text
kinopoisk
Все данные по первому фильму встречающемуся на странице

Находим контейнер с кусочком кода и генерируем ссылку на фильм

link = "https://www.kinopoisk.ru" +soup.find('div',class_ = "element").find('div', class_ = "info").find('a').get("data-url")
link
Готовая ссылка на фильм и контейнер содержащий ссылку

Можно составить код, который сделает таблицу, содержащую все фильмы с данной таблицы

data = []
films =soup.findAll("div",class_ = "element")
for film in films:
    russian_name = film.find('div', class_ = "info").find('a', class_ = "js-serp-metrika").text
    original_name = film.find('span', class_ = "gray").text
    
    try:
        year = film.find('span', class_ = "year").text
    except:
        year = ""
    
    try:
        kinopoisk = film.find('div', class_ = "rating").text
    except:
        kinopoisk = ""
    
    link = "https://www.kinopoisk.ru" +film.find('div', class_ = "info").find('a').get("data-url")
  
    #print (russian_name)
    #print (original_name)
    #print (year)
    #print (kinopoisk)
    #print (link)
    data.append([russian_name, original_name,year,kinopoisk,link  ])
Содержимое таблицы data

Мы можем собрать все фильмы с одной страницы. Теперь нужно сделать цикл для сбора со всех страниц данного раздела. В этом разделе 11 страниц, значит нужен цикл для формирования списка страниц

for page in range(1,12):
    url = f"https://www.kinopoisk.ru/s/type/film/list/1/find/%F1%E5%EA%F1/order/relevant/page/{str(page)}/"
    print(url)
Результат выполнения цикла for с полученными страницами

Теперь можно дополнить весь код. Не забываем про слип, так как на многих сайтах стоит защита от парсинга

data = []

for page in range(1,12):
    url = f"https://www.kinopoisk.ru/s/type/film/list/1/find/%F1%E5%EA%F1/order/relevant/page/{str(page)}/"
    print(url)
    
    r = requests.get(url)
    sleep(40)
    soup = BeautifulSoup(r.text, "lxml")
    
    films = soup.findAll("div", class_ ="element")

    for film in films:
        
        russian_name = film.find("div", class_="info").find("a").text
       # print(russian_name)
    
        original_name = film.find("div", class_="info").find("span", class_="gray").text
    
        year = film.find("span", class_="year").text

        try:
            year = film.find("div", class_= "span").text
        except:
            year = ""
        
        try:
            rate = film.find("div", class_= "rating").text
        except:
            rate = ""
    
        link = "https://www.kinopoisk.ru"+film.find("div", class_="info").find("a").get("data-url")
    
        data.append([russian_name, original_name, year, link])
По мере прохождения страниц, будут печатаются страницы на которых находится сейчас робот

Делаем заголовки таблицы и выгружаем в файл csv

header = ['russian_name', 'original_name', 'year', 'link']
df = pd.DataFrame(data, columns = header)
df.head()

df.to_csv("d:\data_kino.csv")
получившаяся таблица с выгрузкой

Можно и в питоне получить список всех ссылок на фильмы, работая с таблицей

for i in data:
    #print (i)
    link = i[3]
    print (link)
Вебинар курса «Веб-скрейпинг для журналистов. С программированием и без». Используется среда разработки Анаконда.

Правила

Чтобы работа была комфортной и предсказуемой для обеих сторон, я заранее обозначаю несколько правил и принципов взаимодействия. Они помогают избежать недоразумений и сосредоточиться на задачах.

Для некоторых такой формат может показаться неудобным. Если эти правила вам не подходят, скорее всего, нам будет сложно эффективно поработать, мы просто не подойдём друг другу — и это нормально.

Правила «НЕ»:

  • не давать денег в долг,
  • не обсуждать личные финансы,
  • не участвовать в сомнительных схемах (откаты, серые договорённости и т. п.),
  • не делать «чужую» работу,
  • не принимать и не передавать чужие вещи и передачи,
  • не покупать вещи по просьбе третьих лиц,
  • не передавать свой телефон для разговоров другим людям.

Правила работы:

  • работать по системе «Ресурс»
  • вся рабочая переписка только в группах, никакой «лички».

«Ресурс» — это система организации работы, основанная на доверии, взрослой ответственности и фокусе на результате, а не на присутствии или формальном рабочем времени. В ней нет контроля «кто где и сколько», но есть высокая требовательность к качеству, срокам и коммуникации.

Подробное описание принципов системы — в материале бюро:
https://bureau.ru/soviet/20090824/
Текст объёмный, но хорошо объясняет логику подхода и то, почему он работает.

Как преобразовать из юникода в читабельные символы

При подключении к базе данных в Power Bi русские буквы выглядят символами unicode:

"\u041e\u0442\u043c\u0435\u0442\u043a\u0430 \u0432\u0440\u0435\u043c\u0435\u043d\u0438": "23.12.2020 20:59:22", "\u0420\u0430\u043d\u0435\u0435 \u043f\u043e\u0441"
Так выдает база данных, я не нашел где в РowerBi, можно поменять кодировку.

Можно преобразовать их в читабельные буквы при помощи языка R, нашел похожее преобразование

Скрипт вносится в отдельном окне, для этого на панели инструментов нажмите R script
# 'dataset' holds the input data for this script
library(stringi)
string <- dataset$'Содержимое строки'
string2 <- stri_unescape_unicode(gsub("<U\\+(....)>", "\\\\u\\1", string))
outputRegEx <-within (dataset, {RegEx = string2})
Результат выполнения скрипта в новом столбце исходной таблицы.

UPD: Оказывается, в моем примере, был запрос json можно было не преобразовывать, а расшифровать содержание строки: Transform — Json.

Семинар по этим данным
8:34 — семинар на котором это показывают, временная метка
Для вызова команды Трансформ — нажмите правую клавишу мыши на столбце, который нужно трансформировать

Частотное разложение в фотографии

Андрей Журавлев показывает как быстро ретушировать фотографии раскладывая на частоты.

Разложение на частоты в фотошопе позволяет вынести на разные слои детали: мелкие на один слой, а крупные на второй.

Андрей Журавлев показывает как быстро ретушировать фотографии раскладывая на частоты. 5 часов, можно смотреть на скорости 2.

Подробный конспект ролика в ЖЖ Андрея.

Примеры можно покрутить самим: часть 1, 540 Мб, часть 2, 438 Мб

Панель ProfileSchoolPanel для фотошопа, 1 Мб

Инструкция по установки панели

У Андрея есть экшен, для разложения:

  • на две полосы частот с визуализацией по низкой и высокой частоте,
  • на три полосы частот,
  • упрощенной ретуши средних частот (Inverted High Pass)
Экшен от Андрея Журавлева, выбираем и нажимаем проиграть, делает тоже самое что и панель для 8 битных изображений.

Для ретуши:

  • На высоких частотах (мелкие детали) используем штамп с 100% непрозрачностью и резкими краями, активный слой.
  • На низких частотах (общий цвет) используем штамп с небольшой непрозрачностью (10—20%) и не резкими краями. На низких частотах можно использовать кисточку с взятием ближайшего цвета, активный слой и ниже.
  • На средних частотах используем штамп с 100% непрозрачностью и резкими краями, активный слой и ниже.

Пересаживаем текстуру кожи на низких частотах.

У Профайл школы есть экшен — панель частотного разложения

Как проверить правильность регулярного выражения

В справке гугл таблиц есть функции регулярных выражений:

  • REGEXREPLACE — заменяет часть текста заданного в регулярном выражении на другой текст.
  • REGEXEXTRACT — извлекает часть текста заданного в регулярном выражении.
  • REGEXMATCH — проверяет, соответствие текста регулярному выражению.

Есть большая справка по регулярным выражениям на гитхабе.

Регулярные выражения RE2, справка на гитхабе.

Для проверки правильности регулярных выражений я использую сервис regex101.com

Например: у нас есть выражение:

10000В01.001.001

Из него нужно оставить только первые цифры, все остальное отбросить, для этого используем регулярное выражение:

[0-9]+

оно состоит из двух частей:

  • [0-9] — цифра
  • + — любое количество, предыдущего условия, т. е. цифр.
Проверяем в сервисе regex101: 1. вводим регулярное выражение, 2. вводим что проверить и результат будет подсвечиваться, 3. справка, 4. результат работы.
Выбор метода по которому проводить анализ: я выбираю «multi line»

Выражение проверено, можно вставлять в гугл таблицу

=REGEXEXTRACT(A1;"[0-9]+")
В гугл таблицах: в ячейке A1 — исходный текст, в ячейке A3 — получаемый

В Power Bi тоже можно использовать регулярные выражения, только через скрипты R

В ролике очень подробно рассказывают про регулярные выражения и как использовать в языке R
Код: передается таблица, и идет сравнение строки ZipCode и регулярного выражения, результат передается в новый столбец RegEx
# 'dataset' holds the input data for this script
library("stringr")
pattern <-"99\\d{2}99$"
cleanRegEx <- str_extract(dataset$ZipCode, pattern)
outputRegEx <-within (dataset, {RegEx = cleanRegEx})

На гит хабе Zeeshan Ahmad выложил описание и примеры на русском языке по регулярным выражениям

У Алексея Куличевского есть видео, по которому можно учиться работать с регулярными выражениями

Алексей рекомендует шпаргалку по регулярным выражениям

Ранее Ctrl + ↓