python scrapy动态选择xpaths和css

时间:2014-01-31 07:28:45

标签: python css python-2.7 xpath scrapy

我不想硬编码蜘蛛中我的物品的xpath和css选择器。

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

是否有任何官方支持此功能pelase?

我尝试了什么

我创建了一个字典,关键是项目名称,值是一个包含两个值的列表,第一个值用于xpath,第二个值用于css。

1 个答案:

答案 0 :(得分:0)

您可以定义与此类似的配置文件(从the Scrapy tutorial借用):

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

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

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

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

您可以将JSON字符串作为参数传递给您的蜘蛛(sel.xpath('./a').css('::attr(href)')),并且您的参数可以作为您的蜘蛛的属性 - -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

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