使用 Scrapy Splash 和 Lua 在鼠标点击时动态加载内容

如何解决使用 Scrapy Splash 和 Lua 在鼠标点击时动态加载内容

我有一个带有 Lua 脚本的 Scrapy Splash 抓取工具。 Lua 脚本目前仅在页面上启动滚动以在搜索页面上加载更多结果。 我从搜索页面导航到我抓取的详细信息页面。 但是,在详细信息页面上,照片轮播尚未出现在 DOM 中,它会在用户点击 #showphotos 元素时动态加载。

单击该元素后,将加载以下照片轮播 HTML:

<div id="slider">
    <div class="slider-inner">
        <div class="item active">
            <img src="https://www.example.com/images/1.jpg">
        </div>
        <div class="item">
            <img src="https://www.example.com/images/2.jpg">
        </div>
    </div>
</div>

我已经检查了 herehere

所以我尝试写一些脚本:

click_script = """
        function main(splash,args)

            btn = splash:select_all('#showphotos')[0]
            btn:mouse_click()
            assert(splash:wait(0.5))
              return {
                num = #splash:select_all('#slider div.slider-inner'),html = splash:html()
              }
        end
        """

由于我对 Splash 和 Lua 非常陌生,我不知道在哪里添加代码或从哪里调用它。

我创建了一个测试详细信息页面 here

我当前的代码

myscraper.py

import json
import re

import scrapy
import time
from scrapy_splash import SplashRequest
from scrapy.selector import Selector
from scrapy.http import HtmlResponse
from myresults.items import MyResultItem


class Spider(scrapy.Spider):
    name = 'myscraper'
    allowed_domains = ['example.com']
    start_urls = ['https://www.example.com/results']

    def start_requests(self):
        # lua script for scroll to bottom while all objects appeared
        lua_script = """
        function main(splash,args)
          local object_count = 0
          local url = splash.args.url
          splash:go(url)
          splash:wait(0.5)
          local get_object_count = splash:jsfunc([[
            function (){
              var objects = document.getElementsByClassName("object-adres");
              return objects.length;
            }
            ]])
          temp_object_count = get_object_count()
          local retry = 3
          while object_count ~= temp_object_count do
            splash:evaljs('window.scrollTo(0,document.body.scrollHeight);')
            splash:wait(0.5)
            object_count = temp_object_count
            temp_object_count = get_object_count()
            
          end
          return splash:html()
        end
        """

        # yield first splash request with lua script and parse it from parse def
        yield SplashRequest(
            self.start_urls[0],self.parse,endpoint='execute',args={'lua_source': lua_script},)

    def parse(self,response):
        # get all properties from first page which was generated with lua script
        # get all adreslink from a tag
        object_links = response.css('a.adreslink::attr(href)').getall()
        for link in object_links:
            # send request with each link and parse it from parse_object def
            yield scrapy.Request(link,self.parse_object)

    def parse_object(self,response):
        # create new MyResultItem which will saved to json file
        item = MyResultItem()

        item['url'] = response.url # get url        
        


        yield item

items.py

import scrapy

class RentalItem(scrapy.Item):
    id = scrapy.Field()
    photos = scrapy.Field()
    url = scrapy.Field()

    pass

解决方法

Lua 脚本像 Python 脚本一样运行。在 Spider -> start_requests -> lua_script 中,您已经有一个 Lua 脚本。您要选择第一个 #showphotos 元素并单击它;此外,您还想向结果中添加更多数据。

因此,在执行已经存在的 Lua 代码后,我们要告诉 Splash 选择第一个 #showphotos 元素:

btn = splash:select_all('#showphotos')[1]

请注意索引 1,而不是 0,因为 splash:select_all 数组从 1 开始。

之后,点击它:

btn:mouse_click()

最后,向结果中添加更多数据:

return {
    num = splash:select_all('#slider div.slider-inner')[1].node.outerHTML,html = splash:html()
}

同样,请注意索引 1,而不是 0,因为 splash:select_all 数组从 1 开始。另外,我添加了 .node.outerHTML,因为 {{1 }} 返回一个 Lua 对象,并且没有默认的方式将其序列化为 JSON (ref)

最后,你应该得到这样的结果:

splash:select_all()

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?