Выполнение операции над каждым элементом списка

Я столкнулся с такой проблемой: есть класс с методом, который получает в качестве аргумента веб-ссылку, запрашивает страницу и парсит её.

В классе вызываю результат 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 шт):

Автор решения: Mike Lazko

Вероятнее всего вы хотите сделать что то вроде

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 из конструктора
  • удален и сам конструктор так как не стало в нем необходимости

Все еще возможны какие то ошибки так как тесты я не писал и делал рефакторинг в блокноте. Надеюсь вы сможете с ними побороться, успехов!

→ Ссылка