Программно создавать подклассы - PullRequest
0 голосов
/ 12 марта 2019

Я использую Scrapy, чтобы сканировать набор похожих страниц (веб-комиксы). Поскольку эти страницы очень похожи, я написал класс под названием ComicCrawler, который содержит всю логику паука и некоторые переменные класса (start_url, next_selector и т. Д.). Затем я переопределяю эти переменные класса в конкретных классах для каждого паука.

Создание классов для каждого комика вручную затруднительно. Теперь я хочу указать атрибуты в файле JSON и создать классы во время выполнения (т. Е. применить шаблон фабрики (?) ). Как мне лучше всего это сделать?

В качестве альтернативы: есть ли способ запустить паука, не создавая класс для него? Редактировать: Основная проблема заключается в том, что Scrapy использует классы, а не экземпляры для своих пауков. В противном случае я просто сделал бы переменные экземпляра класса и покончил бы с этим.


Пример:

class ComicSpider(Spider):
  name = None
  start_url = None
  next_selector = None
  # ...

  # this class contains much more logic than shown here

  def start_requests(self):
    # something including / along the lines of...
    yield Request (self.start_url, self.parse)

  def parse(self, response):
    # something including / along the lines of...
    yield Request(response.css(self.next_selector).get(), self.parse)

в другом файле:

class SupernormalStep(ComicSpider):
  name = "SupernormalStep"
  start_url = "https://supernormalstep.com/archives/8"
  next_selector = "a.cc-next"

что я хочу:

myComics = {
  "SupernormalStep": {
    "start_url": "https://supernormalstep.com/archives/8",
    "next_selector": "a.cc-next"
  }, # ...
}

process = CrawlerProcess(get_project_settings())
for name, attributes in myComics:
  process.crawl(build_process(name, attributes))

PS: я ползу ответственно.

Ответы [ 2 ]

3 голосов
/ 13 марта 2019

Оператор class является декларативной оболочкой, использующей type напрямую.Предполагая, что process.crawl принимает класс в качестве аргумента,

process = CrawlerProcess(get_project_settings())
for name, attributes in myComics.items():
    process.crawl(type(name, (ComicSpider,), attributes))

type(name, (ComicSpider,), attributes) создаст класс с именем name, который будет наследоваться от ComicSpider и будет иметь атрибуты, определенные в attributes толковый словарь. Пример документации по Python.

0 голосов
/ 12 марта 2019

Поиск метаклассов. Это способ в Python динамически создавать новые классы. Что такое метаклассы в Python?

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...