Как скачать html страницу python
Перейти к содержимому

Как скачать html страницу python

  • автор:

Как сохранить html страницу без знаков вопроса?

Если открывать такой такой сайт после сохранения появляются знаки вопроса вместо текста или картинок.

Отслеживать
задан 5 дек 2022 в 0:39
17 1 1 серебряный знак 5 5 бронзовых знаков

Вообще ничего не появляется, даже знаки вопроса. Access denied Error code 1020 . В браузере то же самое. Если это сайт под логином и паролем, вряд ли SO сможет помочь.

5 дек 2022 в 1:19
open(‘file.html’, ‘w’, encoding=’utf-8′)
5 дек 2022 в 2:46

1 ответ 1

Сортировка: Сброс на вариант по умолчанию

На Linux Ваш код сработает правильно. Скорее всего Вы выполняете его в Windows. А это значит, что файл создается в кодировке Windows-1251. А в html разметке в head указано, что файл браузер должен читать как utf-8. Необходимо немного изменить код:

import requests url = "https://www.templatemonster.com/ru/backgrounds/231926.html" r = requests.get(url) with open('file.html', 'w', encoding="utf-8") as file: file.write(r.text) 

Отслеживать
ответ дан 5 дек 2022 в 3:06
2,075 1 1 золотой знак 3 3 серебряных знака 11 11 бронзовых знаков
Так и есть.На линукс все работало нормально, а на виндовс нет.Спасибо.
5 дек 2022 в 20:10

  • python
  • html
    Важное на Мете
Похожие

Подписаться на ленту

Лента вопроса

Для подписки на ленту скопируйте и вставьте эту ссылку в вашу программу для чтения RSS.

Дизайн сайта / логотип © 2023 Stack Exchange Inc; пользовательские материалы лицензированы в соответствии с CC BY-SA . rev 2023.11.15.1019

Нажимая «Принять все файлы cookie» вы соглашаетесь, что Stack Exchange может хранить файлы cookie на вашем устройстве и раскрывать информацию в соответствии с нашей Политикой в отношении файлов cookie.

Получить HTML содержимое веб-страницы с помощью Python

Python предоставляет несколько способов сделать это в своей стандартной библиотеке . Вероятно, самый популярный способ загрузки файла — через HTTP с помощью модуля urllib . Метод urllib.request — это модуль Python для извлечения URL-адресов. Он предлагает очень простой интерфейс в виде функции urlopen. Это позволяет получать URL-адреса с использованием различных протоколов. urllib.request.urlopen() , откройте URL-адрес URL, который может быть строкой или объектом Request.

from urllib.request import urlopen html = urlopen("http://net-informations.com/about.htm") print(html.read())

(1 оценок, среднее: 5,00 из 5)

Похожие новости

Какое использование лямбда в Python?

Какое использование лямбда в Python?

Разница между @staticmethod и @classmethod в Python

Разница между @staticmethod и @classmethod в Python

Что означает __name __ == ‘__ main__’ в Python?

Что означает __name __ == ‘__ main__’ в Python?
  • Книги по 1С
  • Книги по Assembler
  • Книги по Android
  • Книги по C#
  • Книги по C++
  • Книги по CSS
  • Книги по Delphi
  • Книги по HTML
  • Книги по JavaScript
  • Книги по Java
  • Книги по MySql
  • Книги по Php
  • Книги по Python
  • Книги по Pascal

Скачивание любого сайта с помощью Python себе на компьютер

Сегодня я Вам расскажу про интересную библиотеку для Python под названием Pywebcopy.

​PyWebCopy – бесплатный инструмент для копирования отдельных веб-страниц или же полного копирования сайта на жесткий диск.

Модуль обладает такими полезными методами как:

  • save_webpage() — для сохранения одной страницы;
  • save_website() — позволяет копировать сайт целиком.

Как предупреждают разработчики используйте save_website() аккуратно, т.к метод отправляет множество запросов, что может повлечь за собой значительную нагрузку на сервер.

Итак, не будем тянуть и приступим к коду. Сначала скачаем необходимые библиотеки:

pip install pywebcopy
pip install validators

Теперь приступаем к написанию скрипта. Для начала импортируем заранее установленные библиотеки:

