我已经创建了一个脚本,以解析start_urls
中列出的不同站点的标题。该脚本可以完美地完成工作。
我现在想做的是,无论其中有多少个URL,在解析了两个URL之后,让我的脚本停止。
到目前为止,我已经尝试过:
import scrapy
from scrapy.crawler import CrawlerProcess
class TitleSpider(scrapy.Spider):
name = "title_bot"
start_urls = ["https://www.google.com/","https://www.yahoo.com/","https://www.bing.com/"]
def parse(self, response):
yield {'title':response.css('title::text').get()}
if __name__ == "__main__":
c = CrawlerProcess({
'USER_AGENT': 'Mozilla/5.0',
})
c.crawl(TitleSpider)
c.start()
当列出的两个网址被抓取时,如何停止脚本?
答案 0 :(得分:1)
按照Gallaecio的建议,您可以添加一个计数器,但是这里的区别在于,您可以在if语句之后导出一个项目。这样,它将几乎总是最终导出2个项目。
import scrapy
from scrapy.crawler import CrawlerProcess
from scrapy.exceptions import CloseSpider
class TitleSpider(scrapy.Spider):
name = "title_bot"
start_urls = ["https://www.google.com/", "https://www.yahoo.com/", "https://www.bing.com/"]
item_limit = 2
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.counter = 0
def parse(self, response):
self.counter += 1
if self.counter > self.item_limit:
raise CloseSpider
yield {'title': response.css('title::text').get()}
为什么几乎总是?您可能会问。它与parse
方法中的竞争条件有关。
想象一下,self.counter
当前等于1
,这意味着希望再导出一个项目。但是现在Scrapy同时接收到两个响应,并为它们两者调用parse
方法。如果两个运行parse
方法的线程将同时增加计数器,则它们两个都将具有等于self.counter
的{{1}},因此都会引发3
异常。
在这种情况下(这种情况不太可能发生,但仍然有可能发生),蜘蛛只会输出一项。
答案 1 :(得分:1)
目前,我看到了立即停止此脚本的唯一方法-使用<div class="media">
<video src="video.mov" autoplay loop
muted></video>`
</div>
<div class="background"></div>
<div class="contents">
<h1>Registration Page</h1>
</div>
<div class="slider">
<button class="slidercontact">Contact</button>
<div class="slidercontent">
<a href="#">1</a>
<a href="#">2</a>
</div>
</div>
强制退出功能:
os._exit
我尝试过的另一件事。
但是我没有收到所需的结果(立即停止脚本,在import os
import scrapy
from scrapy.crawler import CrawlerProcess
class TitleSpider(scrapy.Spider):
name = "title_bot"
start_urls = ["https://www.google.com/","https://www.yahoo.com/","https://www.bing.com/"]
item_counter =0
def parse(self, response):
yield {'title':response.css('title::text').get()}
self.item_counter+=1
print(self.item_counter)
if self.item_counter >=2:
self.crawler.stats.close_spider(self,"2 items")
os._exit(0)
if __name__ == "__main__":
c = CrawlerProcess({'USER_AGENT': 'Mozilla/5.0' })
c.crawl(TitleSpider)
c.start()
中仅用 3个网址停止脚本中的2个已删除项目):
start_urls
实例转移到蜘蛛设置并调用
CrawlerProcess
,(CrawlerProcess.stop
)等。以及其他方法
来自reactor.stop
方法。使用parse
扩展名docs source)并遵循以下CloseSpider
定义:
CrawlerProcess
将c = CrawlerProcess({
'USER_AGENT': 'Mozilla/5.0',
'EXTENSIONS' : {
'scrapy.extensions.closespider.CloseSpider': 500,
},
"CLOSESPIDER_ITEMCOUNT":2 })
的设置减小为CONCURRENT_REQUESTS
(使用1
raise CloseSpider
方法中的条件)。
当应用程序刮取2个项目并
到达带有parse
的代码行-已经有第三个请求
在另一个线程中启动。
如果使用常规停止方式
蜘蛛,应用程序将一直处于活动状态,直到之前处理过
请求并处理他们的响应,只有在此之后-它
关闭。
由于您的应用程序的start_urls中的URL数量相对较少,因此应用程序会在到达raise ClosesSpider
之前很长时间开始处理所有URL。
答案 2 :(得分:0)
在https://stackoverflow.com/a/38331733/939364之上进行构造,您可以在Spider的构造函数中定义一个计数器,并使用parse
来增加它,并在CloseSpider
达到2时提高它:
import scrapy
from scrapy.crawler import CrawlerProcess
from scrapy.exceptions import CloseSpider # 1. Import CloseSpider
class TitleSpider(scrapy.Spider):
name = "title_bot"
start_urls = ["https://www.google.com/","https://www.yahoo.com/","https://www.bing.com/"]
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.counter = 0 # 2. Define a self.counter property
def parse(self, response):
yield {'title':response.css('title::text').get()}
self.counter += 1 # 3. Increase the count on each parsed URL
if self.counter >= 2:
raise CloseSpider # 4. Raise CloseSpider after 2 URLs are parsed
if __name__ == "__main__":
c = CrawlerProcess({
'USER_AGENT': 'Mozilla/5.0',
})
c.crawl(TitleSpider)
c.start()
我不确定100%会阻止第三个URL的解析,因为我认为CloseSpider
会停止启动新请求,但会等待启动的请求结束。
如果要防止刮掉2个以上的项目,可以编辑parse
以便在self.counter > 2
时不产生项目。
答案 3 :(得分:-1)
枚举做好的工作。架构和
方面的一些变化for cnt, url in enumerate(start_urls):
if cnt > 1:
break
else:
parse(url)