Главная страница

Сам_себе_программист._Как_научиться_программировать_и_устроиться. Guide to Programming Professionally


Скачать 3.94 Mb.
НазваниеGuide to Programming Professionally
Дата25.02.2023
Размер3.94 Mb.
Формат файлаpdf
Имя файлаСам_себе_программист._Как_научиться_программировать_и_устроиться.pdf
ТипGuide
#954463
страница13 из 15
1   ...   7   8   9   10   11   12   13   14   15


, !
X  B
определяет сам контент страни- цы. Вместе теги создают ссылку. HTML-элементы могут содержать дан- ные. К примеру, помещение строки href="https://w ww.google.com"
внутрь
HTML-элемента a
дает браузеру понять, на какой сайт нужно добавить ссылку.
В языке HTML есть еще много чего, но для создания своего первого парсера кон- тента этих знаний вам будет достаточно.

173
Введение в инструменты программирования
Парсинг контента с сайта Google Новости
В данном разделе вы построите парсер контента , который собирает все исто- рии с сервиса Google Новости, извлекая все теги из HTML-кода этого сайта. На сайте Google Новости эти теги используются для создания ссылок на различные сайты, так что помимо некоторых дополнительных данных вы собе- рете все URL-адреса новостей, отображаемых на сайте. Вы воспользуетесь мо- дулем BeautifulSoup, чтобы выполнить парсинг HTML-кода сайта Google
Новости. Парсинг означает принятие формата вроде HTML и придание ему структуры при помощи языка программирования. К примеру, превращение дан- ных в объект. Для начала используйте следующую команду для установки модуля
BeautifulSoup на Ubuntu и Unix.
bash_ex58.sh
$ sudo pip install beautifulsoup4==4.4.1
>> Successfully insta lled beautifulsoup4-4.4.1
И на Windows (запустите командную строку от имени администратора).
bash_ex59.sh
C:\Python36\Scripts\pip3.exe install beautifulsoup4==4.4.1
>> Successfully installed beautifulsoup4-4.4.1
Для работы с URL-адресами у Python есть встроенный модуль urllib. Введи- те следующий код в новый файл Python:
Python_ex284.py
1
import urllib.request
2
from bs4 import BeautifulSoup
3
class Scraper:
4
def __init__(
self
,
5
site):
6 self
.site = site
7
def scrape(
self
):
8
pass
Метод __init__ принимает в качестве параметра сайт, с которого нужно со- брать данные. Позднее вы передадите в качестве параметра значение "https://
news.google.ru/"
. В классе Scraper есть метод scrape, который вы будете вызывать всякий раз, когда захотите собрать данные с переданного сайта.
Добавьте следующий код в ваш метод scrape:

174
Часть III
Python_ex285.py
1
def scrape(
self
):
2
r = urllib.request.urlopen(
self
.site)
3
html = r.read()
Функция urlopen() отправляет запрос на веб-сайт и возвращает объект
Response
, в котором сохранен HTML-код этого сайта вместе с дополнитель- ными данными. Функция response.read() возвращает HTML-код из объекта
Response
. Весь HTML-код с сайта содержится в переменной html.
Теперь вы готовы выполнить парсинг HTML-кода. Добавьте в функцию scrape новую строку кода, которая создаст объект BeautifulSoup, и передай- те в функцию в качестве параметра переменную html и строку "html.parser"
(поскольку вы выполняете парсинг HTML-контента).
Python_ex286.py
1
def scrape(
self
):
2
r = urllib.request.urlopen(
self
.site)
3
html = r.read()
4
parser = "html.parser"
5
sp = BeautifulSoup(html, parser)
Объект BeautifulSoup делает всю трудную работу и выполняет парсинг
HTML-кода. Теперь вы можете добавить в функцию scrape код, который вы- зывает метод  nd_all в объекте BeautifulSoup. Передайте в качестве пара- метра значение "a" (это сообщит функции, что нужно искать теги
) и метод вернет все URL-адреса, на которые ссылается сайт, в загруженном вами
HTML-коде.
Python_ex287.py
1
def scrape(
self
):
2
r = urllib.request.urlopen(
self
.site)
3
html = r.read()
4
parser = "html.parser"
5 sp = BeautifulSoup(html, parser)
6
for tag in sp. nd_all("a"):
7 url = tag.get("href")
8
if url is
None
:
9
continue
10
if "html" in url:
11
print("\n" + url)
Метод  nd_all возвращает итерируемый объект, который содержит най- денные методом объекты tag. При каждом прохождении цикла for перемен- ной tag присваивается значение нового объекта Tag. У каждого объекта Tag

