Skip to main content
 首页 » 编程设计

python scrapy动态选择xpaths和css

2025年05月04日9sky-heaven

我不想在蜘蛛程序中对元素的 xpath 和 css 选择器进行硬编码。

相反,我想将它们保存在一个地方并在蜘蛛运行时动态提取它们。

请问这个功能有官方支持吗?

我尝试过的

我做了一个字典,键是元素名称,值是一个包含两个值的列表,第一个值用于 xpath,第二个值用于 css。

请您参考如下方法:

您可以定义一个类似于此的配置文件(借用自 the Scrapy tutorial ):

{ 
    "region": [["xpath", "//ul/li"]], 
    "fields": { 
        "title": [["xpath", "a/text()"]], 
        "link": [["xpath", "./a"], ["css", "::attr(href)"]], 
        "desc": [["xpath", "text()"]] 
    } 
} 

其中列表表示要应用的连续选择器表达式,可以是 CSS 选择器或 XPath 表达式。 例如,

  • [["xpath", "//ul/li"]] 表示“应用 XPath 表达式 //ul/li,即 sel。 xpath('//ul/li')
  • [["xpath", "./a"], ["css", "::attr(href)"]] 表示“应用 XPath 表达式 ./a ,CSS选择器::attr(href)(注意:这是非标准的,它是Scrapy的扩展),相当于sel.xpath('./a ').css('::attr(href)')

我添加了一个配置“区域”以在特定区域应用选择器

您可以将一个 JSON 字符串作为参数传递给您的蜘蛛 (-a argname=argvalue),并且您的参数可作为蜘蛛的一个属性使用 -- self.selconfig 在我的例子中。

爬虫代码:

from scrapy.spider import Spider 
from scrapy.selector import Selector 
from scrapy.item import Item, Field 
import json 
import pprint 
 
def apply_exp_list(selector, expression_list): 
    out = selector 
    for expr_type, expr_val in expression_list: 
        if expr_type == "xpath": 
            out = out.xpath(expr_val) 
        elif expr_type == "css": 
            out = out.css(expr_val) 
    return out 
 
class DmozItem(Item): 
    title = Field() 
    link = Field() 
    desc = Field() 
 
 
class DmozSpider(Spider): 
    name = "dmoz" 
    allowed_domains = ["dmoz.org"] 
    start_urls = [ 
       "http://www.dmoz.org/Computers/Programming/Languages/Python/Books/", 
       "http://www.dmoz.org/Computers/Programming/Languages/Python/Resources/" 
    ] 
 
    def parse(self, response): 
        sel = Selector(response) 
 
        config = json.loads(self.selconfig) 
        self.log("selector configuration: \n%s" % pprint.pformat(config)) 
 
        regions = apply_exp_list(sel, config["region"]) 
        items = [] 
        for region in regions: 
            item = DmozItem() 
            for field_name, exp_list in config["fields"].items(): 
                item[field_name] = apply_exp_list(region, exp_list).extract() 
            items.append(item) 
        return items 

在命令行上,例如:

paul@wheezy:~/tmp/stackoverflow$ scrapy runspider 21474657.py \ 
-a selconfig='{"fields": {"desc": [["xpath", "text()"]], "link": [["xpath", "./a"], ["css", "::attr(href)"]], "title": [["xpath", "a/text()"]]}, "region": [["xpath", "//ul/li"]]}' 

注意:我玩了一下,它可能比预期的要复杂一点,它让我想起了(免责声明:我自己的)parslepy元素。