3

我正在尝试做的事情

在avito.ru(俄罗斯房地产网站)上,用户的电话是隐藏的,直到您点击它。我想用 Scrapy+Splash 收集手机。

示例网址:https ://www.avito.ru/moskva/kvartiry/2-k_kvartira_84_m_412_et._992361048

截图:手机被隐藏

单击按钮后,将显示弹出窗口并显示电话。

在此处输入图像描述

我正在使用带有以下 Lua 脚本的Splash执行API:

function main(splash)
    splash:go(splash.args.url)
    splash:wait(10)
    splash:runjs("document.getElementsByClassName('item-phone-button')[0].click()")
    splash:wait(10)
    return splash:png()
end

问题

未单击该按钮且未显示电话号码。这是一项微不足道的任务,我无法解释为什么它不起作用。

item-phone-button如果我们替换为 ,单击对于同一页面上的另一个字段可以正常工作js-show-stat。所以 Javascript通常可以工作,蓝色的“显示电话”按钮一定是特殊的。

我试过的

为了隔离问题,我创建了一个带有最小示例脚本的仓库和一个用于 Splash 的 docker-compose 文件: https ://github.com/alexanderlukanin13/splash-avito-phone

Javascript 代码是否有效,您可以在 Chrome 和 Firefox 中使用 Javascript 控制台进行验证

document.getElementsByClassName('item-phone-button')[0].click()

我已经用 Splash 版本 3.0、3.1、3.2 尝试过,结果是一样的。

更新

我也试过:

4

2 回答 2

8

以下脚本适用于我:

function main(splash, args)
  splash.private_mode_enabled = false
  assert(splash:go(args.url))
  btn = splash:select_all('.item-phone-button')[2]
  btn:mouse_click()
  btn.style.border = "5px solid black"
  assert(splash:wait(0.5))
  return {
    num = #splash:select_all('.item-phone-button'),
    html = splash:html(),
    png = splash:png(),
    har = splash:har(),
  }
end

原始解决方案有两个问题:

  1. 'item-phone-button' 类有 2 个元素,感兴趣的按钮是第二个。我已经通过设置检查了哪个元素匹配btn.style.border = "5px solid black"
  2. 该网站需要禁用私有模式,可能是因为它使用了 localStorage。检查http://splash.readthedocs.io/en/stable/faq.html#website-is-not-rendered-correctly以获取其他常见建议。
于 2018-03-20T14:55:12.610 回答
1

我不知道你的实现是如何工作的,但我建议用 重命名mainparse这是蜘蛛在启动时调用的默认函数。

如果这不是问题,首先要做的是控制是否使用带有 css 选择器的 Javascript 选择了该类的正确元素。也许它存在另一个具有item-phone-button类属性的项目,而您单击了错误的位置。

如果以上所有内容都是正确的,我建议有两个对我有用的选项:

  • 使用Splash mouse_clickSplash wait(我看到你已经使用了后者)。如果它不起作用,请尝试双击,通过替换您的代码:

    local button = splash:select('item phone-button') 
    button:mouse_click()
    button:mouse_click()
    

  • 使用Splash wait_for_resume,执行 javascript 代码直到终止,然后重新启动 LUA。您的代码也会变得更简单:

    function main(splash)
        splash:go(splash.args.url)
        splash:wait_for_resume("document.getElementsByClassName([[
                      function main(splash) {
                           document.getElementsByClassName('item-phone-button');[0].click()
                           splash.resume();
                      }               
        ]])
        return splash:png()
    end
    

    编辑:在这个例子dispatchEvent中使用而不是click()像这样似乎很好:

    function simulateClick() {
      var event = new MouseEvent('click', {
        view: window,
        bubbles: true,
        cancelable: true
      });
      var cb = document.getElementById('checkbox'); 
      var cancelled = !cb.dispatchEvent(event);
      if (cancelled) {
        // A handler called preventDefault.
        alert("cancelled");
      } else {
        // None of the handlers called preventDefault.
        alert("not cancelled");
      }
    }
    
  • 于 2018-03-14T13:55:46.140 回答