Страницы

Поиск по вопросам

Показаны сообщения с ярлыком urllib. Показать все сообщения
Показаны сообщения с ярлыком urllib. Показать все сообщения

воскресенье, 29 марта 2020 г.

Извлечение домена из ссылки и поиск ссылок по имени домена

#python #парсер #url #urllib


Задача стоит такая:


Сверка ссылок по домену(*) из TXT №2 с TXT №1
Сохранение уникальны ссылок в отдельный TXT №3
Добавление уникальных ссылок в TXT №1


При сверке по  доменам - идет сверка только доменов сайта без: http:// и без https://
, так же при сверке по домену не учитывается все что после доменной зоны (.com , .ru
, и т.п.)

Я разделил программу на подзадачи и написал код на python 3.8:
Подзадачи: 

Исходные данные:

1.txt

http://site.com/
https://sit1e.com/vwdsvdfw/vwdefei/userpanel?cid=2
https://site.com/index.php?id=1
http://sit2e.com/
http://site.com/vwifow/fwviiwf?

2.txt

http://site.com/
https://sit1e213.com/vwdsvdfw/vwdefei/userpanel?cid=2
https://site.com/index.php?id=1
http://sit222e.com/
http://site.com/vwifow/fwviiwf?


1) Достать домены:

import re

f1 = open('1.txt')
f2 = open('2.txt')

filevar1 = f1.read()
filevar2 = f2.read()

domains1 = re.findall(r'\/\/([\w\-]+)', filevar1) 
domains2 = re.findall(r'\/\/([\w\-]+)', filevar2)

#Вывод доменов с новой строки 

with open('domains1.txt','w') as out:
    for domen in domains1:
        print(domen,file=out)
with open('domains2.txt','w') as out:
    for domen in domains2:
        print(domen,file=out)

f1.close()
f2.close()

input('Нажмите Enter, чтобы выйти из программы')


Результат работы участка кода:

domains1.txt

site
sit1e
site
sit2e
site

domains2.txt

site
sit1e213
site
sit222e
site


2) Сравнить домены:

import re

def diff():
    with open('result1.txt') as text_one, \
            open('result2.txt') as text_two:
        return set(text_one) ^ set(text_two)
if __name__ == '__main__':
    with open('output.txt', 'w') as result:
        for i in diff():
            result.write(i)

input('Нажмите Enter, чтобы выйти')


Выходные данные:

output.txt

sit1e
sit2e
sit1e213
sit222e


3) Найти исходные строки по выделенным доменам в исходных файлах и записать их в
отдельный файл.
с этим возникают проблемы. Не знаю какую регулярную функцию использовать.

PS: пока искал ответ на свой вопрос, то заметил, что моя программа не учитывает субдомены,
вроде для этого уже существует специальная функция в python: urlparse, но я не могу
понять как ее использовать.

Можно ли как-то сократить код программы, чтобы не писать 3-й блок программы?
Можно-ли реализовать эту задачу проще?
    


Ответы

Ответ 1



