自动检测来自用户给定项目的 Xpath 作为输入

Automatically detect Xpath from user given item as input

我正在编写一个 Flask 应用程序,它运行 Scrapy 蜘蛛来抓取给定的网站。 Flask 应用程序提供了一个 UI,它接受要报废的 URL 和一个要报废的 ITEM(比如 website 的职位)。

现在的问题是,蜘蛛如何自动检测用户给定 ITEM 的 Xpath ?????

以下是 spider 的代码(带有硬编码的 Xpath):

class StackItem(scrapy.Item):
    def __setitem__(self, key, value):
        if key not in self.fields:
            self.fields[key] = scrapy.Field()
        self._values[key] = value


class newAppSpider(CrawlSpider):
    name = "appSpider"


    def __init__(self, *args, **kwargs): 
        super(newAppSpider, self).__init__(*args, **kwargs) 
        self.start_urls = [kwargs.get('start_url')]

    rules = (Rule (SgmlLinkExtractor(allow=('.*\?id1=.*',),restrict_xpaths=('//a[@class="prevNext next"]',))
, callback="parse_items", follow= True),)


    def parse_items(self, response):
        hxs = HtmlXPathSelector(response)
        posts = hxs.select("//article[@class='classified']")
        items = []

        for post in posts:
            item = StackItem()
            item[self.settings['MY_PROPERTY']] = post.select("div[@class='uu mb2px']/a/strong/text()").extract() 
            items.append(item)

            for item in items:
                yield item

因为您要在节点集中查找文本(每个作业 posting),所以您必须遍历 posting 的节点并查看该节点是否包含您的文本需要。

如果你想让它变得非常通用,这是 XPath 的一个大问题。

但是如果特定 post 包含此文本,您可以使用如下内容进行过滤:

for post in posts:
    text_node = self.find_text(post, "Job Title")
        if text_node:
            print text_node.xpath('text()').extract()

以及进入蜘蛛的 find_text 函数(这可以进一步改进):

def find_text(self, node, text):
    for child in node.xpath("./child::node()"):
        if child.xpath("./text()[contains(.,'{0}')]".format(text)).extract():
            return child
        if child.xpath(".//text()[contains(.,'{0}')]".format(text)).extract():
            return self.find_text(child, text)

注意 XPath 的 contains 区分大小写。这意味着 职位 不等于 职位

但是,如果您查看该站点,您会发现 "Job Title" 会产生一个小问题,因为该标签包含的不仅仅是职位名称。

还有一件事

因为您使用了规则,所以您的 start_url 没有被解析。如果您输入 "Job Title" 作为搜索文本,这是显而易见的,它会在更深的地方找到包含此文本的职位描述。要解决此问题,您必须覆盖蜘蛛的 parse_start_url 函数:

def parse_start_url(self, response):
    self.parse_items(response)

对于启动错误

为您从 Flask 网站获得的价值加上引号:

command = "scrapy crawl appSpider -a start_url=" + request.form['url'] + '-s MY_PROPERTY="' + request.form['tag1']+'"'