from pywebcopy import save_webpage, save_website import validators

Теперь напишем блоки, которые будут скачивать весь веб-сайт или его отдельную страницу:

def webpage(url, folder, name): save_webpage( url=url, project_folder=folder, project_name=name, bypass_robots=True, debug=True, open_in_browser=True, delay=None, threaded=False, ) def website(url, folder, name): save_website( url=url, project_folder=folder, project_name=name, bypass_robots=True, debug=True, open_in_browser=True, delay=None, threaded=False, )

Блок webpage скачивает отдельную страницу сайта по ссылке url в папку folder и называет папку с сайтом name. Блок website скачивает весь сайт, а не его отдельную страницу.

Теперь напишем блок, который будет выводить текст красного цвета в терминал, для вывода ошибок.

def warning(text): print("\033[1m\033[31m<>\033[0m".format(text))

Теперь соединяем всё это вместе:

print("""Выберите цифру: 1 - Сохранить страницу 2 - Сохранить сайт""") b=False while b==False: try: a = int(input()) if a==1 or a==2: b=True else: warning("Выберите корректный номер!") except: warning("Только цифры!") c=False while c==False: url = input("Введите ссылку: ") if validators.url(url): c=True else: warning("Некорректная ссылка!") folder=input("Куда сохранять: ") name=input("Название проекта: ") if a==1: webpage(url, folder, name) else: website(url, folder, name)

В этом куске кода мы просим пользователя выбрать один из вариантов, или скачать весь сайт или только одну его страницу. Потом делаем проверку того, что пользователь ввел цифру, и что это число равно 1 либо 2. Потом с помощью библиотеки validators проверяем корректность введённой пользователем ссылки, если такая ссылка существует, то просим пользователя ввести путь к папке в которую будет сохранен сайт. А потом просим ввести название проекта. После чего, если все данные введены верно, то начинается закачка сайта на Ваш компьютер.

Ну вроде бы всё. Теперь Вы можете скачивать любой сайт к себе на компьютер. Но будьте окуратны с этим скриптом, так как если попытаться скачать весь сайт YouTube, то комп просто ляжет от огромного размера данных. Удачи!

Вот весь исходный код данного скрипта:

from pywebcopy import save_webpage, save_website import validators def warning(text): print("\033[1m\033[31m<>\033[0m".format(text)) def webpage(url, folder, name): save_webpage( url=url, project_folder=folder, project_name=name, bypass_robots=True, debug=True, open_in_browser=True, delay=None, threaded=False, ) def website(url, folder, name): save_website( url=url, project_folder=folder, project_name=name, bypass_robots=True, debug=True, open_in_browser=True, delay=None, threaded=False, ) print("""Выберите цифру: 1 - Сохранить страницу 2 - Сохранить сайт""") b=False while b==False: try: a = int(input()) if a==1 or a==2: b=True else: warning("Выберите корректный номер!") except: warning("Только цифры!") c=False while c==False: url = input("Введите ссылку: ") if validators.url(url): c=True else: warning("Некорректная ссылка!") folder=input("Куда сохранять: ") name=input("Название проекта: ") if a==1: webpage(url, folder, name) else: website(url, folder, name)

Скрапинг сайта с помощью Python: гайд для новичков

Пишем простой скрапер на Python для сайта с объявлениями о недвижимости. Получаем готовый очищенный готовый к экспорту датасет.

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

Отличие от вызовов API

Альтернативный метод получения данных сайта — вызовы API. Взаимодействие с API — это официально предоставляемый владельцем сайта способ получения данных прямо из БД или обычных файлов. Обычно для этого требуется разрешение владельца сайта и специальный токен. Однако апи доступен не всегда, поэтому скрапинг так привлекателен, однако его законность вызывает вопросы.

Юридические соображения

Скрапинг может нарушать копирайт или правила использования сайта, особенно когда он используется для получения прибыли, конкурентного преимущества или причинения ущерба (например из-за слишком частых запросов). Однако скрапинг публично доступен и используется для личного использования, академических целей или безвредного некоммерческого использования.
Если данные являются платными, требуют регистрации, имеют явную защиту от скрапинга, содержат конфиденциальные данные или личные данные пользователей, то нужно избегать любого из видов скрапинга.