Для чтения доменов из файлов со ссылками можно использовать следующую функцию: from urllib.parse import urlparse def get_domains(filename): with open(filename) as f: return ['.'.join(urlparse(line.strip()).netloc.split('.')[:-1]) for line in f] Проверка: dom1 = get_domains(r'C:\temp\1.txt') dom2 = get_domains(r'C:\temp\2.txt') print(dom1) # ['site', 'sit1e', 'site', 'sit2e', 'site'] print(dom2) # ['site', 'sit1e213', 'site', 'sit222e', 'site'] Работа со списками доменов как со множествами - объединение, пересечение, симметрическая разность: In [31]: set(dom1) | set(dom2) Out[31]: {'sit1e', 'sit1e213', 'sit222e', 'sit2e', 'site'} In [32]: set(dom1) & set(dom2) Out[32]: {'site'} In [33]: set(dom1) ^ set(dom2) Out[33]: {'sit1e', 'sit1e213', 'sit222e', 'sit2e'} Поиск ссылок по списку доменов: import re def search_domains(filename, doms): with open(filename) as f: text = f.read() pat = r'(https?://[^./\r\n]*?\b(?:{})\b[^\r\n]*)'.format('|'.join(doms)) return re.findall(pat, text) Проверка: In [47]: doms = set(dom1) ^ set(dom2) In [48]: doms Out[48]: {'sit1e', 'sit1e213', 'sit222e', 'sit2e'} In [49]: search_domains(r'C:\temp\1.txt', doms) Out[49]: ['https://sit1e.com/vwdsvdfw/vwdefei/userpanel?cid=2', 'http://sit2e.com/'] In [50]: search_domains(r'C:\temp\2.txt', doms) Out[50]: ['https://sit1e213.com/vwdsvdfw/vwdefei/userpanel?cid=2', 'http://sit222e.com/'] PS с записью результатов в файл я думаю вы справитесь сами.

среда, 5 февраля 2020 г.

Как заставить urllib3 возвращать 307/301 ответы сервера?

#python #python_3x #urllib


При попытке получить ответ сервера по URL, который СОВЕРШЕННО ТОЧНО редиректит по
307 коду (по 301 скорее всего тоже), urllib3 возвращает 200-й ответ сервера, что дезинформирует. 
Нужно знать, когда страница возвращает 307-й ответ. Как быть?

Ниже привожу часть кода, которая у меня за это дело отвечает. Пробовал через Requests,
та же история.

from urllib.request import *
from urllib.error import *

    def __init__(self, urls):
        super().__init__()

        self.urls = urls

    def run(self):
        for url in self.urls:
            try:
                code = urlopen(url).getcode()
            except HTTPError as e:
                # Пусть будет исключение
                code = str(e)

    


Ответы

Ответ 1



Если использовать модуль requests, то при запросе можно указать параметр allow_redirects=False, тогда автоматическое перенаправление выполняться не будет: r = requests.get('http://ya.ru/') print(r) # print(r.url) # https://ya.ru/ - автоматически перенаправлено на https r = requests.get('http://ya.ru/', allow_redirects=False) print(r) # Документация: Redirection and History

Ответ 2



Модуль urllib автоматически ходит по перенаправлениям. Не знаю, по какому недоразумению отсутствует штатная возможность отключения этого, но можно написать свой отключающий handler: class NoRedirectHandler(urllib.request.HTTPRedirectHandler): def http_error_302(self, req, fp, code, msg, headers): return fp http_error_301 = http_error_303 = http_error_307 = http_error_302 Потом создаём opener с этим handler'ом: opener = urllib.request.build_opener(NoRedirectHandler()) Теперь можно отправлять свои запросы с помощью метода opener.open, но если хочется отключить обработку перенаправлений по умолчанию везде и сразу, то можно установить его по умолчанию: urllib.request.install_opener(opener) Теперь редиректы обрабатываться не будут: r = urllib.request.urlopen('http://ya.ru/') print(r.code) # → 302 print(r.url) # → http://ya.ru/ print(r.headers['Location']) # → https://ya.ru/

воскресенье, 12 января 2020 г.

Как обработать кириллические символы в urllib.request.urlopen()?

#python #http #python_3x #urllib


Здравствуйте! У меня такой вопрос, urllib.request.urlopen() не принимает кириллические
символы в http запросе,
Выполняю:

urllib.request.urlopen('http://exemple.com/sent?"русский_текст"')

получаю:
self._output(request.encode('ascii'))  UnicodeEncodeError: 'ascii' codec can't encode
characters in position 11-17: ordinal not in range(128)

Прочитав документацию по urllib.request понял, что urllib.request.urlopen() пытается
перевести мой запрос в кодировку latin 1 (iso8859-1) и именно на это он и ругается,
как правильно обработать запрос с кириллическими символами?    


Ответы

Ответ 1