175
Введение в инструменты программирования есть много переменных экземпляра, но вам нужно значение лишь переменной href
, содержащий все URL-адреса. Его можно получить путем вызова метода get и передачи в него значения "href" в качестве параметра. Наконец, вы про- веряете, содержит ли переменная url данные; содержит ли она строку "html"
(вам не нужно выводить внутренние ссылки), если содержит, вы выводите ее.
Ниже показан полный код парсера контента.
Python_ex288.py
1
import urllib.request
2
from bs4 import BeautifulSoup
3
class Scraper:
4
def __init__(
self
, site):
5
self
.site
= site
6
def scrape(
self
):
7
r = urllib.request.urlopen(
self
.site)
8
html = r.read()
9
parser = "html.parser"
10
sp = BeautifulSoup(html, parser)
11
for tag in sp. nd_all("a"):
12 url = tag.get("href")
13
if url is
None
:
14
continue
15
if "html" in url:
16 print("\n" + url)
17
news
= "https://news.google.ru/"
18
Scraper(news).scrape()
Когда вы запустите программу, вывод будет выглядеть примерно так:
>> https://regnum.ru/russian/fd-south/crimea/alushta.html
>> https://www.gazeta.ru/business/2017/11/01/10965968.shtml
>> https://www.segodnya.ua/regions/krym/v-okkupirovannom-kry- mu-zayavili-o-diversii-vzorvan-gazoprovod-1068509.html
>> http://www.vesti.ru/doc.html?id=2949606&cid=9
Теперь, когда вы умеете собирать ссылки с сайта Google Новости, ваши возмож- ности безграничны. Вы можете написать программу, которая будет анализировать наиболее часто употребляемые в заголовках слова. Можете разработать программу, которая будет оценивать «настроения» заголовков, чтобы узнать, существует ли кор- реляция с фондовым рынком. Благодаря парсингу контента вам доступна информа- ция со всего мира, и, я надеюсь, что вас это поражает так же сильно, как и меня.

Словарь терминов
HTML: язык, который организовывает структуру сайта.
HTML-элемент: аналогичен ключевому слову в программировании — инструк- тирует браузер сделать что-либо.
Парсер веб-контента: программа, извлекающая данные с веб-сайта.
Парсинг: парсинг означает принятие формата вроде HTML и придание ему структуры при помощи языка программирования. К примеру, превращение дан- ных в объект.
Практикум
Модифицируйте ваш парсер контента так, чтобы он сохранял найденные ссыл- ки в файл.
Решение: challenge_1.py.

177
Глава 21. Структуры данных
Вообще-то я утверждаю, что разница между плохим программистом и хорошим закл ючается в том, что именно он считает более важным — свой код или свои структуры данных. Плохие программисты беспокоятся о коде.
Хорошие программисты беспокоятся о структурах данных и их отношениях.
Линус Торвальдс
Структуры данных
Структура данных — это формат, используемый для хранения и организации информации. Структуры данных — фундаментальное понятие в программирова- нии, они встроены в большинство языков. Вы уже знаете, как пользоваться не- которыми встроенными в Python структурами данных — списками, кортежами и словарями . В этой главе вы научитесь создавать еще две структуры данных — сте- ки и очереди.
Стеки
Стек — это структура данных. Как и в список, в стек можно добавлять элементы и удалять их из него, но в отличие от списка, вы можете добавлять и удалять толь- ко последний элемент. Если у вас есть список [1, 2, 3], вы можете удалить из него любой элемент. Если у вас есть такой же стек, вы можете удалить лишь по- следний элемент, 3, и тогда стек будет иметь вид [1, 2]. Теперь можно удалить
2
, а после этого — 1, и стек станет пустым. Удаление элемента из стека обознача- ется термином pop. Если вы поместите 1 обратно в стек, он будет иметь вид [1], а если затем поместите двойку, то [1, 2]. Добавление элемента в стек обозна- чается словом push. Такой вид структуры данных, при котором последний поме-
ЧАСТЬ IV
Введение в информатику

178
Часть IV
щенный элемент является первым извлекаемым, называется структурой данных
«последним вошел — первым вышел» (LIFO, last-in-first-out).
LIFO можно представить как стопку тарелок. Если вы сложите пять тарелок одну на другую и захотите вытащить ту, что в самом низу, вам сначала придется убрать все верхние. Каждый фрагмент данных в стеке сродни тарелке, чтобы по- лучить к нему доступ, нужно избавиться от данных сверху.
В этом разделе вы построите стек. В Python есть библиотека с обеими струк- турами данных, описываемыми в этой главе, но чтобы понять, как они работают, нужно создать их самостоятельно. У стека будет пять методов: is_empty, push, pop
, peek и size. Метод is_empty возвращает значение True если ваш стек пуст, и False в противном случае. Метод push добавляет элемент на «вершину» стека, pop удаляет и возвращает элемент с «вершины» стека, peek возвращает этот эле- мент, но не удаляет его. Метод size возвращает целое число, представляющее ко- личество элементов в стеке. Вот как выглядит реализация стека в Python:
Python_ex289.py
1
class Stack:
2
def __init__(
self
):
3
self
.items
= []
4
def is_empty(
self
):
5
return
self
.items
== []
6
def push(
self
, item):
7
self
.items.append(item)
8
def pop(
self
):
9
return
self
.items.pop()
10
def peek(
self
):
11
last = len(
self
.items)
-1 12
return
self
.items[last]
13
def size(
self
):
14
return len(
self
.items)
Если вы создадите новый стек, он будет пуст, и метод is_empty вернет зна- чение True.
Python_ex290.py
1
stack
= Stack()
2
print(stack.is_empty())
>> True

