我用嵌套的if else
案例编写了这段代码,但我觉得它很丑陋,并且想知道是否有任何方法可以改进它(或者更好的方法来实现它)。
def do_something(self, response):
a_url = response.css('a.classA::attr(href)').extract_first()
if a_url:
a_url = a_url.split('&')[0]
else:
a_url = response.css('a.classB::attr(href)').extract_first()
if a_url:
a_url = a_url.split('&')[0]
else:
logger.error('get no url')
if a_url:
yield Request(
url=a_url,
dont_filter=True,
callback=self.do_next_thing
)
主要关注的是我想从响应中提取url / link,然后拆分并获取第一个元素。但 a_url 仅存在于两个(或可能更多)元素之一中。我无法直接执行拆分,因为 a_url 可能是NoneType
。我想尝试使用try except else
,但这似乎变得更加复杂。
有更好的解决方案吗?
答案 0 :(得分:4)
我认为你可以这样做:
def do_something(self, response):
a_url = (
response.css('a.classA::attr(href)').extract_first()
or
response.css('a.classB::attr(href)').extract_first()
)
if not a_url:
logger.error('get no url')
return # or raise an exception and let the caller do the logging
yield Request(
url=a_url.split('&')[0],
dont_filter=True,
callback=self.do_next_thing
)
这使用了or
operator:
表达式
x
或y
首先评估x
;如果x
为真,那么 返回值;否则,将评估y
并生成结果值 归还。
它还使用“早期返回”技术,即首先处理失败案例,然后可以在任何if
或else
之外完成“正常”案例。
答案 1 :(得分:2)
简化此代码的最佳方法是首先在scrappy中选择这两个类:
def do_something(self, response):
a_url = response.css("a.classA::attr(href), a.classB::attr(href)")
if a_url:
yield Request(
url=a_url.split('&')[0],
dont_filter=True,
callback=self.do_next_thing
)
else:
logger.error('get no url')
答案 2 :(得分:0)
您可能需要考虑将方法拆分为两个(稍后甚至三个)。因为在我看来,第一行更多的是准备而不是实际逻辑。像这样:
def prepare_something(self, response):
a_url = response.css('a.classA::attr(href)').extract_first()
if a_url:
return a_url.split('&')[0]
else:
a_url = response.css('a.classB::attr(href)').extract_first()
if a_url:
return a_url.split('&')[0]
else:
logger.error('get no url')
return None
def do_something(self, response):
a_url = self.prepare_something(response)
if a_url:
yield Request(
url=a_url,
dont_filter=True,
callback=self.do_next_thing
)
这样,imho,代码有点干净,你可以看到你可能想要重构prepare_something
方法,如下所示:
def get_a_url_part(self, response, path):
a_url = response.css(path).extract_first()
return a_url.split('&')[0] if a_url else None
def prepare_something(self, response):
a_url = self.get_a_url_part(response, 'a.classA::attr(href)')
b_url = self.get_a_url_part(response, 'a.classB::attr(href)')
return a_url if a_url else b_url
def do_something(self, response):
a_url = self.prepare_something(response)
if a_url:
yield Request(
url=a_url,
dont_filter=True,
callback=self.do_next_thing
)
从我的观点来看,这可以被视为一种改进。
问候:)