Невозможно отучить людей изучать самые ненужные предметы.
Введение в CSS
Преимущества стилей
Добавления стилей
Типы носителей
Базовый синтаксис
Значения стилевых свойств
Селекторы тегов
Классы
CSS3
Надо знать обо всем понемножку, но все о немногом.
Идентификаторы
Контекстные селекторы
Соседние селекторы
Дочерние селекторы
Селекторы атрибутов
Универсальный селектор
Псевдоклассы
Псевдоэлементы
Кто умеет, тот делает. Кто не умеет, тот учит. Кто не умеет учить - становится деканом. (Т. Мартин)
Группирование
Наследование
Каскадирование
Валидация
Идентификаторы и классы
Написание эффективного кода
Вёрстка
Изображения
Текст
Цвет
Линии и рамки
Углы
Списки
Ссылки
Дизайны сайтов
Формы
Таблицы
CSS3
HTML5
Блог для вебмастеров
Новости мира Интернет
Сайтостроение
Ремонт и советы
Все новости
Справочник от А до Я
HTML, CSS, JavaScript
Афоризмы о учёбе
Статьи об афоризмах
Все Афоризмы
Помогли мы вам |
Первые два урока доступны целиком без платной подписки. Этот — почти целиком: за исключением последнего примера и домашнего задания.
Начнем, как всегда, с несложных вещей. В Python есть модуль с лаконичным названием os
, который (ты не поверишь!) предназначен для взаимодействия программы с операционной системой, в том числе для управления файлами.
Первым делом, конечно, нужно импортировать его в начале нашего скрипта:
import os
И теперь нам открываются разные интересные возможности. К примеру, мы можем получить путь к текущей папке. Сначала она совпадает с той, в которой ты был при запуске скрипта (даже если сам скрипт находится где‑то в другом месте), но по ходу исполнения программы мы можем менять это значение при помощи функции os.
.
# Возвращает путь к текущей рабочей папке
pth=os.getcwd()
print(pth)
# Устанавливает путь к текущей рабочей папке, в данном случае это диск D:/
os.chdir(r'D:/')
Если ты работаешь в Windows, то в пути к файлу или папке перед открывающей кавычкой указывай букву r
(что означает raw) или вместо одной косой черты в пути ставь две.
Попробуем получить список файлов с расширением .py, находящихся в текущей директории. Для этого используем модули os и fnmatch.
import os
import fnmatch
# В цикле, с помощью os.listdir('.') получим список файлов
# в текущей директории (точка в скобках как раз ее и обозначает)
for fname in os.listdir('.'):
# Если у текущего имени файла расширение .py, то печатаем его
if fnmatch.fnmatch(fname, '*.py'):
print(fname)
Модуль fnmatch позволяет искать в строках определенный текст, подходящий по маске к заданному шаблону:
*
заменяет любое количество любых символов;?
заменяет один любой символ;[seq]
заменяет любые символы из последовательности в квадратных скобках;[!seq]
заменяет любые символы, кроме тех, что присутствуют в квадратных скобках.Давай безжалостно удалим какой‑нибудь файл:
(os.remove(r'D:allmypasswords.txt'))
Переименуем файл:
import os
os.rename('lamer.txt','xakep.txt')
А теперь создадим папку по указанному пути и сразу же удалим ее. Для этого пригодится модуль shutil, где есть функция rmtree(
, которая удаляет папку вместе с содержимым.
import shutilos.makedirs(r'D:secretbeerphoto') # Создает все папки по указанному путиshutil.rmtree(r'D:secretbeerphoto') # Удаляет папку вместе с ее содержимым
Допустим, ты хочешь получить список всех файлов, содержащихся в папках по указанному пути (учитывая вложенные папки тоже), чтобы найти что‑то интересное. Скрипт будет выглядеть следующим образом:
Будь осторожен — скрипт в таком виде обшарит весь диск D. Если он у тебя есть и там много хлама, то процесс может затянуться.
import os
for root, dirs, files in os.walk(r'D:'):
for name in files:
fullname = os.path.join(root, name)
print(fullname)
if('pass' in fullname):
print('Бинго!!!')
Функция walk() модуля os принимает один обязательный аргумент — имя каталога. Она последовательно проходит все вложенные каталоги и возвращает объект‑генератор, из которого получают:
Генератор — это объект, который сразу при создании не вычисляет значения всех своих элементов. Этим генераторы отличаются от списков — те хранят в памяти все свои элементы, и удалить их можно только программно. Вычисления с помощью генераторов называются ленивыми, они экономят память. Подробнее мы рассмотрим генераторы в следующих уроках.
Сейчас покажу, как узнать размер любого файла, а также дату его модификации.
# Модуль для преобразования даты в приемлемый форматfrom datetime import datetimepath = r'C:Windowsnotepad.exe'# Получим размер файла в байтахsize = os.path.getsize(path)# А теперь в килобайтах# Две косые черты — это целочисленное делениеksize = size // 1024atime = os.path.getatime(path)# Дата последнего доступа в секундах с начала эпохиmtime = os.path.getmtime(path)# Дата последней модификации в секундах с начала эпохиprint ('Размер: ', ksize, ' KB')print ('Дата последнего использования: ', datetime.fromtimestamp(atime))print ('Дата последнего редактирования: ', datetime.fromtimestamp(mtime))
Для операционных систем Unix 1 января 1970, 00:00:00 (UTC) — точка отсчета времени, или «начало эпохи». Чаще всего время в компьютере вычисляется в виде прошедших с этого момента секунд и лишь затем переводится в удобный для человека вид.
Давай пошутим над юзером: создадим какой‑нибудь файл и будем постоянно его открывать с помощью той программы, которой этот файл обычно открывается в системе:
import os
# Модуль time понадобится для паузы, чтобы не слишком часто открывалось
import time
# Создаем текстовый файл
f=open('beer.txt','w',encoding='UTF-8')
f.write('СРОЧНО НАЛЕЙТЕ ХАКЕРУ ПИВА, ИНАЧЕ ЭТО НЕ ЗАКОНЧИТСЯ!!')
f.close()
while True:
# Открываем файл программой по умолчанию
os.startfile('beer.txt')
# Делаем паузу в одну секунду
time.sleep(1)
Ниже приведен список еще некоторых полезных команд:
os.path.basename('путь')
— возвращает название файла или папки в конце пути;os.path.dirname('путь')
— возвращает родительский путь к объекту пути;os.path.splitext('путь')
— разделяет путь на путь и расширение файла;os.path.exists('путь')
— существует ли путь до файла или папки;os.path.isfile('путь')
— является ли объект пути файлом (существующим);os.path.isdir('путь')
— является ли объект пути папкой (существующей).Регулярные выражения — это специальные шаблоны для поиска и замены строк в тексте. Вообще говоря, их вполне можно считать самостоятельным языком, и его изучение выходит за рамки этого цикла. Мы пройдемся по самым основам и по использованию регулярок в Python.
Подробнее о регэкспах ты можешь почитать в документации Python, в Википедии или в книге Джеффри Фридла, которая так и называется — «Регулярные выражения».
Мы не раз писали о полезных сайтах, которые помогают работать с регулярными выражениями: CyberChef, RegExr, txt2re. Помимо этого, можешь обратить внимание на сервис regex101.com и сайт RegexOne с интерактивным тренажером.
За работу с регулярными выражениями в Python отвечает модуль re. Первым делом импортируем его.
import re
В качестве простейшего паттерна мы можем использовать какое‑нибудь слово. Пусть по традиции это будет «пиво»:
import re
pattern = r"пиво"
string = "Хакер знает, что пиво играет во взломе решающую роль. Свежее пиво — ключ к сисадмину. Пока сисадмин ходит писать, можно сесть за его комп и внедрить троян."
result = re.search(pattern, string)
print(result.group(0))
Команда re.
ищет в тексте string
первое вхождение шаблона pattern
и возвращает группу строк, доступ к которым можно получить через метод .
. Но команда search
ищет только первое вхождение шаблона. Поэтому в нашем случае вернется всего один результат — слово «пиво», несмотря на то что в нашем тексте оно присутствует дважды.
Чтобы вернуть все вхождения шаблона в текст, используется команда re.
. Эта команда вернет список строк, которые присутствуют в тексте и совпадают с шаблоном.
import re
pattern = r"пиво"
string = "Хакер знает, что пиво играет во взломе решающую роль. Свежее пиво — ключ к сисадмину. Пока сисадмин ходит писать, можно сесть за его комп и внедрить троян."
result = re.findall(pattern, string)
print(result)
Обрати внимание, что шаблоны в регулярных выражениях имеют буковку r перед началом строки. Это так называемые сырые строки, в которых не работает символ экранирования с помощью обратного слеша . При этом «сырая» строка не может заканчиваться этим символом.
В предыдущих двух примерах программ в качестве шаблона pattern
для поиска строк ты использовал просто какое‑то слово. Но мощь регулярных выражений не в этом. Ты можешь заменять части шаблона специальными символами, чтобы под шаблон подходили не только конкретные слова, но и самые разные строки.
Давай, например, попробуем найти в тексте все слова, которые начинаются с «пи». Для этого используем специальный символ b
— он означает «начало слова». Сразу после него указываем, с чего должно начинаться слово, и напишем специальный символ w
, который означает, что дальше в шаблоне должны идти какие‑то буквы (плюс означает, что их может быть одна или больше) до тех пор, пока не встретится небуквенный символ (например, пробел или знак препинания). Шаблон будет выглядеть так: r"bпиw+"
.
pattern = r"bпиw+"string = "Хакер знает, что пиво играет во взломе решающую роль. Свежее пиво — ключ к сисадмину. Пока сисадмин ходит писать, можно сесть за его комп и внедрить троян."result = re.findall(pattern, string)print(result)
Краткая справка по специальным символамДавай попробуем выполнить чуть более сложную задачу. Найдем в тексте все email с доменом mail.
, если они там есть.
pattern = r"bw+@mail.ru"string = "Если вы хотите связаться с админом, пишите на почту admin@mail.ru. По другим вопросам обращайтесь на support@mail.ru."result = re.findall(pattern, string)print(result)
Как видишь, мы использовали тот же трюк, что и в прошлый раз, — написали специальный символ b
, чтобы обозначить начало слова, потом w+
, что значит «одна или больше букв», а затем @mail.
, заэкранировав точку, поскольку иначе она будет означать «любой символ».
Часто бывает нужно найти какой‑то элемент строки, окруженный двумя другими элементами. Например, это может быть URL. Чтобы выделить ту часть шаблона, которую нужно вернуть, используются скобки. Приведу пример, в котором ты получишь все адреса ссылок из какого‑то кусочка кода на HTML.
import re
string = 'Вы можете посмотреть карту сайта <a href="map.php">тутa>. Посетите также <a href="best.php"разделa>'
pattern = r'href="(.+?)"'
result = re.findall(pattern,string)
print(result)
В коде выше использовался паттерн r'href="(.
— в этом шаблоне искомая строка начинается с href="
и заканчивается еще одной двойной кавычкой. Скобки нужны для того, чтобы указать, какую часть подходящей под шаблон строки ты хочешь получить в переменную result
. Точка и плюс внутри скобок указывают, что внутри кавычек могут быть любые символы (кроме символа новой строки). Знак вопроса означает, что нужно остановиться перед первой же встреченной кавычкой.
Знак вопроса в регулярных выражениях используется в двух немного разных смыслах. Если он идет после одного символа, это значит, что символ может присутствовать или не присутствовать в строке. Если же вопросительный знак идет после группы символов, это означает «нежадный» (non-greedy) режим: такая регулярка будет стараться захватить как можно меньше символов.
Мы можем не только искать строки, но и заменять их чем‑то другим. Например, давай попробуем удалить из HTML-кода все теги. Для этого используется команда re.
.
import re
string = 'Вы можете посмотреть карту сайта <a href="map.php">тутa>. Посетите также <a href="best.php"разделa>'
pattern = r'<(.+?)>'
result = re.sub(pattern,'',string)
print(result)
Программа напечатает строку уже без тегов, так как мы заменили их пустой строкой.
Регулярные выражения — очень мощная штука. Освоив их, ты сможешь делать со строками почти все, что угодно, а в сочетании с кодом на Python — буквально что угодно. Для начала же можешь поэкспериментировать и изменить какие‑то из приведенных рецептов.
Пришла пора подробнее поговорить о функциях. Мы уже неоднократно вызывали разные функции — как встроенные в Python (например, print(
), так и из подключаемых модулей (например, urllib.
). Но что такое функция изнутри и как их делать самостоятельно?
Представь, что у тебя есть какой‑то набор команд, которые нужно выполнять несколько раз, изменяя лишь входные данные. Такие блоки команд обычно выносят в отдельные кусочки программы.
В объектно ориентированном программировании функции являются методами какого‑либо класса и пишутся через точку от его названия.
s='Hello, xakep!'
print(s) # Функция
s.lower() # Метод
У функции могут быть входные параметры — это одна или несколько переменных, которые пишутся в скобках после имени функции. При вызове функции ты можешь передать ей аргументы для этих параметров. Некоторые из параметров могут быть необязательными или иметь значение по умолчанию — на случай, если его не передадут.
Объявление функции начинается с ключевого слова def
, далее следует имя функции, параметры в скобках и программный код, отделенный четырьмя пробелами. Функция может возвращать одно или несколько значений с помощью ключевого слова return
. Оно, кстати, прекращает работу функции, и, если за ним идут какие‑то команды, они будут пропущены.
Для примера разберем простейшую функцию, которая будет принимать в качестве аргументов два любых числа и перемножать их, возвращая результат умножения. Назовем ее umn.
def umn(a, b):
c = a * b
return c
Теперь, когда ты описал функцию, далее в этой же программе можно ее вызывать.
a = int(input('Введите первое число: '))
b = int(input('Введите второе число: '))
с = umn(a, b)
print(c)
Иногда надо задать один из параметров как необязательный, установив для него значение по умолчанию.
def umn(a, b=10):
c = a * b
return c
Теперь если ты вызовешь функцию и не передашь ей второй аргумент, то она просто будет считать его равным десяти, то есть будет умножать любое переданное число на десять.
с=umn(5)
print(c)
Несмотря на то что параметр b
в данном случае равен по умолчанию 10 и необязателен для передачи в качестве второго аргумента, ты по‑прежнему можешь передавать второй аргумент, если это будет нужно, и тогда в качестве b
будет использовано не 10
, а переданное значение.
с=umn(5, b=20)
print(c)
Внутри программы мы можем вызывать созданную нами функцию сколько угодно раз.
Давай создадим программу, которая будет считать прибавку к зарплате за каждую уязвимость, которую хакер нашел на работе. У каждого хакера будет своя зарплата, в зависимости от его ранга, но начисление прибавки для всех работает по принципу «+2% к базовой зарплате за уязвимость, если таких уязвимостей найдено больше чем три».
Сделаем функцию, которая принимает в качестве аргументов размер зарплаты сотрудника и количество найденных уязвимостей. Для округления результата используем функцию round(
, которая округлит прибавку до целого числа.
def pribavka(zarplata, bugs):
k = 0
if bugs > 3:
k = round((bugs - 3) * 0.02 * zarplata)
return k
a = int(input('Введите зарплату сотрудника: '))
b = int(input('Введите количество найденных им уязвимостей за месяц: '))
c = pribavka(a, b)
print('В этом месяце прибавка к зарплате составит: ' + str(c))
Если функция должна возвращать больше одного значения, то можно перечислить их через запятую.
def myfunc(x):
a = x + 1
b = x * 2
return a, b
Функция будет возвращать список, но мы можем сразу присвоить возвращаемые значения каким‑нибудь переменным:
plusone, sum = myfunc(5)
Внутри функций вполне можно использовать переменные, которые встречались в коде программы до вызова функции. Но если внутри кода функции задать переменную с таким же именем, то эта переменная автоматически станет локальной и все дальнейшие изменения будут происходить с ней только в пределах функции.
Поясню на примере:
def boom(a, b):
z = 15
c = a * b * z
return c
z = 1
c = boom(15, 20)
print(z)
В результате выполнения программы ты увидишь единицу. Почему? Внутри кода функции мы присвоили переменной z
значение 15, и она стала локальной, и все изменения с ней будут происходить внутри функции, тогда как в основной программе ее значение будет по‑прежнему равно единице.
Это немного трудно понять, но на самом деле удобно. Если ты пишешь несколько похожих функций, то вполне можешь использовать внутри них одинаковые названия локальных переменных, не опасаясь, что они будут влиять как‑то друг на друга.
Переменные, объявленные вне функций, называются глобальными. Если ты хочешь изнутри функции изменить одну из них, то объяви ее внутри функции, использовав ключевое слово global
.
def addfive(num):
global a
a += num
a = 5
addfive(3)
print(a)
Эта программа напечатает 8. Обрати внимание, что мы ничего не возвращали через return
, а просто изменили глобальную переменную. Кстати, функция, в которой ничего не возвращается через return
, будет возвращать значение None
.
a = 5
print(addfive(3))
На экране выведется слово None
. Это бывает полезно, если функция возвращает что‑то только при выполнении каких‑то условий, а если они не выполнены, то выполнение не доходит до return
. Тогда можно проверить, не вернула ли она None
.
def isoneortwo(num):
if(num==1):
return 'Один'
if(num==2):
return 'Два'
print(isoneortwo(1))
print(isoneortwo(2))
print(isoneortwo(3))
Эта функция проверяет, равно ли значение единице или двойке, и если не равно, то вернет None
. Это можно дальше проверить при помощи if
:
if isoneortwo(3) is None:
print("Не 1 и не 2!")
Итак, мы научились создавать функции, вызывать их и возвращать из них параметры, а также использовать внутри функций глобальные переменные. С этого момента мы уже можем браться за относительно сложные примеры!
На этот раз мы создадим скрипт, который будет искать SQL-уязвимости по разным URL. Заранее создадим файл urls.
, в каждой строчке которого будут адреса сайтов, содержащие GET-параметры. Например:
http://www.taanilinna.com/index.php?id=325
https://www.925jewellery.co.uk/productlist.php?Group=3&pr=0
http://www.isbtweb.org/index.php?id=1493
Напишем скрипт, который получает список подобных URL из нашего файла и добавляет в каждый из GET-параметров знак кавычки, пытаясь вызвать ошибки SQL баз данных.
|
|