在scrapy中使用自定义方法时无法找出正确的方法

时间:2020-12-25 08:03:11

标签: python python-3.x selenium web-scraping scrapy

我正在尝试使用scrapy结合selenium从网站的内页中抓取不同帖子的标题,尽管该网站的内容是静态的。该脚本从着陆页抓取不同帖子的链接,并重用新解析的链接从其内页获取标题。

我知道有一个 library 用于在 scrapy 中使用 selenium。但是,我对在这个基本用例中使用该库不感兴趣。

以下蜘蛛中有两种方法。我可以坚持使用一种方法来完成整个事情,但我在这里使用了两种方法来了解如何将链接从一种方法传递到另一种方法,以便在不发出任何请求的情况下完成后一种方法中的其余事情,如{ {1}}。

脚本似乎工作正常。如果我从这里踢出 scrapy.Request() yield 并像 yield self.parse_from_innerpage(response.urljoin(elem)) 一样使用,脚本也能正常工作。

问题:我是否应该在 parse 方法中使用 yield 或不使用 yield 来继续当前的实现,因为它们可以互换工作?

我尝试过:

self.parse_from_innerpage(response.urljoin(elem))

2 个答案:

答案 0 :(得分:2)

def parse_from_innerpage(self,link):
        self.driver.get(link)
        elem = self.wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "h1[itemprop='name'] > a")))
        print(elem.text)

在回答您的问题之前,我想对您在 print() 函数中的 parse_from_innerpage(self, link) 语句添加一点注释。尽管本主题是 controversially discussed,但返回有问题的对象是更好的做法 - 您可以稍后决定通过 assigning a class instance(然后调用该方法)或直接通过 Class.Method(**args)< /p>

那不碍事 - 让我们来解决您的问题:

<块引用>

我应该在 parse 方法中使用 yield 还是不使用当前的实现,因为它们可以互换工作?

要回答这个问题 - 或者更确切地说是理解回复 - 我强烈建议查看一些定性资源以掌握 yield 的概念。以下是一些用于进一步阅读的链接:

基本上,return 发送一个指定的值,另一方面,yield 生成一个序列值 - 因此非常适合迭代您获得的值。 >


让我们看看您的代码:

parse(self, response) method

def parse(self, response):
        for elem in response.css(".summary .question-hyperlink::attr(href)").getall():
            yield self.parse_from_innerpage(response.urljoin(elem))

简单地说,这个方法期望来自 parse_from_innerpage(self, link) 的一些值,因为它“yields”或遍历接收列表。 但是,您的 parse_from_innerpage(self,link) 没有返回任何内容 - 看看,没有 return 声明!:

def parse_from_innerpage(self,link):
        self.driver.get(link)
        elem = self.wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "h1[itemprop='name'] > a")))
        
        #Use return instead of print()
        print(elem.text)

parse_from_innerpage(**args) 返回 None 时,parse(**args) 也不会返回任何东西,因为没有任何东西可以迭代/返回。因此,您应该将 print() 替换为 return


我建议查看 Scrapy Documentation(尤其是 Scrapy at a glance)以了解 Scrapy 的具体工作原理以及它期望 scrapy.Spider 做什么以实现您的目标。基本上,parse(**args) 方法用作生成器(指 already mentioned StackOverflow question)来获取您想要获得的结果 - 一旦没有元素可以迭代(它停止)它“显示它们给你”

<块引用>

在解析回调中,我们使用 CSS 循环引用元素 选择器,生成一个带有提取的引用文本的 Python dict 和 作者,查找下一页的链接并安排另一个请求 使用与回调相同的解析方法

...但正如您在案例中提到的,parse(**args) 不幸收到 None,原因是 print() 而不是 return

答案 1 :(得分:1)

yield 在 python 中用于从生成器内部“放弃”运行并返回值。

所以这里的 parse 方法返回 parse_from_innerpage 的结果。但是,parse_from_innerpage 没有 return 语句,这意味着它返回 None

从scrapy 文档中阅读this,了解scrapy 期望蜘蛛做什么。

简而言之,scrapy 使用 parse 方法作为结果的生成器,然后在停止运行时(用完要抓取的链接)向您显示它们。 用返回替换 print,一切都应该按预期工作