Уведомления

Группа в Telegram: @pythonsu
  • Начало
  • » Python для новичков
  • » Сохранение исходников страниц из файла в html (работает, но хотелось бы наставлений по качеству) [RSS Feed]

#1 Июль 20, 2018 11:07:11

Romanus
Зарегистрирован: 2018-07-19
Сообщения: 14
Репутация: +  0  -
Профиль   Отправить e-mail  

Сохранение исходников страниц из файла в html (работает, но хотелось бы наставлений по качеству)

Всем привет.
Уже 5 часов в питоне, пробую написать некоторые автоматизации, которые помогают в работе.

Код работал исправно, пока я не решил сделать его более гибким. Т.е. он сохраняет исходный код урла в файл. Всё круто.
В urls.txt - просто список урлов, каждый с новой строки.

Но, как только я захотел, чтобы он сохранял не в корень, а в {Domain}/{Date}/file.html - начались проблемы. По отдельности вроде работает и папки создает и файл кладет, но всё вместе - отказывается работать. Т.е. папка может быть уже создана (после взятия 1 url, а проверка на существование папки через try - раздувает код и всё равно не работает, уверен есть какой-то более явный способ).

Так же хотелось бы мнение специалистов - с for у меня 100% говнокод, который можно сделать лучше, т.е. чтобы он брал строку с удалением (но у меня в голове получается еще больший говнокод с получением line - удалением line и т.д.).

 import requests
import re
import linecache
import datetime
import os
from urllib.request import urlopen
from bs4 import BeautifulSoup
urls = open ('urls.txt')
date = str(datetime.datetime.now().date().strftime('%d.%m.%Y'))
numstr = 1
for url in urls.readlines():
    url = linecache.getline('urls.txt', numstr).rstrip()
    page = urlopen(url)
    source =  BeautifulSoup(page, "html.parser" ).encode('utf-8')
    domain = re.match(r'(?i)(?=http:\/\/|https:\/\/|ftp:\/\/)?([a-z0-9\-\.]+)?[a-z0-9\-]+(!?\.[a-z]{2,4})', url)
    filename = re.sub(r'(?i)(http:\/\/|https:\/\/|ftp:\/\/)?([a-z0-9\-\.]+)?[a-z0-9\-]+(!?\.[a-z]{2,4})', '', url)
    filename = re.sub(r'\/', '-', filename)
    os.mkdir(domain.group(0))
    os.mkdir(date)
    file = open (filename + 'backup.html', 'wb')
    file.write (source)
    file.close
    numstr = numstr + 1

Проблема:
 ---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-2-4fb49e3a7d5b> in <module>()
     18     filename = re.sub(r'(?i)(http:\/\/|https:\/\/|ftp:\/\/)?([a-z0-9\-\.]+)?[a-z0-9\-]+(!?\.[a-z]{2,4})', '', url)
     19     filename = re.sub(r'\/', '-', filename)
---> 20     os.mkdir(domain.group(0))
     21     os.mkdir(date)
     22 #             os.chdir(str(datetime.datetime.now().date().strftime('%d.%m.%Y'))
AttributeError: 'NoneType' object has no attribute 'group'

Ставит в тупик то, что print (domain.group(0)) - выдает корректное имя. И отдельно этот код работает и создает папку. Что же не так в итоговом файле?

Отредактировано Romanus (Июль 20, 2018 11:08:50)

Офлайн

#2 Июль 20, 2018 12:21:08

Rodegast
От: Пятигорск
Зарегистрирован: 2007-12-28
Сообщения: 2679
Репутация: +  182  -
Профиль   Отправить e-mail  

Сохранение исходников страниц из файла в html (работает, но хотелось бы наставлений по качеству)

> проверка на существование папки через try - раздувает код и всё равно не работает, уверен есть какой-то более явный способ

os.path.isdir
> Проблема

У тебя domain равен None. Это может произойти если например в файле есть неверные url, пустые строки или строки только из пробельных символов.



