Выполнение операции над каждым элементом списка
Я столкнулся с такой проблемой: есть класс с методом, который получает в качестве аргумента веб-ссылку, запрашивает страницу и парсит её.
В классе вызываю результат links, и все работает, но с условием, что в файле первая строка с адресом сайта. А мне нужно чтобы для каждой ссылки эта операция выполнялась отдельно. На выполнение уходит 2-5 секунд. Подскажите как это реализовать? Добавить второй класс? Добавить функцией в этот класс? Заранее спасибо! Вот весь код:
# -*- coding: utf-8 -*-
import os
import requests
import textwrap
from bs4 import BeautifulSoup
with open('links.txt', 'r') as f:
content = f.readlines()
content = [x.strip() for x in content]
for links in content:
print(links)
class GrabberArticle:
"""url - article address.
filename - file name used to save. Matches the last item in the URL path.
path - path to save article. Match with URL paths ([CUR_DIR]/host/path1/path2/...)
content_tags - tags for article processing.
wrap - сolumn width.
"""
# Set default values:
url = ""
filename = ""
path = ""
content_tags = ['p']
wrap = 80
def __init__(self, url_address):
self.url = url_address
# Get path and filename for saving article by splitting URL.
# If the URL ends with some.html, then the previous (-2) element
# of the path is taken to form the path and the filename = some.html.txt respectively.
path_arr = self.url.split('/')
if path_arr[-1] != '':
self.filename = path_arr[-1] + ".txt"
self.path = os.getcwd() + "/".join(path_arr[1:-1])
else:
self.filename = path_arr[-2] + ".txt"
self.path = os.getcwd() + "/".join(path_arr[1:-2])
if not os.path.exists(self.path):
os.makedirs(self.path)
def write_in_file(self, text):
# Write file in path, stored in self.path: "[CUR_DIR]/host/path_item1/path_item2/..."
# with filename, stored in self.filename
file = open(str(self.path) + '/' + str(self.filename), mode="w")
file.write(text)
file.close()
def get_text(self):
# return clear text of article
r = requests.get(self.url).text
soup = BeautifulSoup(r, 'html.parser')
content = soup.find_all(self.content_tags)
# Getting the entire tag content, described in self.content_tags.
wrapped_text = ""
for p in content:
# Skipping empty tags.
if p.text != '':
# Formatting links into view: [link]
links = p.find_all('a')
if links != '':
for link in links:
p.a.replace_with(link.text + str("[" + link['href'] + "]"))
# Text formatting in tags according to сolumn width (self.wrap).
wrapped_text += ''.join(textwrap.fill(p.text, self.wrap)) + "\n\n"
self.write_in_file(wrapped_text)
if __name__ == "__main__":
try:
mr = GrabberArticle(links)
mr.get_text()
print("Successfully processed")
except Exception:
print("Error processing URL")
Ответы (1 шт):
Вероятнее всего вы хотите сделать что то вроде
class GrabberArticle:
# Set default values:
content_tags = ['p']
wrap = 80
def process(self, url):
wrapped_text = self._get_text(url)
dir_path, filename = self._extract_dir_path_and_filename(url)
self._write_file(dir_path, filename, wrapped_text)
def _get_text(self, url):
# return clear text of article
r = requests.get(url).text
soup = BeautifulSoup(r, 'html.parser')
content = soup.find_all(self.content_tags)
# Getting the entire tag content, described in self.content_tags.
wrapped_text = ""
for p in content:
# Skipping empty tags.
if p.text != '':
# Formatting links into view: [link]
extracted_links = p.find_all('a')
if extracted_links:
for extracted_link in extracted_links:
p.a.replace_with(extracted_link.text + str("[" + extracted_link['href'] + "]"))
# Text formatting in tags according to сolumn width (self.wrap).
wrapped_text += ''.join(textwrap.fill(p.text, self.wrap)) + "\n\n"
return wrapped_text
def _extract_dir_path_and_filename(self, url):
# Get path and filename for saving article by splitting URL.
# If the URL ends with some.html, then the previous (-2) element
# of the path is taken to form the path and the filename = some.html.txt respectively.
path_arr = url.split('/')
if path_arr[-1] != '':
filename = path_arr[-1] + ".txt"
path = os.getcwd() + "/".join(path_arr[1:-1])
else:
filename = path_arr[-2] + ".txt"
path = os.getcwd() + "/".join(path_arr[1:-2])
return path, filename
def _write_file(self, path, filename, text):
# Write file in path, stored in self.path: "[CUR_DIR]/host/path_item1/path_item2/..."
# with filename, stored in self.filename
if not os.path.exists(path):
os.makedirs(path)
with open(str(path) + '/' + str(filename), mode="w") as file:
file.write(text)
grabber = GrabberArticle()
with open('links.txt', 'r') as file:
for line in file:
link = line.strip()
grabber.process(link)
Над исходным кодом были произведены следующие трансформации(рефакторинг):
- добавлен публичный метод
process - остальные методы сделаны внутренними(протектед) чтобы не отвлекать своим внимание при использовании класса при помощи добавления нижнего подчерка
def _any_method - все не константные поля удалены из состояния класса и инстанса, и передаются явно через аргументы методов и возвращаемое значение. так проще понимать код и тестировать
- выделен отдельный метод _extract_dir_path_and_filename из конструктора
- удален и сам конструктор так как не стало в нем необходимости
Все еще возможны какие то ошибки так как тесты я не писал и делал рефакторинг в блокноте. Надеюсь вы сможете с ними побороться, успехов!