179
Введение в информатику
Если вы добавите новый элемент в стек, метод is_empty вернет значение
False
Python_ex291.py
1
stack
= Stack()
2
stack.push(1)
3
print(stack.is_empty())
>> False
Вызовите метод pop, чтобы удалить элемент из стека, тогда метод is_empty снова вернет значение True.
Python_ex292.py
1
stack
= Stack()
2
stack.push(1)
3
item
= stack.pop()
4 print(item)
5
print(stack.is_empty())
>> 1
>> True
Наконец, вы можете заглянуть в содержимое стека и узнать его размер.
Python_ex293.py
1
stack
= Stack()
2
for i in range(0, 6):
3
stack.push(i)
4
print(stack.peek())
5
print(stack.size())
>> 5
>> 6
Изменение порядка символов строки
при помощи стека
Стек может изменять направление итерируемого элемента на обратное, по- скольку все, что вы поместите в стек, отделяется в обратном порядке. В этом разделе вы решите часто задаваемую на собеседованиях задачу — изменение по- рядка следования символов в строке с помощью стека путем помещения строки в стек и дальнейшего ее извлечения.

180
Часть IV
Python_ex294.py
1
class Stack:
2
def __init__(
self
):
3
self
.items
= []
4
def is_empty(
self
):
5
return self
.items
== []
6
def push(
self
, item):
7
self
.items.append(item)
8
def pop(
self
):
9
return self
.items.pop()
10
def peek(
self
):
11
last
= len(
self
.items)
-1 12
return self
.items[last]
13
def size(
self
):
14
return len(
self
.items)
15
stack
= Stack()
16
for c in "":
17
stack.push(c)
18
reverse
= ""
19
for i in range(len(stack.items)):
20
reverse += stack.pop()
21
print(reverse)
>> 
Сначала вы прошли через каждый символ строки "" и поместили его в стек. Затем вы перебрали стек, взяли каждый элемент из стека и поместили в пере- менную reverse. Как только итерирование завершилось, буквы в исходном слове расположились в обратном порядке, и программа вывела строку .
Очереди
Очередь — еще одна структура данных. Она тоже похожа на список; вы може- те добавлять в нее элементы и удалять их. Очередь также напоминает стек, по- скольку добавлять и удалять элементы можно лишь в определенном порядке.
В отличие от стека, где первый помещенный элемент является последним извле- каемым, очередь представляет собой структуру данных вида «первым вошел —

181
Введение в информатику
первым вышел» (FIFO , first-in-first-out): первый помещенный элемент является первым извлекаемым.
Представьте FIFO как очередь людей, желающих купить билеты в кино. Пер- вый человек в очереди — это первый человек, который купит билеты, второй че- ловек в очереди — второй, кто купит билеты, и так далее.
В этом разделе вы построите очередь, используя четыре метода: enqueue, dequeue
, is_empty и size. enqueue добавляет новый элемент в очередь; dequeue удаляет элемент из очереди; is_empty проверяет, пуста ли очередь, и возвращает со- ответственно True либо False; size возвращает количество элементов в очереди.
Python_ex295.py
1
class Queue:
2
def __init__(
self
):
3
self
.items
= []
4
def is_empty(
self
):
5
return self
.items
== []
6
def enqueue(self, item):
7
self
.items.insert(0, item)
8
def dequeue(
self
):
9
return
self
.items.pop()
10
def size(
self
):
11
return len(
self
.items)
Если вы создадите новую пустую очередь, метод is_empty вернет значение
True
Python_ex296.py
1
a_queue
= Queue()
2
print(a_queue.is_empty())
>> True
Добавьте в очередь элементы и узнайте ее размер.
Python_ex297.py
1
a_queue = Queue()
2
for i in range(5):
3
a_queue.enqueue(i)
4
print(a_queue.size())
>> 5

