这是我从another user's question产生的问题。如果你看一下我的答案,你会得到一些关于这个问题的背景知识。我要去的网页的URL是https://hotels.ctrip.com/hotel/347422.html?isFull=F#ctm_ref=hod_sr_lst_dl_n_1_8,如果你想亲自检查一下。
考虑问题底部的python selenium脚本。当selenium试图点击这个元素时没有任何反应:
browser.find_element_by_xpath('//*[@id="cPageBtn"]').click()
这个元素也是一样的
browser.find_element_by_xpath('//*[@id="appd_wrap_close"]').click()
在为每个元素调试我的selenium脚本时,我确认selenium可以很好地找到该元素;它不是隐藏的,在iFrame中,被禁用,或者我通常检查失败的硒行为的任何其他奇怪之处。
但是,它有一个鼠标点击事件,可以调用一个有趣的JavaScript文件,我实际上可以通过导航到这里显示的URL来访问它:
将鼠标悬停在URL上显示它是https://webresource.c-ctrip.com/ResUnionOnline/R3/float/floating_normal.min.js?20190306:2。
在我找到的文件的最开头
document.getElementById("ab_testing_tracker") && "abTestValue_Value" != h ?
document.getElementById("ab_testing_tracker").value
因此,我(通过开发控制台中的CSS选择器)搜索id为"ab_testing_tracker"
的元素的网页HTML,我很惊讶它没有返回任何内容。然后我解开并在文件中搜索“ab_testing_tracker”的所有实例。这让我想到了这个元素:
document.getElementsByTagName("body")[0].insertAdjacentHTML("afterBegin","<input type='hidden' name='ab_testing_tracker' id='ab_testing_tracker' value='"+h.split("|")[1]+"'>")
好吧,为了实现自动化跟踪,似乎在文档的body
中插入了一个隐藏的输入节点。 Google搜索显示,自动跟踪通常是通过查看navigator.userAgent
属性并查找指示自动化的userAgent来完成的。但是脚本每次都使用一个随机的合法userAgent,所以我不认为userAgent是检测发现selenium的方式。
由于网站的测试跟踪,Selenium无法点击网页上的某些元素。我想到了几件可以绕过它的东西:也许我可以在使用selenium时禁用点击事件?这个我不知道怎么办,在网上搜索后找不到办法。接下来,我尝试使用Javascript执行程序单击它,但这不起作用。
有没有人知道如何绕过测试跟踪器并单击所需的元素?
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.firefox.options import Options
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.common.by import By
# url
url = "https://hotels.ctrip.com/hotel/347422.html?isFull=F#ctm_ref=hod_sr_lst_dl_n_1_8"
# User Agent
User_Agent_List = ["Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.2 (KHTML, like Gecko) Chrome/22.0.1216.0 Safari/537.2",
"Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US)",
"Mozilla/5.0 (compatible; MSIE 10.0; Macintosh; Intel Mac OS X 10_7_3; Trident/6.0)",
"Opera/9.80 (X11; Linux i686; U; ru) Presto/2.8.131 Version/11.11",
"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.2 (KHTML, like Gecko) Chrome/22.0.1216.0 Safari/537.2",
"Mozilla/5.0 (Windows NT 6.2; Win64; x64; rv:16.0.1) Gecko/20121011 Firefox/16.0.1",
"Mozilla/5.0 (iPad; CPU OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5355d Safari/8536.25"]
# Define the related lists
Score = []
Travel_Types = []
Room_Types = []
Travel_Dates = []
Comments = []
DEFINE_PAGE = 10
def next_page():
current_page = int(browser.find_element_by_css_selector('a.current').text)
# First, clear the input box
browser.find_element_by_id("cPageNum").clear()
print('Clear the input page')
# Second, input the next page
nextPage = current_page + 1
print('Next page ',nextPage)
browser.find_element_by_id("cPageNum").send_keys(nextPage)
# Third, press the goto button
browser.find_element_by_xpath('//*[@id="cPageBtn"]').click()
def scrap_comments():
"""
It is a function to scrap User comments, Score, Room types, Dates.
"""
html = browser.page_source
soup = BeautifulSoup(html, "lxml")
scores_total = soup.find_all('span', attrs={"class":"n"})
# We only want [0], [2], [4], ...
travel_types = soup.find_all('span', attrs={"class":"type"})
room_types = soup.find_all('a', attrs={"class":"room J_baseroom_link room_link"})
travel_dates = soup.find_all('span', attrs={"class":"date"})
comments = soup.find_all('div', attrs={"class":"J_commentDetail"})
# Save score in the Score list
for i in range(2,len(scores_total),2):
Score.append(scores_total[i].string)
Travel_Types.append(item.text for item in travel_types)
Room_Types.append(item.text for item in room_types)
Travel_Dates.append(item.text for item in travel_dates)
Comments.append(item.text.replace('\n','') for item in comments)
if __name__ == '__main__':
# Random choose a user-agent
user_agent = random.choice(User_Agent_List)
print('User-Agent: ', user_agent)
# Browser options setting
options = Options()
options.add_argument(user_agent)
options.add_argument("disable-infobars")
# Open a Firefox browser
browser = webdriver.Firefox(options=options)
browser.get(url)
browser.find_element_by_xpath('//*[@id="appd_wrap_close"]').click()
page = 1
while page <= DEFINE_PAGE:
scrap_comments()
next_page()
browser.close()
问题不在于跟踪或点击事件,问题在于时间和可能的浏览器大小。搜索横幅关闭按钮时,最大化浏览器窗口并添加显式等待
browser = webdriver.Firefox(options=options)
browser.maximize_window()
browser.get(url)
wait = WebDriverWait(browser, 10)
wait.until(EC.element_to_be_clickable((By.ID, 'appd_wrap_close'))).click()
wait.until(EC.invisibility_of_element_located((By.ID, 'appd_wrap_default')))
current_page = int(browser.find_element_by_css_selector('a.current').text)
next_page = current_page + 1
page_number_field = wait.until(EC.visibility_of_element_located((By.ID, 'cPageNum')))
page_number_field.clear()
page_number_field.send_keys(next_page)
wait.until(EC.element_to_be_clickable((By.ID, 'cPageBtn'))).click()