Метка: python

Поддельный User-Agent

Одна из примитивных защит сайтов от парсинга – проверка HTTP заголовка User-Agent, который содержит наименование веб-браузера или клиента, делающего запрос. Если этого заголовка нет, то сервер может не выполнить запрос, раскусив, что его делает робот, а не человек. Обход защиты – имитация реального User-Agent браузера библиотекой fake_useragent. Установка:

pip install fake_useragent

Использование:

from fake_useragent import UserAgent
ua = UserAgent()
print(ua.random)
# Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.90 Safari/537.36

ua.random – агент случайного браузера (с учетом статистики распространенности браузеров по миру). Также доступны агенты для конкретных браузеров: ua.ie, ua.msie, ua.opera, ua.chrome, ua.google, ua.firefox, ua.ff, ua.safari.

Пример отправки запроса через request:

from fake_useragent import UserAgent
import requests
ua = UserAgent()

# куда шлем (этот URL как раз ответит нам наш UA для проверки)
url = 'https://httpbin.org/user-agent'

# создаем заголовок
headers = {'User-Agent': ua.chrome}

# делаем запрос, передав заголовок
result = requests.get(url, headers=headers)
print(result.content)

Еще в классе есть метод ua.update(), что обновляет базу данных браузеров, если она устарела. Это медленный метод, он делает запрос на сервера. Его не нужно вызывать каждый раз.

Специально для канала @pyway. Подписывайтесь на мой канал в Телеграм @pyway 👈 

С Новым Годом 2020!

​​Дорогие друзья!

🎄 Поздравляю вас всех с наступающим Новым Годом 2020! 🎄

Желаю вам счастья, здоровья, хорошего настроения! Поменьше багов в коде и побольше интересных проектов! А также любви, путешествий, достижений, новых открытий и позитивных эмоций!

Я искренне рад и благодарен, что вы читаете наш сайт и канал. В новом году я буду радовать вас множеством свежих интересных статей! 🎇

🎅 А пока вот небольшой праздничный сюрприз: написал программу, которая приклеивает шапку и бороду Деда Мороза на лица из видео-файла или с камеры. Используются библиотеки OpenCV и face-recognition. Код доступен на GitHub. Буду рад вашим звездочкам 🌟

Демонстрация работы SantaMask

Спасибо за поддержку! 🥂

Специально для канала @pyway. Подписывайтесь на мой канал в Телеграм @pyway 👈 

​​Unicode по имени

Вы знали, что в строке Python 3 можно вставлять символы по их названию в юникод-таблице?

Допустим нужны вам стрелки:

>>> "\N{LEFTWARDS ARROW} EXIT \N{RIGHTWARDS ARROW}"
'← EXIT →'

Найти юникод символы и их имена удобно с помощью онлайн-сервисов

Да, конечно, в Python 3 вы можете прямо в код вставлять любые юникод символы без их кодов и имен. Но профессиональнее – вставлять символы по именам, потому что читатель вашего кода может видеть его другим шрифтом, где начертание символов отличается от вашего, или вообще эти символы не отображаются. Ерунда? А вот вам пример:

>>> "Hello" == "Hello"
False

Строки выглядят одинаково, но я спрятал в одной из них символ "\N{ZERO WIDTH JOINER}", поэтому они неравны:

>>> len("Hel‍lo")
6
>>> len("Hello")
5
>>> "Hello".encode('utf-8')
b'Hel\xe2\x80\x8dlo'
>>> "Hello".encode('utf-8')
b'Hello'

Примечание: если примеры выше не работает правильно при копировании кода с сайта, это из-за того, что спрятанный юникод символ неправильно отображается на сайта. В посте в Телеграм – код корректно копируется.

Специально для канала @pyway. Подписывайтесь на мой канал в Телеграм @pyway 👈 

​​collections.deque – очередь Python

deque – коллекция двухсторонней очереди, которая похожа на список, за исключением того, что добавлять и удалять элементы можно либо в начало (слева), либо в конец (справа). Можно использовать и как стек. Реализована через двусвязный список. Благодаря этому, операции добавления или удаления элемента с любого конца deque имеют сложность O(1). Доступ к произольному элементу – O(n).

Создание:

from collections import deque

d1 = deque() # пустая
d2 = deque([1, 2, 3])  # из любого iterable
d3 = deque(maxlen=5)  # максимальная длина

Методы

Метод append(x) – добавить элемент в конец.

Метод appendleft(x) – добавить элемент в начало.

Метод pop(x) – удалить и вернуть элемент с конца.

Метод popleft(x) – удалить и вернуть элемент с начала.