Установка Beautiful Soup в Python

Beautiful Soup — это Python библиотека для скрапинга данных сайтов через HTML код.
Установите последнюю версию библиотеки.

$ pip install beautifulsoup4 

Чтобы делать запросы, установите requests (библиотеку для отправки HTTP запросов):

$ pip install requests 

Импортируйте библиотеки в файле Python или Jupiter notebook:

from bs4 import BeautifulSoup import requests 

И несколько стандартных библиотек, которые потребуются для скрапинга на Python:

import re from re import sub from decimal import Decimal import io from datetime import datetime import pandas as pd 

Введение

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

Предположим, что запрос приведет к странице результатов, которая выглядит следующим образом:

Как только мы узнаем, в каких элементах сайта хранятся необходимые данные, нам нужно придумать логику скрапинга, которая позволит нам получить всю нужную информацию из каждого объявления.
Нам предстоит ответить на следующие вопросы:

  1. Как получить одну точку данных для одного свойства (например данные из тега price в первом объявлении)?
  2. Как получить все точки данных для одного свойства со всей страницы (например все теги price с одной страницы)?
  3. Как получить все точки данных для одного свойства всех страниц с результатами (например все теги price со всех страниц с результатами)?
  4. Как устранить несоответствие, когда данные могут быть разных типов (например, есть некоторые объявления, в которых в поле цены указана цена по запросу. В конечном итоге у нас будет столбец, состоящий из числовых и строковых значений, что в нашем случае не позволяет провести анализ)?
  5. Как лучше извлечь сложную информацию (Например, предположим, что каждое объявление содержит информацию об общественном транспорте, например “0,5 мили до станции метро XY”)?

Логика получения одной точки данных

Все примеры кода для скрапинга на Python можно найти в Jupiter Notebook файле на GitHub автора.

Запрос кода сайта

Во-первых, мы используем поисковый запрос, который мы сделали в браузере в скрипте Python:

# поиск в определённой зоне url = 'https://www.website.com/london/page_size=25&q=london&pn=1' # делаем запрос и получаем html html_text = requests.get(url).text # используем парсер lxml soup = BeautifulSoup(html_text, 'lxml') 

Переменная soup содержит полный HTML-код страницы с результатами поиска.

Поиск тегов-свойств

Для этого нам потребуется браузер. Некоторые популярные браузеры предлагают удобный способ получения информации о конкретном элементе напрямую. В Google Chrome вы можете выбрать любой элемент сайта и, нажав правой кнопкой, выбрать пункт “Исследовать элемент” . Справа откроется код сайта с выделенным элементом.

HTML классы и атрибут id

HTML-классы и id в основном используются для ссылки на класс в таблице стилей CSS, чтобы данные могли отображаться согласованным образом.
В приведенном выше примере, класс, используемый для получения информации о ценах из одного объявления, также применяется для получения цен из других объявлений (что соответствует основной цели класса).

Обратите внимание, что HTML-класс также может ссылаться на ценники за пределами раздела объявлений (например, специальные предложения, которые не связаны с поисковым запросом, но все равно отображаются на странице результатов). Однако для целей этой статьи мы фокусируемся только на ценах в объявлениях о недвижимости.
Вот почему мы сначала ориентируемся на объявление и ищем HTML-класс только в исходном коде для конкретного объявления:

# используем парсер lxml soup = BeautifulSoup(html_text, 'lxml') # находим одно объявление ad = soup.find('div', class_ = 'css-ad-wrapper-123456') # находим цену price = ad.find('p', class_ = 'css-aaabbbccc').text 

Использование .text в конце метода find() позволяет нам возвращать только обычный текст, как показано в браузере. Без .text он вернет весь исходный код строки HTML, на которую ссылается класс:

Скрапинг сайта с помощью Python: гайд для новичков 1

Важное примечание: нам всегда нужно указывать элемент, в данном случае это p.

Логика получения всех точек данных с одной страницы

Чтобы получить ценники для всех объявлений, мы применяем метод find.all() вместо find():

ads = ad.find_all('p', class_ = 'css-ad-wrapper-123456') 

Переменная ads теперь содержит HTML-код для каждого объявления на первой странице результатов в виде списка списков. Этот формат хранения очень полезен, так как он позволяет получить доступ к исходному коду для конкретных объявлений по индексу.

