CSS
Animatable CSS properties
Добавление шрифтов на сайт
Современный справочник по HTML и CSS
Параметры requests.* методов
url: str | bytes - обязательный параметр, адрес куда стучимся
params: Any - get-параметры (?field1=value1&field2=value2) в виде словаря
data: Any | None - для передачи параметров POST, PUT
headers: Any | None - передача заголовков
cookies: Any | None - передача куки
files: Any | None - передача файла
auth: Any | None - кортеж для включения HTTP-аутентификации
timeout: Any | None - время ожидания отклика от сайта
allow_redirects: bool - разрешать редирект от этой страницы
proxies: Any | None - словарь протокола к URL-адресу прокси
hooks: Any | None - перехватчик событий
stream: Any | None - получить необработанный ответ сокета от сервера
verify: Any | None - логическое или строковое указание для проверки сертификата TLS сервера или нет
cert: Any | None - строка или кортеж, определяющий файл сертификата или ключ
json: Any | None - передача json
Остальные методы (по аналогии)
import requests
# GET
r = requests.get('url', params={"field1": "data1"})
# POST
r = requests.post('url', data={"field1": "data1"})
# UPDATE
r = requests.put('url', data={"field1": "data1"})
# PATCH аналогичен методу POST, но с двумя отличиями: он используется
# для частичных изменений ресурса и его нельзя использовать в HTML-формах.
r = requests.patch('url', data={'field1': 'data1'})
# DELETE
r = requests.delete('url')
# Метод HEAD запрашивает ответ, идентичный запросу GET, но без тела ответа.
r = requests.head('url')
Метод select
import requests
from bs4 import BeautifulSoup as bs
r = requests.get('https://pythonworld.ru/samouchitel-python')
text = r.text
soup = bs(text, "html.parser")
# получить первый элемент, то можно получить так
print(soup.title.text)
# можно получить так
print(soup.select("head > title")[0].text)
# получить родителя
print(soup.title.parent.name)
# получить тег
print(soup.title.name)
print("---------------------------------------------------------")
# список мета-тегов
meta = soup.select("head > meta")
for m in meta:
print(m)
# attrs - выдает словарь всех аттрибутов тега: {"attr": "value", ...}
for att, val in m.attrs.items():
print("....", att, val)
# можно удалить аттрибут
# del m['id']
print("---------------------------------------------------------")
# поиск по классу
a1 = soup.select("p.strikeout.body")
Метод find
import requests
from bs4 import BeautifulSoup as bs
r = requests.get('https://pythonworld.ru/samouchitel-python')
text = r.text
soup = bs(text, "html.parser")
# вложенный поиск
print(soup.find("head").find("title"))
# поиск первого элемента
soup.find(id="link3")
Метод find_all
import requests
from bs4 import BeautifulSoup as bs
r = requests.get('https://pythonworld.ru/samouchitel-python')
text = r.text
soup = bs(text, "html.parser")
print("---------------------------------------------------------")
# все дети
for child in soup.head.children:
print(child)
# все родители у первой ссылки
for parent in soup.find_all('a')[0].parents:
print(parent.name)
# предыдущий тег на уровне
print(soup.find_all('meta')[0].previous_sibling)
# следующий тег на уровне
print(soup.find_all('meta')[0].next_sibling)
# сразу все по тегам в виде списка
print(soup.find_all(["a", "b"]))
# если нужны все элементы по атрибуту
news_list1 = soup.find_all('h2', id='post_title')
# если нужны все элементы по классу
news_list2 = soup.find_all('h2', class_='post__title')
# все по идентификатору
ids = soup.find_all(id="link2")
# все элементы с href через регулярку
import re
a1 = soup.find_all(href=re.compile("elsie"))
# все у кого есть атрибут id
a2 = soup.find_all(id=True)
# все ссылки
for link in soup.find_all('a'):
print(link.get('href'))
# поиск по нескольким аттрибутам в виде словаря
a3 = soup.find_all(attrs={"data-foo": "value"})
# функция-фильтр поиска элементов
def has_six_characters(css_class):
return css_class is not None and len(css_class) == 3
soup.find_all(class_=has_six_characters)
# установить ограничение на количество элементов
a4 = soup.find_all("a", limit=2)
Асинхронный парсер BS4 + aiohttp
# pip install aiohttp
# pip install fake_useragent
from bs4 import BeautifulSoup as BS
import aiohttp
import asyncio
from fake_useragent import UserAgent
url = "https://nsk.rbc.ru/"
h = {"User-Agent": UserAgent().random}
async def main():
async with aiohttp.ClientSession() as session:
async with session.get(url, headers=h) as response:
content = await aiohttp.StreamReader.read(response.content)
soup = BS(content, "html.parser")
news = soup.find_all("span", {"class": "main__feed__title"})
d = []
for n in news:
# получаем ссылку на новость
link = n.parent.parent['href']
# получаем заголовок новости
header = n.text
d.append((header, link))
# делаем текст
t = ''
for i in d:
t += i[0] + ';' + i[1] + '\n'
# заносим текст в файл
with open("data2.csv", "w", encoding="utf-8") as f:
f.write(t)
if __name__ == "__main__":
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
Динамический BS4 + selenium
Сайт, который был выбран для парсинга, случайный. У него есть штука, при загрузке появляется спинер (ожидание данных с сервера), потом только выходят данные. Для этого использовал задержку nime.sleep.
from bs4 import BeautifulSoup as BS
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
import time
URL = "https://www.onlinetrade.ru/catalogue/noutbuki-c9/"
o = Options()
o.add_experimental_option("detach", True)
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=o)
# driver.maximize_window()
driver.get(URL)
# ставим задержку, чтобы прогрузилась страница
time.sleep(5)
text = driver.page_source
# создаем парсер
soup = BS(text, "html.parser")
# ищем все элементы по исследованному тегу и классу
items = soup.find_all("div", class_="indexGoods__item")
d = []
for n in items:
# получаем название товара
name = n.find("a", class_="indexGoods__item__name")
# получаем цену в виде 45 006 Р
price = n.find("span", itemprop="price")
# обрабатываем цену
price_edit = price.text.replace(" ", "")
d.append((name.text, int(price_edit[:-1])))
# вывод всех данных
for i in d:
print(i)
Парсер с обработкой ошибок от PythonToday
import requests
from bs4 import BeautifulSoup
import time
def test_request(url, retry=5):
headers = {
"accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
"user-agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.106 Safari/537.36"
}
try:
response = requests.get(url=url, headers=headers)
print(f"[+] {url} {response.status_code}")
except Exception as ex:
time.sleep(3)
if retry:
print(f"[INFO] retry={retry} => {url}")
return test_request(url, retry=(retry - 1))
else:
raise
else:
return response
def main():
with open("lesson10/books_urls.txt") as file:
books_urls = file.read().splitlines()
for book_url in books_urls:
# test_request(url=book_url)
try:
r = test_request(url=book_url)
soup = BeautifulSoup(r.text, "lxml")
print(f"{soup.title.text}\n{'-' * 20}")
except Exception as ex:
continue
if __name__ == "__main__":
main()
Асинхронный парсер от Denis
import asyncio
import aiohttp
import time
start_time = time.time()
all_data = []
async def get_page_data(session, category: str, page_id: int) -> str:
if page_id:
url = f'https://ozon.ru/brand/{category}/?page={page_id}'
else:
url = f'https://ozon.ru/brand/{category}/'
async with session.get(url) as resp:
assert resp.status == 200
print(f'get url: {url}')
resp_text = await resp.text()
all_data.append(resp_text)
return resp_text
async def load_site_data():
categories_list = ['playstation-79966341', 'adidas-144082850', 'bosch-7577796', 'lego-19159896']
async with aiohttp.ClientSession() as session:
tasks = []
for cat in categories_list:
for page_id in range(100):
# собираем все задачи в кучу
task = asyncio.create_task(get_page_data(session, cat, page_id))
tasks.append(task)
# process text and do whatever we need...
# Запускаем кучу задач
await asyncio.gather(*tasks)
asyncio.run(load_site_data())
end_time = time.time() - start_time
print(all_data)
print(f"\nExecution time: {end_time} seconds")
Создание документа.
Создавать файл будем с помощью библиотеки fpdf. Установим библиотеку:
pip install fpdf
И напишем небольшой код:
import fpdf
# ориентация Portrait LandScape
# измерения mm pt cm in
# форматы А3 A4 A5 letter legal
pdf = fpdf.FPDF(orientation='P', unit='mm', format='A4')
# создаем страницу
pdf.add_page()
# устанавливаем шрифт
pdf.set_font("Arial", size=12)
# устанавливаем точку, рамку, выравнивание, текст, ссылку
pdf.cell(190, 1, border=True, fill=True, ln=1, align="C")
pdf.cell(10, 5, link='http://yandex.ru', txt="Welcome to Python!", ln=3, align="L")
pdf.cell(190, 1, border=True, fill=True, ln=1, align="C")
# добавляем свой шрифт
pdf.add_font('calibri', '', 'C:\\Windows\\Fonts\\calibri.ttf', uni=True)
pdf.set_font('calibri', size=18)
pdf.set_text_color(220, 50, 50)
pdf.cell(190, 15, txt="Welcome to Python!", ln=1, align="C")
# вставляем картинку
pdf.image("logo.png", x=10, y=80, w=100)
# рисуем
pdf.line(10, 10, 10, 100)
pdf.set_line_width(1)
pdf.set_draw_color(255, 128, 0)
pdf.line(20, 20, 100, 20)
pdf.ellipse(10, 40, 10, 100, 'F')
pdf.set_fill_color(230, 230, 0)
pdf.rect(30, 30, 100, 50)
pdf.output("simple_demo.pdf")
HTML в PDF.
from fpdf import FPDF, HTMLMixin
class MyFPDF(FPDF, HTMLMixin):
pass
html = '''<h1 align="center">PyFPDF HTML Demo</h1>
<p>This is regular text</p>
<p>You can also <b>bold</b>, <i>italicize</i> or <u>underline</u>
'''
pdf = MyFPDF()
pdf.add_page()
pdf.write_html(html)
pdf.output('html.pdf')
docx to pdf
import os
import comtypes.client
wdFormatPDF = 17
in_file = os.path.abspath("filename1.docx")
out_file = os.path.abspath("filename1.pdf")
word = comtypes.client.CreateObject('Word.Application')
doc = word.Documents.Open(in_file)
doc.SaveAs(out_file, FileFormat=wdFormatPDF)
doc.Close()
word.Quit()
xlsx to pdf
Вариант сохранения отдельного листа
import os
import comtypes.client
wdFormatPDF = 17
in_file = os.path.abspath("filename2.xlsx")
out_file = os.path.abspath("filename2.pdf")
excel = comtypes.client.CreateObject('Excel.Application')
excel.Visible = False
excel.DisplayAlerts = False
doc = excel.Workbooks.Open(in_file)
# обязательно указать нужный лист
doc.WorkSheets("New_sheet2").Select()
doc.ActiveSheet.ExportAsFixedFormat(0, out_file)
doc.Close()
excel.Quit()