С дураками и сектантами не спорю, истину не ищу.
Ели кому-то правда не нравится, то заранее извиняюсь.

Офлайн

#3 Июль 20, 2018 14:06:55

Romanus
Зарегистрирован: 2018-07-19
Сообщения: 14
Репутация: +  0  -
Профиль   Отправить e-mail  

Сохранение исходников страниц из файла в html (работает, но хотелось бы наставлений по качеству)

Никак не понимал, почему domain в одном случае None, а в другом - имя домена.
невнимательно использовал re.match, а нужно было re.search.
А за isdir - спасибо

Сейчас всё работает, еще освоил немного функции, крайне полезная штука.
Рабочий код прилагаю.

Вопросы:
1) Задача-то решена - но код на мой взгляд раздут и идет слишком “в лоб”, куда покопать и как сделать его логичнее, проще и чище?
2) Вариант с перебором строк в цикле for с добавлением +1 (чтобы брать след. строку) - есть какое-то более верное решение типа просто брать 1 строку с удалением взятой строки и пустой строки (т.к. останется пустота)?
3) После создания папки - скрипт сидит в ней, нормальный ли вариант с переходом в “начало” через явное указание начального пути?
4) Любые замечания и указание на косяки будут кстати

 import requests
import re
import linecache
import datetime
import os
from urllib.request import urlopen
from bs4 import BeautifulSoup
urls = open ('urls.txt')
date = str(datetime.datetime.now().date().strftime('%d.%m.%Y'))
numstr = 1
def writefile(filename, source):
    file = open (filename + 'backup.html', 'wb')
    file.write (source)
    file.close
    
for url in urls.readlines():
    os.chdir (r'C:\Users\maest\PYTHON')
    url = linecache.getline('urls.txt', numstr).rstrip()
    page = urlopen(url)
    source =  BeautifulSoup(page, "html.parser" ).encode('utf-8')
    domain = re.search(r'(?i)(?=http:\/\/|https:\/\/|ftp:\/\/)?([a-z0-9\-\.]+)?[a-z0-9\-]+(!?\.[a-z]{2,4})', url)
    filename = re.sub(r'(?i)(http:\/\/|https:\/\/|ftp:\/\/)?([a-z0-9\-\.]+)?[a-z0-9\-]+(!?\.[a-z]{2,4})/', '', url)
    filename = re.sub(r'\/', '-', filename)
    if os.path.isdir (domain.group(0)):
#         print ("Global IF - Папка Домена существует - захожу")
        os.chdir (domain.group(0))
        if os.path.isdir (date):
#             print ("Second IF - Папка Даты существует - захожу")
            os.chdir (date)
            writefile(filename, source)
        else:
#             print ("Second ELSE - Папка Даты не существует - Создаю")
            os.mkdir (date)
            os.chdir (date)
            writefile(filename, source)
    else:
#         print ("Global ELSE - Папка Домена не существует - Создаю")
        os.mkdir (domain.group(0))
        os.chdir (domain.group(0))
        if os.path.isdir (date):
#             print ("Global ELSE IF - Папка Даты существует - захожу")
            os.chdir (date)
            writefile(filename, source)
        else:
#             print ("Global ELSE ELSE - Папка Даты не существует - Создаю")
            os.mkdir (date)
            os.chdir (date)
            writefile(filename, source)
    numstr = numstr + 1

Офлайн

#4 Июль 20, 2018 14:58:31

Rodegast
От: Пятигорск
Зарегистрирован: 2007-12-28
Сообщения: 2679
Репутация: +  182  -
Профиль   Отправить e-mail  

Сохранение исходников страниц из файла в html (работает, но хотелось бы наставлений по качеству)

Должно быть типа такого. Регулярки явно нужно переписывать, как работает не проверял.

 import re
import os
import datetime
 
from bs4 import BeautifulSoup
from urllib.request import urlopen
 
