在avito.ru(俄罗斯房地产网站)上,人们的手机会被隐藏,直到您点击它为止。我想用Scrapy + Splash收集手机。
示例网址:https://www.avito.ru/moskva/kvartiry/2-k_kvartira_84_m_412_et._992361048
单击该按钮后,将显示弹出窗口并显示电话。
我使用Splash execute API并使用以下Lua脚本:
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 一般有效,蓝色"显示手机"按钮必须是特殊的。
为了隔离问题,我创建了一个包含最少示例脚本的repo和一个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,结果是一样的。
我也尝试过:
@ Lore的建议,包括simulateClick()
方法(参见simulate_click分支)
此处所述的mouseDown / mouseUp事件:Simulating a mousedown, click, mouseup sequence in Tampermonkey?(请参阅trigger_mouse_event分支)
答案 0 :(得分:3)
以下脚本适合我:
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
原始解决方案存在两个问题:
btn.style.border = "5px solid black"
来检查匹配了哪个元素。 答案 1 :(得分:1)
我不知道您的实施是如何运作的,但我建议将main
重命名为parse
,这是spidrs在启动时调用的默认函数。
如果这不是问题,首先要做的是控制你是否使用带有css选择器的Javascript选择了该类的正确元素。也许它存在另一个具有item-phone-button
类属性的项目,并且您点击了错误的位置。
如果以上都是正确的,那么我建议两个选项对我有用:
local button = splash:select('item phone-button')
button:mouse_click()
button:mouse_click()
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
编辑:在this example中使用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");
}
}