首先,这是一个跟进问题:更改正在运行的蜘蛛scrapyd的数量
我使用phantomjs和selenium为我的scrapy项目创建了一个下载器中间件.当我在本地一次运行一只蜘蛛时,它运作良好,并没有真正放慢速度.
但就在最近,我在AWS上放了一台scrapyd服务器.我注意到一个可能的竞争条件,当一次运行多个蜘蛛时,这似乎会导致错误和性能问题.我觉得问题源于两个不同的问题.
1)蜘蛛试图同时使用可执行的phantomjs.
2)蜘蛛试图同时登录phantomjs的ghostdriver日志文件.
在这里猜测,性能问题可能是蜘蛛试图等待资源可用(这可能是因为我也有一个sqlite数据库的竞争条件).
以下是我得到的错误:
exceptions.IOError:[Errno 13]权限被拒绝:'ghostdriver.log'(日志文件竞争条件?)
selenium.common.exceptions.WebDriverException:消息:'无法连接到GhostDriver'(可执行竞争条件?)
我的问题是:
我对问题的分析是否正确?
除了限制一次可以运行的蜘蛛数量之外,是否有任何已知的解决方案?
还有其他方法我应该处理JavaScript吗?(如果你认为我应该创建一个全新的问题来讨论使用scrapy处理javascript的最佳方法让我知道,我会)
这是我的下载中间件:
class JsDownload(object):
@check_spider_middleware
def process_request(self, request, spider):
if _platform == "linux" or _platform == "linux2":
driver = webdriver.PhantomJS(service_log_path='/var/log/scrapyd/ghost.log')
else:
driver = webdriver.PhantomJS(executable_path=settings.PHANTOM_JS_PATH)
driver.get(request.url)
return HtmlResponse(request.url, encoding='utf-8', body=driver.page_source.encode('utf-8'))
Run Code Online (Sandbox Code Playgroud)
注意:_platform代码是一个临时工作,直到我将此源代码部署到静态环境中.
我找到了针对javascript问题的解决方案但是它们是基于蜘蛛的.这让我感到困扰,因为这意味着每个请求都必须在下载程序处理程序中再次执行,并再次在蜘蛛中.这就是为什么我决定将我的实现作为下载中间件.
如何在scrapy中实现自定义信号?我的项目实施了评分系统。根据项目的分数,它要么被接受,要么被拒绝。我希望能够发出 ITEM_ACCEPTED 和 ITEM_REJECTED 信号以收集有关爬网的统计信息。
我正在查看源,https://github.com/scrapy/scrapy/blob/master/scrapy/signals.py - 但我不清楚这里发生了什么。
任何有关如何发送此信号的说明也将有所帮助。
任何建议表示赞赏!
编辑:我在scrapy docs上找到了这个:
http://doc.scrapy.org/en/latest/topics/api.html#module-scrapy.signalmanager
我的一只蜘蛛:
from Scrapers.extensions import signals #my custom signals
def parse(self, response):
manager = SignalManager(self)
manager.send_catch_log(signals.ITEM_ACCEPTED)
manager.send_catch_log(signals.ITEM_REJECTED)
Run Code Online (Sandbox Code Playgroud)
我的扩展名:
from Scrapers.extensions import signals as custom
@classmethod
def from_crawler(cls, crawler):
o = cls(crawler.stats)
crawler.signals.connect(o.spider_closed, signal=signals.spider_closed)
crawler.signals.connect(o.spider_error, signal=signals.spider_error)
crawler.signals.connect(o.item_scraped, signal=signals.item_scraped)
crawler.signals.connect(o.item_accepted, signal=custom.ITEM_ACCEPTED)
crawler.signals.connect(o.item_rejected, signal=custom.ITEM_REJECTED)
return o
def item_accepted(self):
print "it worked -- accepted"
def item_rejected(self):
print "it worked -- rejected"
Run Code Online (Sandbox Code Playgroud)
信号
ITEM_ACCEPTED = object()
ITEM_REJECTED = object()
Run Code Online (Sandbox Code Playgroud) 对于通过[FromBody]我传递到动作的模型,我喜欢使它们的属性不可变public int SomeProperty { get; private set; }。这样我就知道我的处理程序的输入没有被修改。
我遇到的问题是 Swagger 和 Swashbuckle 完全忽略了那些用于呈现参数有效负载示例的字段。我查看了从我们的 API 生成的 swagger 模式,看到所有提到的字段都有readOnly: true.
我想知道是否有某种方法可以将 Swashbuckler 或 Swagger 配置为不忽略这些属性。或者,也许有某种方法可以使用 SwashBuckle 扩展框架的某些部分将每个定义的 readonly 设置为 false?
编辑:从 swagger.json 添加示例
在这个例子中,someProperty 被标记为只读。我认为这就是该属性没有出现在生成的 POST 参数示例中的原因。如果有办法让 swagger gen 不添加任何只读属性,我会很好。
{
"type": "object",
"properties": {
"someProperty": {
"format": "int32",
"type": "integer",
"readOnly": true
},
}
}
Run Code Online (Sandbox Code Playgroud) 我一直在寻找有问题的文档,以寻找一种方法来限制我的蜘蛛可以发出的请求数量。在开发过程中,我不想坐在这里等蜘蛛完成整个爬网,即使爬网非常集中,它们仍然可能需要一段时间。
我希望能够说:“在向站点抓取了x个请求之后,我停止生成新请求。”
我想知道是否有某种设置我可能会错过,或者使用其他方法使用框架来完成,然后再尝试提出自己的解决方案。
我正在考虑实现一个下载程序中间件,该中间件将跟踪正在处理的请求数量,并在达到限制后停止将其传递给下载程序。但是就像我说的,如果可能的话,我宁愿在框架中使用一种机制。
有什么想法吗?谢谢。
python-2.7 ×3
scrapy ×3
python ×2
c# ×1
ghostdriver ×1
phantomjs ×1
selenium ×1
signals ×1
swagger ×1
swashbuckle ×1
web-scraping ×1