urllib.request.urlopen('http://example.com/send?{0}'.format(quote_plus('"русский_текст"'))) или даже так: urlopen(urlunparse(('http', 'example.com', '/send', None, quote_plus('"русский текст"'), None), )) а вообще либой requests многие штуки чуточку удобнее делать

среда, 25 декабря 2019 г.

Как использовать urlib для адреса с кириллицей

#python #python_3x #urllib


Как правильно использовать urlib.request для получения кода страницы, при условии,
что в URL есть кириллица

UPD. Есть функция:

def get_html(url):
    return urllib.request.urlopen(url).read()


Она отдает html-код страницы по URL (да-да, кэп).
Она работает ровно до того момента как в заголовке появляется кириллица и интерпретатор
отдает ошибку: 


  UnicodeEncodeError: 'ascii' codec can't encode characters in position 10-18: ordinal
not in range(128)

    


Ответы

Ответ 1



В рамках протокола HTTP не-ASCII символы в URI не допускаются. Например кириллица может быть введена и отображена в адресной строке браузера, но браузер переводит эту строку запроса (в виде IRI) в правильный, с точки зрения протокола HTTP URI. Соответственно для имени хоста применяется Punycode, а для остальных компонентов URL-кодирование. В вашем случае можно воспользоваться дополнительной функцией для перевода из кириллического IRI в ASCII URI from urllib.parse import quote, urlsplit, urlunsplit def iri_to_uri(iri): parts = urlsplit(iri) uri = urlunsplit(( parts.scheme, parts.netloc.encode('idna').decode('ascii'), quote(parts.path), quote(parts.query, '='), quote(parts.fragment), )) return uri И вызывать вашу функцию так: content = get_html(iri_to_uri(url))

среда, 11 декабря 2019 г.

Скачивание файла через urllib

#python #urllib


Подскажите, пожалуйста, как скачать файл средствами python (urllib) доступный по
http и положить его рядом со скриптом?    


Ответы

Ответ 1



urllib -> urlopen - открывает файл по данной ему ссылке для чтения, далее можете его просто считать read(), открыть файл для бинарной записи, и записать в него то что прочитали по http. Пример скачивания эмблемки: import urllib logo = urllib.urlopen("http://www.google.com/images/srpr/logo3w.png").read() f = open("logo3w.png", "wb") f.write(logo) f.close() Также есть urllib.urlretrieve(url, [filname,[...]]) - по моему его предназначение именно для скачивания. import urllib destination = 'logo3w.png' url = 'http://www.google.com/images/srpr/logo3w.png' urllib.urlretrieve(url, destination)

Ответ 2



#!/usr/bin/env python3 from urllib.request import urlretrieve url = 'http://www.bing.com/az/hprichbg?p=rb/CollaredLorys_ROW927887560.jpg' destination = url.rsplit('/',1)[1] urlretrieve(url, destination) Чтобы сохранить читаемые русские имена, можно использовать более сложный способ вычисления имени файла url2filename(): #!/usr/bin/env python # -*- coding: utf-8 -*- import os import posixpath try: from urlparse import urlsplit from urllib import unquote except ImportError: # Python 3 from urllib.parse import urlsplit, unquote def url2filename(url): """Return basename corresponding to url. >>> print(url2filename('http://example.com/path/to/file%C3%80?opt=1')) fileÀ >>> print(url2filename('http://example.com/slash%2fname')) # '/' in name Traceback (most recent call last): ... ValueError """ urlpath = urlsplit(url).path basename = posixpath.basename(unquote(urlpath)) if (os.path.basename(basename) != basename or unquote(posixpath.basename(urlpath)) != basename): raise ValueError # reject '%2f' or 'dir%5Cbasename.ext' on Windows return basename Пример: local_filename, headers = urlretieve(url, url2filename(url))

Ответ 3



urllib.urlrertieve(url, filename)

Ответ 4