Схема методов deque

Метод clear() – очистить очередь.

Метод reverse() – развернуть очередь наоборот:

d = deque([1, 2, 3])
d.reverse()
print(d)  # deque([3, 2, 1])

Метод rotate(n) – последовательно переносит n элементов с конца в начало (если n отрицательно, то из начала в конец):

d = deque(range(8))
# deque([0, 1, 2, 3, 4, 5, 6, 7])
d.rotate(2)
# deque([6, 7, 0, 1, 2, 3, 4, 5])
d.rotate(-1)
# deque([7, 0, 1, 2, 3, 4, 5, 6])

Метод extend(iterable) – добавляет в конец все элементы iterable.

Метод extendleft(iterable) – добавляет в начало все элементы iterable (начиная с последнего элемента iterable):

d = deque()
d.extend([1, 2, 3])
d.extendleft([10, 20, 30])
print(d)  # deque([30, 20, 10, 1, 2, 3])

Метод insert(index, x) – вставить элемент x в индекс i (медленно).

d[index] – доступ к элементу по индексу (медленно).

len(d) – число элементов в очереди (тоже работает медленно).

Метод remove(value) – удаляет первое вхождение значения value (слева направо). Остальные элементы не трогаются.

Метод count(value) – количество элементов со значением value в очереди.

Максимальная длина

Если при создание deque задано maxlen, то длина очереди будет ограничена. Это значит, что если мы попытаемся вставить элемент в очередь длины (maxlen), то элемент с противоположного конца будет вытеснен, и длина очереди не изменится:

# максимальная длина 5
d = deque(maxlen=5) 

d.extend(range(10))
# deque([5, 6, 7, 8, 9], maxlen=5)
# затерлись первые 5 элементов

d.appendleft(100)
# слева вставим 100, девятка вылетит справа
# deque([100, 5, 6, 7, 8], maxlen=5)

d.append(200)
# справа вставим 200, сотня вылетит слева
# deque([5, 6, 7, 8, 200], maxlen=5)

Резюме: deque хороша, когда частый доступ осуществляется только к концам коллекции. Подходит для очередей (например, задач), стэка, алгоритма round-robin, подсчета бегущих средних и прочего. А если нужен доступ к элементам по индексу – лучше брать list.

Специально для канала @pyway. Подписывайтесь на мой канал в Телеграм @pyway 👈 

Узнать тип type() и проверить тип isinstance()

В Python у нас утиная динамическая типизация, поэтому бывает что нужно узнать тип переменной. Функция type() возвращает тип аргумента или, учитывая, что в Python – все класс, то класс аргумента. Результат можно сравнить с известным типом:

>>> i, s = 10, "hello"
>>> type(i)
<class 'int'>
>>> type(i) is int
True
>>> type(s) is str
True
>>> class A: pass
...
>>> a = A()
>>> type(a) is A
True

Можно создать экземпляр объекта того же класса, что и переменная:

>>> new_a = type(a)()
>>> type(new_a) == type(a)
True

⚠️ Нужно знать! type() не принимает во внимание наследование. Тип наследника отличается от типа родителя:

>>> class B(A): pass
...
>>> type(A()) is type(B())
False

Лучший способ проверить типы – функция isinstance(x, type) (instance англ. – экземпляр). Она возвращает True, если первый аргумент является экземпляром класса во втором аргументе:

>>> isinstance(i, int)
True
>>> isinstance(s, str)
True
>>> isinstance(a, A)
True

Функция поддерживает наследование:

class A: pass
class B(A): pass
b = B()
>>> isinstance(b, A)
True

И самое крутое: вторым аргументом допускается передать кортеж из типов, и isinstance вернет True, если хоть один из типов в кортеже подходит:

>>> isinstance(i, (int, float))
True
>>> isinstance(a, (A, B))
True

Загадка:

class A: ...
a = A()
class A: ...
print(isinstance(a, A))

Правильный ответ был False!

Объяснение. Динамическая натура Python позволяет переопределить класс во время интерпретации. Помните, как недавно я рассказывал про декораторы класса? Там мы подменяли один класс другим. Вот это из той же оперы. Тут мы подменили один класс, другим классом, отвязав имя А от старого класса и привязав его к новому. Старый класс А остался жив только как класс объекта в переменной a. Старого и нового классов разные адреса (id):

class A: ...
print(id(A))  # 140479777819720

a = A()

class A: ...
print(id(A))  # 140479777809672

isinstance(a, A)  # False

Специально для канала @pyway. Подписывайтесь на мой канал в Телеграм @pyway 👈