Чтобы получить все ценники, мы используем словарь для сбора данных:

map = <> id = 0 # получаем все элементы ads = ad.find_all('p', class_ = 'css-ad-wrapper-123456') for i in range(len(ads)): ad = ads[i] id += 1 map[id] = <> # находим цену price = ad.find('p', class_ = 'css-aaabbbccc').text # находим адрес address = ad.find('p', class_ = 'css-address-123456').text map[id]["address"] = address map[id]["price"] = price 

Важное примечание: использование идентификатора позволяет находить объявления в словаре:

Получение точек данных со всех страниц

Обычно результаты поиска либо разбиваются на страницы, либо бесконечно прокручиваются вниз.

Вариант 1. Веб-сайт с пагинацией

URL-адреса, полученные в результате поискового запроса, обычно содержат информацию о текущем номере страницы.

Как видно на рисунке выше, окончание URL-адреса относится к номеру страницы результатов.

Важное примечание: номер страницы в URL-адресе обычно становится видимым со второй страницы. Использование базового URL-адреса с дополнительным фрагментом &pn=1 для вызова первой страницы по-прежнему будет работать (в большинстве случаев).

Применение одного цикла for-loop поверх другого позволяет нам перебирать страницы результатов:

url = 'https://www.website.com/london/page_size=25&q=london&pn=' map = <> id = 0 # максимальное количество страниц max_pages = 15 for p in range(max_pages): cur_url = url + str(p + 1) print("Скрапинг страницы №: %d" % (p + 1)) html_text = requests.get(cur_url).text soup = BeautifulSoup(html_text, 'lxml') ads = soup.find_all('div', class_ = 'css-ad-wrapper-123456') for i in range(len(ads)): ad = ads[i] id += 1 map[id] = <> price = ad.find('p', class_ = 'css-aaabbbccc').text address = ad.find('p', class_ = 'css-address-123456').text map[id]["address"] = address map[id]["price"] = price 

Определение последней страницы результатов

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

Чтобы решить эту проблему, мы будем проверять, есть ли на странице кнопка с такой ссылкой:

url = 'https://www.website.com/london/page_size=25&q=london&pn=' map = <> id = 0 # используем очень большое число max_pages = 9999 for p in range(max_pages): cur_url = url + str(p + 1) print("Скрапинг страницы №: %d" % (p + 1)) html_text = requests.get(cur_url).text soup = BeautifulSoup(html_text, 'lxml') ads = soup.find_all('div', class_ = 'css-ad-wrapper-123456') # ищем ссылку в кнопке page_nav = soup.find_all('a', class_ = 'css-button-123456') if(len(page_nav) == 0): print("Максимальный номер страницы: %d" % (p)) break (. ) 

Вариант 2. Сайт с бесконечным скроллом

В таком случае HTML скрапер не сработает. Альтернативные методы мы обсудим в конце статьи.

Устранение несогласованности данных

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

Функция для определения аномалий

def is_skipped(price): ''' Определение цен, которые не являются ценами (например "Цена по запросу") ''' for i in range(len(price)): if(price[i] != '£' and price[i] != ',' and (not price[i].isdigit())): return True return False 

И применить его при сборе данных:

(. ) for i in range(len(ads)): ad = ads[i] id += 1 map[id] = <> price = ad.find('p', class_ = 'css-aaabbbccc').text # пропускаем объявление без корректной цены if(is_skipped(price)): continue map[id]["price"] = price 

Форматирование данных на лету

Мы могли заметить, что цена хранится в строке вместе с запятыми с символом валюты. Мы можем исправить это ещё на этапе скрапинга:

def to_num(price): value = Decimal(sub(r'[^\d.]', '', price)) return float(value) 

Используем эту функцию:

(. ) for i in range(len(ads)): ad = ads[i] id += 1 map[id] = <> price = ad.find('p', class_ = 'css-aaabbbccc').text if(is_dropped(price)): continue map[id]["price"] = to_num(price) (. ) 

Получение вложенных данных

Информация об общественном транспорте имеет вложенную структуру. Нам потребуются данные о расстоянии, названии станции и типе транспорта.

Отбор информации по правилам

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

