【问题标题】:list of functions PythonPython 函数列表
【发布时间】:2018-01-19 10:11:55
【问题描述】:

我有一个模式列表:

    patterns_trees = [response.css("#Header").xpath("//a/img/@src"), 
                      response.css("#HEADER").xpath("//a/img/@src"),
                      response.xpath("//header//a/img/@src"),
                      response.xpath("//a[@href='"+response.url+'/'+"']/img/@src"),
                      response.xpath("//a[@href='/']/img/@src")
                      ]

在我遍历它并找到正确的模式后,我必须将模式作为参数发送给回调函数

for pattern_tree in patterns_trees:
...
    pattern_response = scrapy.Request(...,..., meta={"pattern_tree": pattern_tree.extract_first()})

通过这样做,我得到了正则表达式的值而不是模式

我尝试过的事情:

我尝试将模式隔离在一个单独的类中,但仍然存在无法将它们存储为模式而是值的问题。

我尝试将它们保存为字符串,也许我可以让它工作,但是

存储函数列表最有效的方法是什么

更新:可能的解决方案,但过于硬编码,当我想添加更多模式时问题太大:

def patter_0(response):
    response.css("#Header").xpath("//a/img/@src")    
def patter_1(response):
    response.css("#HEADER").xpath("//a/img/@src")
.....
class patternTrees:
    patterns = [patter_0,...,patter_n]

    def length_patterns(self):
        return len(patterns)

【问题讨论】:

  • 特定模式是否应该与特定功能相关联?
  • meta 你发送.extract_first(),括号会导致它执行。尝试发送.extract_first(不带括号)来发送实际函数。
  • @Magnus 是的,我希望每个模式都有一个特定的函数,以便我可以向它发送参数
  • @Swier 不,这不是问题,有或没有那个函数pattern_tree 已经是一个计算结果
  • 您可以使用对象response 是一个实例来访问其方法。对于字符串,您可以这样做:[str.upper, str.lower][0]('test') -> 'TEST'

标签: python python-3.x list function reference


【解决方案1】:

如果您愿意考虑重新格式化您的操作列表,那么这是一个不错的解决方案。我已将操作列表更改为元组列表。每个元组包含(引用)适当的函数,以及另一个由参数组成的元组。

向列表中添加新操作相当容易:只需指定要使用的函数和适当的参数。

如果您想在下一个操作中使用一个操作的结果作为参数:您必须从 execute() 返回值并在 for 循环中处理它 em>。

我已经用 prints() 替换了对 response 的调用,以便您可以轻松地对其进行测试。

def response_css_ARG_xpath_ARG(args):
    return "response.css(\"%s\").xpath(\"%s\")" % (args[0],args[1])
    #return response.css(args[0]).xpath(args[1])

def response_xpath_ARG(arg):
    return "return respons.xpath(\"%s\")" % (arg)
    #return response.xpath(arg)

def execute(function, args):
    response = function(args)
    # do whatever with response
    return response 

response_url = "https://whatever.com"


patterns_trees = [(response_css_ARG_xpath_ARG, ("#Header", "//a/img/@src")), 
                  (response_css_ARG_xpath_ARG, ("#HEADER", "//a/img/@src")),
                  (response_xpath_ARG, ("//header//a/img/@src")),
                  (response_xpath_ARG, ("//a[@href='"+response_url+"/"+"']/img/@src")),
                  (response_xpath_ARG, ("//a[@href='/']/img/@src"))]

for pattern_tree in patterns_trees:
    print(execute(pattern_tree[0], pattern_tree[1]))

注意 execute() 可以省略!取决于您是否需要处理结果。如果没有刽子手,你可以直接从循环中调用函数:

for pattern_tree in patterns_trees:
    print(pattern_tree[0](pattern_tree[1]))

【讨论】:

  • 也许这是最聪明的方法
【解决方案2】:

不确定我是否理解您要执行的操作,但您能否将列表设为 lambda 函数列表,如下所示:

patterns_trees = [
    lambda response : response.css("#Header").xpath("//a/img/@src"),
    ...
]

然后,在你的循环中:

for pattern_tree in patterns_trees:
    intermediate_response = scrapy.Request(...)  # without meta kwarg
    pattern_response = pattern_tree(intermediate_response)

或者离开metaresponse 对象有影响吗?

【讨论】:

    猜你喜欢
    • 2013-06-30
    • 2014-04-01
    • 1970-01-01
    • 2016-01-14
    • 2017-07-25
    • 1970-01-01
    • 2020-10-25
    • 2013-02-19
    • 2021-12-19
    相关资源
    最近更新 更多