RE_DOMAIN = re.compile(r"(?i)(?=http:\/\/|https:\/\/|ftp:\/\/)?([a-z0-9\-\.]+)?[a-z0-9\-]+(!?\.[a-z]{2,4})")
RE_FILENAME = re.compile(r"(?i)(http:\/\/|https:\/\/|ftp:\/\/)?([a-z0-9\-\.]+)?[a-z0-9\-]+(!?\.[a-z]{2,4})/")
DATE = str(datetime.datetime.now().date().strftime('%d.%m.%Y'))
 
def processor(url):
	source =  BeautifulSoup(urlopen(url), "html.parser" ).encode("utf-8")
	domain = re.search(RE_DOMAIN, url)
	if not os.path.isdir(domain):
		os.mkdir(domain)
	if not os.path.isdir(op.path.join([domain, DATE])):
		os.mkdir(op.path.join([domain, DATE]))
	filename = re.sub(r'\/', '-', re.sub(RE_FILENAME, '', url))
	with open(os.path.join([domain, DATE, filename+".html"])) as fail:
		fail.write(source)
 
for x in open ("urls.txt"):
	processor(x)



С дураками и сектантами не спорю, истину не ищу.
Ели кому-то правда не нравится, то заранее извиняюсь.

Офлайн

#5 Июль 20, 2018 15:04:28

Romanus
Зарегистрирован: 2018-07-19
Сообщения: 14
Репутация: +  0  -
Профиль   Отправить e-mail  

Сохранение исходников страниц из файла в html (работает, но хотелось бы наставлений по качеству)

в 2 раза короче
Буду разбираться с кодом и новыми методами в нем, спасибо.

Офлайн

#6 Июль 21, 2018 01:50:46

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 9716
Репутация: +  842  -
Профиль   Отправить e-mail  

Сохранение исходников страниц из файла в html (работает, но хотелось бы наставлений по качеству)

Romanus
Сейчас всё работает, еще освоил немного функции, крайне полезная штука.
О, прям как я в 2008-м Я тогда C89 изучал, это первый язык был. Бейзик не считаю, который был до этого, так как серьёзного программирования там было не много. Хотя была прога у меня на Бейзике (знал я тогда где-то треть Бейзика), которая вытягивала текст из баз данных ICQ (которая тогда была, как сегодня Telegram), ориентируясь на знакомые байтовые последовательности. Но именно эта прога дала мне понимание кайфа от собственной программы, которая за секунду делала то, что руками не сделаешь и за неделю, и которой больше ни у кого в мире не было. Так что всё имело смысл, даже Бейзик.

Romanus
Но, как только я захотел, чтобы он сохранял не в корень, а в {Domain}/{Date}/file.html - начались проблемы.
Эти данные должны формироваться внутри функции и возвращаться наружу. При этом сама эта функция может также вызывать функцию для формирования имени файла. А функция формирования имени файла может вызывать функцию для формирования расширения файла. При этом функция создания всего пути не знает, что существует функция формирования расширения файла.

Пример такого абстрагирования через функции
Romanus
  
def writefile(filename, source):
    file = open (filename + 'backup.html', 'wb')
    file.write (source)
    file.close
Вот, например, оно будет так работать неделю, а потом тебе надо будет поменять backup.html на другую строку, что ты будешь делать?

  
def get_filename():
    today = get_today()
    if today == 'monday':
        return 'backup.html'
    else:
        return 'backup.txt'
 
def get_today():
    return 'monday'
 
def writefile(filename, source):
    file = open(filename, 'wb')
    file.write(source)
    file.close()
 
...
 
writefile(get_filename(), get_source())



Отредактировано py.user.next (Июль 21, 2018 01:55:57)

Офлайн

  • Начало
  • » Python для новичков
  • » Сохранение исходников страниц из файла в html (работает, но хотелось бы наставлений по качеству)[RSS Feed]

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version