map[id]["distance"] = [] map[id]["station"] = [] transport = ad.find_all('div', class_ = 'css-transport-123') for i in range(len(transport)): s = transport[i].text x = s.split(' miles ') map[id]["distance"].append(float(x[0])) map[id]["station"].append(x[1]) 

Первоначально переменная transport хранит два списка в списке, поскольку есть две строки информации об общественном транспорте (например, “0,3 мили Слоун-сквер”, “0,5 мили Южный Кенсингтон”). Мы перебираем эти списки, используя len транспорта в качестве значений индекса, и разделяем каждую строку на две переменные: расстояние и станцию.

Поиск дополнительных HTML атрибутов для визуальной информации

В коде страницы мы можем найти атрибут testid, который указывает на тип общественного транспорта. Он не отображается в браузере, но отвечает за изображение, которое отображается на странице. Для получения этих данных нам нужно использовать класс css-StyledIcon:

map[id]["distance"] = [] map[id]["station"] = [] map[id]["transport_type"] = [] transport = ad.find_all('div', class_ = 'css-transport-123') type = ad.find_all('span', class_ = 'css-StyledIcon') for i in range(len(transport)): s = transport[i].text x = s.split(' miles ') map[id]["distance"].append(float(x[0])) map[id]["station"].append(x[1]) map[id]["transport_type"].append(type[i]['testid']) 

Преобразование в датафрейм и экспорт в CSV

Когда скрапинг выполнен, все извлеченные данные доступны в словаре словарей.

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

result = [] cur_row = 0 for idx in range(len(map[1]["distance"])): result.append([]) result[cur_row].append(str(map[1]["uuid"])) result[cur_row].append(str(map[1]["price"])) result[cur_row].append(str(map[1]["address"])) result[cur_row].append(str(map[1]["distance"][idx])) result[cur_row].append(str(map[1]["station"][idx])) result[cur_row].append(str(map[1]["transport_type"][idx])) cur_row += 1 

Создаём датафрейм

df = pd.DataFrame(result, columns = ["ad_id", "price", "address", "distance", "station", "transport_type"]) 

Мы можем экспортировать датафрейм в CSV:

filename = 'test.csv' df.to_csv(filename) 

Преобразование всех объявлений в датафрейм:

result = [] cur_row = 0 for id in map.keys(): cur_price = map[id]["price"] cur_address = map[id]["address"] for idx in range(len(map[id]["distance"])): result.append([]) result[cur_row].append(int(cur_id)) result[cur_row].append(float(cur_price)) result[cur_row].append(str(cur_address)) result[cur_row].append(float(map[id]["distance"][idx])) result[cur_row].append(str(map[id]["station"][idx])) result[cur_row].append(str(map[id]["transport_type"][idx])) cur_row += 1 # преобразование в датафрейм df = pd.DataFrame(result, columns = ["ad_id", "price","address", "distance", "station", "transport_type"]) # экспорт в csv filename = 'test.csv' df.to_csv(filename) 

Мы это сделали! Теперь наш скрапер готов к тестированию.

Ограничения HTML скрапинга и его альтернативы

Этот пример показывает, насколько простым может быть скрапинг HTML на Python в стандартном случае. Для этого не нужно исследовать документацию. Это требует, скорее, творческого мышления, чем опыта веб-разработки.

Однако HTML скраперы имеют недостатки:

  • Можно получить доступ только к информации в HTML-коде, которая загружается непосредственно при вызове URL-адреса. Веб-сайты, которые требуют JavaScript и Ajax для загрузки контента, не будут работать.
  • HTML-классы или идентификаторы могут изменяться в связи с обновлениями веб-сайта.
  • Может быть легко обнаружен, если запросы кажутся аномальными для веб-сайта (например, очень большое количество запросов в течение короткого промежутка времени).
  • Shell скрипты — загружают всю страницу, с помощью регулярных выражений могут обрабатывать html.
  • Screen scraper — изображают реального пользователя, используют браузер (Selenium, PhantomJS).
  • ПО для скрапинга — рассчитаны на стандартные случаи, не требуют написания кода (webscraper.io).
  • Веб сервисы скраперы — не требуют написания кода, хорошо справляются со скрапингом, платные (zyte.com).

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *