我想制作一个通用的刮刀,可以抓取并抓取任何类型的网站(包括AJAX网站)的所有数据。我已经广泛搜索了互联网,但找不到任何正确的链接,可以解释我如何Scrapy和Splash一起刮掉AJAX网站(包括分页,表格数据和点击页面显示之前的按钮)。我提到的每个链接都告诉我,Javascript网站可以使用Splash呈现,但没有关于使用Splash呈现JS网站的良好教程/解释。请不要给我与使用浏览器相关的解决方案(我想以编程方式执行所有操作,欢迎使用无头浏览器建议..但我想使用Splash)。
class FlipSpider(CrawlSpider):
name = "flip"
allowed_domains = ["www.amazon.com"]
start_urls = ['https://www.amazon.com/s/ref=nb_sb_noss?url=search-alias%3Daps&field-keywords=mobile']
rules = (Rule(LinkExtractor(), callback='lol', follow=True),
def parse_start_url(self,response):
yield scrapy.Request(response.url, self.lol, meta={'splash':{'endpoint':'render.html','args':{'wait': 5,'iframes':1,}}})
def lol(self, response):
"""
Some code
答案 0 :(得分:1)
通过编写 JavaScript 功能,您可以模拟行为,例如 ckick 或滚动告诉 Splash 在呈现页面时执行该脚本。
一个小例子:
您定义了一个 JavaScript 函数,用于选择页面中的元素,然后点击:
(来源:splash doc)
-- Get button element dimensions with javascript and perform mouse click.
_script = """
function main(splash)
assert(splash:go(splash.args.url))
local get_dimensions = splash:jsfunc([[
function () {
var rect = document.getElementById('button').getClientRects()[0];
return {"x": rect.left, "y": rect.top}
}
]])
splash:set_viewport_full()
splash:wait(0.1)
local dimensions = get_dimensions()
splash:mouse_click(dimensions.x, dimensions.y)
-- Wait split second to allow event to propagate.
splash:wait(0.1)
return splash:html()
end
"""
然后,当您request
时,修改endpoint
并将其设置为"execute"
,然后将"lua_script": _script
添加到 args 。
例如:
def parse(self, response):
yield SplashRequest(response.url, self.parse_elem,
endpoint="execute",
args={"lua_source": _script})
您会找到有关启动脚本 here
的所有信息答案 1 :(得分:1)
Splash和分页的问题如下:
我无法生成一个Lua脚本,该脚本提供了一个响应格式的新网页(点击分页链接后)。而不是纯HTML。
因此,我的解决方案如下 - 点击链接并提取新生成的网址并将抓取工具指向此新网址。
所以,我在页面上有我执行的分页链接
yield SplashRequest(url=response.url, callback=self.get_url, endpoint="execute", args={'lua_source': script})
使用以下Lua脚本
def parse_categories(self, response):
script = """
function main(splash)
assert(splash:go(splash.args.url))
splash:wait(1)
splash:runjs('document.querySelectorAll(".next-page")[0].click()')
splash:wait(1)
return splash:url()
end
"""
和get_url函数
def get_url(self,response):
yield SplashRequest(url=response.body_as_unicode(), callback=self.parse_categories)
这样我就能循环查询。
同样地,如果你不期望新的URL,你的Lua脚本可以生成纯html,你必须使用正则表达式(这很糟糕) - 但这是我能做的最好的。
答案 2 :(得分:0)
我刚刚在这里回答了一个类似的问题:scraping ajax based pagination。我的解决方案是获取当前页面和最后页面,然后替换请求URL中的页面变量。
此外 - 您可以做的另一件事是查看浏览器开发工具中的网络选项卡,看看您是否可以识别调用的任何 API。如果您查看 XHR 下的请求,您可以看到返回 json 的请求。
然后就可以直接调用API,解析json/html响应了。以下是来自 scrapy 文档的链接:The Network-tool