destination = url.rsplit('/',1)[1] - Здесь один момент не учтен, если url заканчивается на / то destination это пустая строка. Можно лимит поставить 2 и проверять длину. Пример: destination = url.rsplit('/',1)[2] if len(destination) == 0: destination = url.rsplit('/',1)[1]

Ответ 5



Отвечу для версии python3, будет так: import urllib.request logo = urllib.request.urlopen("http://www.marseille-tourisme.com/fileadmin/user_upload/plan_mars2013.jpg").read() f = open("plan_mars2013.jpg", "wb") f.write(logo) f.close()

Ответ 6



ответ в две строки) import urllib.request, urllib.parse, urllib.error urllib.request.urlretrieve('http://откуда_качаем.ком', './ложим_в_текущаю_папку')

суббота, 9 марта 2019 г.

Как обработать кириллические символы в urllib.request.urlopen()?

Здравствуйте! У меня такой вопрос, urllib.request.urlopen() не принимает кириллические символы в http запросе, Выполняю: urllib.request.urlopen('http://exemple.com/sent?"русский_текст"') получаю: self._output(request.encode('ascii')) UnicodeEncodeError: 'ascii' codec can't encode characters in position 11-17: ordinal not in range(128) Прочитав документацию по urllib.request понял, что urllib.request.urlopen() пытается перевести мой запрос в кодировку latin 1 (iso8859-1) и именно на это он и ругается, как правильно обработать запрос с кириллическими символами?


Ответ

urllib.request.urlopen('http://example.com/send?{0}'.format(quote_plus('"русский_текст"'))) или даже так: urlopen(urlunparse(('http', 'example.com', '/send', None, quote_plus('"русский текст"'), None), )) а вообще либой requests многие штуки чуточку удобнее делать

пятница, 7 декабря 2018 г.

Скачивание файла через urllib

Подскажите, пожалуйста, как скачать файл средствами python (urllib) доступный по http и положить его рядом со скриптом?


Ответ

urllib -> urlopen - открывает файл по данной ему ссылке для чтения, далее можете его просто считать read(), открыть файл для бинарной записи, и записать в него то что прочитали по http. Пример скачивания эмблемки:
import urllib logo = urllib.urlopen("http://www.google.com/images/srpr/logo3w.png").read() f = open("logo3w.png", "wb") f.write(logo) f.close()
Также есть urllib.urlretrieve(url, [filname,[...]]) - по моему его предназначение именно для скачивания.
import urllib destination = 'logo3w.png' url = 'http://www.google.com/images/srpr/logo3w.png' urllib.urlretrieve(url, destination)

четверг, 29 ноября 2018 г.

Как использовать urlib для адреса с кириллицей

Как правильно использовать urlib.request для получения кода страницы, при условии, что в URL есть кириллица
UPD. Есть функция:
def get_html(url): return urllib.request.urlopen(url).read()
Она отдает html-код страницы по URL (да-да, кэп). Она работает ровно до того момента как в заголовке появляется кириллица и интерпретатор отдает ошибку:
UnicodeEncodeError: 'ascii' codec can't encode characters in position 10-18: ordinal not in range(128)


Ответ

В рамках протокола HTTP не-ASCII символы в URI не допускаются. Например кириллица может быть введена и отображена в адресной строке браузера, но браузер переводит эту строку запроса (в виде IRI) в правильный, с точки зрения протокола HTTP URI. Соответственно для имени хоста применяется Punycode, а для остальных компонентов URL-кодирование
В вашем случае можно воспользоваться дополнительной функцией для перевода из кириллического IRI в ASCII URI
from urllib.parse import quote, urlsplit, urlunsplit
def iri_to_uri(iri): parts = urlsplit(iri) uri = urlunsplit(( parts.scheme, parts.netloc.encode('idna').decode('ascii'), quote(parts.path), quote(parts.query, '='), quote(parts.fragment), )) return uri
И вызывать вашу функцию так:
content = get_html(iri_to_uri(url))