182
Часть IV
Удалите каждый элемент из очереди.
Python_ex298.py
1
a_queue
= Queue()
2
for i in range(5):
3
a_queue.enqueue(i)
4
for i in range(5):
5
print(a_queue.dequeue())
6
print()
7
print(a_queue.size())
>> 0
>> 1
>> 2
>> 3
>> 4
>>
>> 0
Очередь за билетами
При помощи очереди можно смоделировать ситуацию, когда люди выстроились в ряд и ждут, чтобы купить билеты на фильм.
Python_ex299.py
1
import time
2
import random
3
class Queue:
4
def __init__(
self
):
5
self
.items
= []
6
def is_empty(
self
):
7
return self
.items
== []
8
def enqueue(
self
, item):
9
self
.items.insert(0, item)
10
def dequeue(
self
):
11
return self
.items.pop()

183
Введение в информатику
12
def size(
self
):
13
return len(
self
.items)
14
def simulate_line(
self
, till_show, max_time):
15
pq
= Queue()
16
tix_sold
= []
17
for i in range(10):
18
pq.enqueue(" ƒ  "
+ str(i))
19
t_end
= time.time() + till_show
20
now
= time.time()
21
while now < t_end and not pq.is_empty():
22
now = time.time()
23
r = random.randint(0, max_time)
24
time.sleep(r)
25
person = pq.dequeue()
26
print(person)
27
tix_sold.append(person)
28
return tix_sold
29
queue
= Queue()
30
sold
= queue.simulate_line(5, 1)
31
print(sold)
>>  ƒ  0
>> [' ƒ  0', ' ƒ  1', ' ƒ  2', ...
Вначале вы создали функцию simulate_line, которая моделирует прода- жу билетов людям в очереди. Функция принимает два параметра: till_show и max_time
. Первый параметр является целым числом, представляющим число секунд, оставшихся до того момента, когда начнется фильм и уже не останется времени на покупку билетов. Второй параметр также является целым числом, представляющим максимальное количество времени в секундах, которое уходит на покупку билета одним человеком.
Внутри функции вы создаете новую пустую очередь и пустой список. Список будет отслеживать людей, купивших билет. Затем вы заполняете очередь одной сотней строк, начиная с " ƒ  0" и заканчивая " ƒ  99". Каж- дая строка в очереди представляет человека в очереди, желающего купить билет.
Во встроенном модуле time есть функция time. Она возвращает число с пла- вающей точкой, представляющее число секунд, прошедших с начала эпохи, мо- мента во времени (1 января 1970 года), который используется в качестве ссылки.

184
Часть IV
Если я вызову функцию time прямо сейчас, она вернет 1481849664.256039 — число секунд, прошедших с начала эпохи. Если спустя одну секунду я снова вызову эту функцию, число с плавающей точкой, возвращаемое ей, будет увеличено на 1.
Переменная t_end находит результат сложения значения функции time и числа секунд, переданного в переменной till_show. Этот результат обозначает момент в будущем.
Цикл while будет продолжать итерирование до тех пор, пока либо функция time не вернет значение, большее, чем значение t_end, либо пока очередь не станет пустой.
После этого вы используете функцию sleep из встроенного модуля time, чтобы случайное количество секунд между 0 и max_time интерпретатор Python ничего не делал. Вы указываете Python остановить выполнение кода, чтобы сы- митировать время, требующееся на продажу билета, а случайное количество времени используется для имитации того, что на каждую продажу билета уходит разное время.
После паузы, вызванной функцией sleep, вы извлекаете из очереди строку, представляющую человека, и помещаете ее в список tix_sold, который пред- ставляет человека, уже купившего билет.
Результатом этого кода будет функция, которая умеет продавать билеты лю- дям в очереди, продавая их больше или меньше в зависимости от переданных параметров и случайного значения.
Словарь терминов
FIFO: сокращение от англ. first-in-first-out — «первым вошел — первым вышел».
LIFO: сокращение от англ. last-in-first-out — «последним вошел — первым вышел».
Pop: удаление элемента из стека.
Push: добавление элемента в стек.
Очередь: структура данных вида «первым вошел — первым вышел».
Стек: структура данных вида «последним вошел — первым вышел».
Структура данных «первым вошел — первым вышел»: структура данных, в ко- торой первый помещенный элемент является первым извлекаемым.
Структура данных «последним вошел — первым вышел»: вид структуры дан- ных, при котором последний помещенный элемент является первым извлекае- мым.
Структура данных: формат, используемый для хранения и организации инфор- мации.
Эпох а: момент во времени, используемый в роли ссылки.
Практикум
1. Измените порядок символов строки " B  " при помощи стека.
2. Используйте стек, чтобы создать новый список с элементами списка [1, 2,
3, 4, 5]
в обратном порядке.
Решения: challenge1.py и challenge2.py.

185
Введение в информатику
1   ...   7   8   9   10   11   12   13   14   15


написать администратору сайта