Scrapy,开发可扩展的蜘蛛 - 按元素属性提取Xpath

时间:2017-07-13 14:09:24

标签: python xpath scrapy scrapy-spider

所以我正在开展一个网络抓取项目,它实际上从20多个网站的列表中提取了大量产品信息(如价格,位置,名称等)......到目前为止,我已经创建了一个通用的MasterSpider(类似于这里讨论的内容:Creating a generic scrapy spider),我根据站点的特定架构继承并覆盖它。

然而,在基本上重复了很多代码并希望使这个项目可扩展之后,我已经开始着手推广我的MaterSpider,它可以扩展到其他网站,并且理想情况下使用像start_url这样的最小参数进行实例化。换句话说,我不是通过Xpath定位元素,而是跨域不一致,我现在正在寻找html标签属性值/文本值。

这适用于通用/一致目标,例如从起始页面识别类别链接(通常包含链接中的类别),但是找不到产品名称,价格等等。必须构建一个xpath条件列表(如@class = a或b或c / contains(。,'a')或contains(。,'b')),这样会破坏目的。

我意识到我也可以传递一些xpath条件来实例化蜘蛛,我可能只需要这样做,但我更愿意让它尽可能易于使用和扩展......

我的想法是在解析单个产品页面之前,发出寻找我想要的信息的虚拟请求,并向后工作以实际识别信息的xpath,然后在后续请求中使用。

所以我想知道是否有人对如何提取元素的Xpath有任何好的想法给出可以说它可以包含的标记值列表,或者内部的文本匹配...我实现了一系列的尝试 - 捕获可能会起作用,但这又是一种创可贴而不是解决方案,而且不是很具可扩展性。如果我必须使用像selenium或解析器这样的东西来做这个也是一个选项...

真正接受任何想法或新观点。

谢谢!

1 个答案:

答案 0 :(得分:0)

在工作中,我必须抓住成千上万的新闻网站,正如您所料,没有人适合所有解决方案。所以我们的策略是拥有一个"泛型"方法,通过启发式方法尝试提取所需的信息,对于麻烦的网站,我们将有一个特定的x路径列表。

所以我们的一般结构是这样的:

parsers = {
    "domain1": {
        "item1":  "//div...",
        "item2":  "//div...",
    },
    "domain2": {
        "item1":  "//div...",
        "item2":  "//div...",
    },
}

def parse(self, response):
    domain = urlparse(response.url).netloc # urlparse comes from urllib.parse
    try:
        parser = self.parsers[domain]
        return self.parse_with_parser(response, parser)
    except Exception as e:
        return self.parse_generic(response)

解析器dict我实际上保存在一个单独的文件中。您还可以将其保存在数据库或文件中,并在加载蜘蛛时访问信息,这样您就不必在每次需要更改内容时编辑爬虫。

编辑:

回答你问题的第二部分,根据你需要做的事情,你可以编写考虑到几个条件的xpath。例如:

"//a[contains(@class, 'foo') or contains(@class, 'bar')]"

甚至可能

"//a[contains(@class, 'foo') or contains(@class, 'bar')] | //div[@class='something'] | //td/span"

pipe operator" |"将允许你"链"可能包含您想要提取的内容的不同表达式。 A和/或对不同表达式的操作。