4

我想制作一个通用刮板,它可以从任何类型的网站(包括 AJAX 网站)中抓取和刮取所有数据。我在互联网上进行了广泛搜索,但找不到任何合适的链接来解释我如何 Scrapy 和 Splash 一起抓取 AJAX 网站(包括分页、表单数据和在显示页面之前单击按钮)。我提到的每个链接都告诉我可以使用 Splash 呈现 Javascript 网站,但是没有关于使用 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
       """
4

3 回答 3

2

Splash 和分页的问题如下:

我无法制作提供响应格式的新网页(单击分页链接后)的 Lua 脚本。而不是纯 HTML。

因此,我的解决方案如下 - 单击链接并提取新生成的 url 并将爬虫引导到这个新 url。

所以,我在有分页链接的页面上执行

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,您必须使用正则表达式(这很糟糕) - 但这是我能做到的最好的。

于 2017-07-05T21:43:59.257 回答
1

您可以通过编写 JavaScript函数并告诉Splash在呈现您的页面时执行该脚本来模拟ckickscroll等行为。

一个小例子:

您定义一个JavaScript函数,该函数在页面中选择一个元素,然后单击它:

(来源:飞溅文档

# 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": _scriptargs

例子:

def parse(self, response):
    yield SplashRequest(response.url, self.parse_elem,
                        endpoint="execute",
                        args={"lua_source": _script})

您将在此处找到有关启动脚本的所有信息

于 2017-06-08T13:31:56.630 回答
0

我刚刚在这里回答了一个类似的问题:scraping ajax based pagination。我的解决方案是获取当前页面和最后一页,然后替换请求 URL 中的页面变量。

另外 - 您可以做的另一件事是查看浏览器开发工具中的网络选项卡,看看您是否可以识别任何被调用的 API。如果您查看 XHR 下的请求,您可以看到返回 json 的请求。

然后,您可以直接调用 API 并解析 json/ html 响应。这是来自scrapy docs的链接:网络工具

于 2021-06-25T19:11:05.900 回答