我想通过Web page抓取一些评论。当我尝试通过Selenium选择转到按钮(转到下一页)时,它始终显示一个弹出窗口。我尝试使用Selenium关闭弹出窗口,但仍然无法正常工作。有人可以帮助我解决此问题并帮助我完成下面的next_page()函数吗?非常感谢!
我已经完成了功能 scrap_comments()。我要做的是完成功能 next_page()。
这是我的代码。
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():
"""
It is a function to execute Next Page function
"""
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
WebDriverWait(browser, 20).until(EC.element_to_be_clickable((By.XPATH, '//*[@id="cPageBtn"]')))
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)
#### My ISSUE #####
browser.find_element_by_xpath('//*[@id="appd_wrap_close"]').click()
page = 1
while page <= DEFINE_PAGE:
scrap_comments()
next_page()
browser.close()
谢谢!
答案 0 :(得分:1)
好,所以看来必须要切换到某些窗口才能使Selenium单击'//*[@id="appd_wrap_close"]'
元素,我尝试了一段时间才找到一个。最终,我认为我偶然发现了阻止您单击该元素的原因。他们安装了测试跟踪软件。这是我发现的方式:首先,我所做的只是显而易见的事情,检查您要单击的'x'元素。我试图找到关于该元素的任何异常信息,过一会儿我发现有一个附加的Event
。我在firefox的检查器中单击Event
,并看到了以下内容:
嗯...我希望它能关闭它所在的盒子,但是它具有以下JavaScript:
function() {
c.setCookie({
manualclose: "1"
}, "", 1), u.collapse(), window.__bfi.push(["_tracklog", "pcfloatClose", location.href + "&urlPageId=" + e + "&htmlType=" + d])
}
好吧,这里有u.collapse
,我想这是折叠面板所需的全部代码。但是为什么还有其他这些东西呢?有几件事对我来说很奇怪:为什么每次您单击该按钮时都会设置一个cookie?为什么叫**manual**close
?然后我靠近一点,看到“点击”后面的文字:_esUnionOnline/R3/float/floating_normal.min.js?20190316:2
。嗯因此,他们正在调用javascript文件。那似乎是一个URL。他们为什么要为那个小的“ x”上的mouseclick事件解决所有这些麻烦?
我将鼠标悬停在它上面,并且确实可以看到https://webresource.c-ctrip.com/ResUnionOnline/R3/float/floating_normal.min.js?20190306:2
。
我导航到该网站并找到一个包含缩小的Javascript的大文件。我将其放置在非缩小符中(我使用了https://unminify.com/)。我在文档顶部看到了
document.getElementById("ab_testing_tracker") && "abTestValue_Value" != h ?
document.getElementById("ab_testing_tracker").value
ab_testing_tracker
.....听起来不太好。因此,我对此进行了搜索,找到了一堆ID为ab_testing_tracker
的隐藏输入。在这一点上,我非常确信他们正在检测硒,而不允许您单击。在对常见的测试跟踪方法进行了一些搜索之后,发现除其他外,检查userAgent
是很常见的。 Selenium的默认userAgent只是webdriver,因为您可以阅读here,所以我进行了搜索。果然,有20种结果全部以navigator.userAgent
的形式出现,有些看起来像
i.test(navigator.userAgent)
然后我注意到您使用的是随机的,合法的userAgent,因此它们必须具有其他检测硒的方法。我确实注意到了此功能
function n() {
var t, n;
switch (n = e.ResponseStatus.Errors[0].ErrorCode ? e.ResponseStatus.Errors[0].ErrorCode : "") {
case "104":
t = "验证码输入超时";
break;
case "105":
t = "验证码输入错误";
break;
case "106":
t = "手机号码不正确";
break;
case "107":
t = "客户端IP不能为空";
break;
case "108":
t = "短信内容不能为空";
break;
case "109":
t = "同一号码,两分钟内最多发一次";
break;
case "110":
t = "一天内同一手机最多发两次";
break;
case "111":
t = "一天内同一IP最多发五次";
break;
default:
t = "短信发送失败,请重新发送"
}
return t
}
在他们的JavaScript中,并借助google translation的帮助,发现最近的几个开关正在检查您是否已访问该网站一定次数。但不幸的是,至少在Firefox中,我无法提出解决此问题的真实方法。
如果您愿意在Chrome中进行测试,则默认情况下(无论出于何种原因)该框都会最小化,因此您不必担心摆脱它。
因此,长话短说,如果您可以在Chrome中进行测试,则只需删除以下行,而不必担心愚蠢的框。测试跟踪器可能仍然会运行,我不知道它是如何工作的,我怀疑他们是自己编写的,因为我找不到使用这些“ ab_test_tracking”节点的任何工具-实际上,在Google上搜索“ ab_test_tracking”的结果很少结果,其中大多数都是这个网站。
让我知道您的选择是什么(出于某种原因需要使用Firefox?),如果您能够在Chrome中运行测试,请告诉我它是否有效!
编辑有关分页按钮 因此,我发现您尝试单击以导航到下一页的按钮也是如此-它具有一个onClick事件,该事件也链接到具有测试跟踪的缩小文件,因此我想这就是您的原因无法单击按钮,硒将永远不会超过第一页。
但是“下一步”按钮没有单击时调用的脚本。您应该能够使用
单击该按钮browser.find_element_by_xpath('//*[@id="divCtripComment"]/div[4]/div/a[2]')
让我知道这是否适合您。
答案 1 :(得分:0)
由于Peck的指导,我可以完成next_page()函数。但是,弹出窗口是一种浏览器指纹技术,用于通过Web跟踪用户。现在,我们还不知道如何绕过跟踪技术。下面的代码是我完成的next_page()。
def next_page(page):
"""
It is a function to execute Next Page function
param: page. # Integer, it depends on what page you want to change to.
"""
retryNum = 5
while retryNum >= 0:
try:
# page is the page you see right now, what you wanna do is to change to the next page.
page = page + 1
# Clear
browser.find_element_by_id("cPageNum").clear()
# Send keys
browser.find_element_by_id("cPageNum").send_keys(page)
# Click goto button
browser.find_element_by_id("cPageBtn").click()
# Sleep for random seconds as waiting for loading
time.sleep(random.randint(15, 25))
# Check current page
currentPage = int(browser.find_element_by_css_selector('a.current').text)
if currentPage != page:
retryNum -= 1
print('Retry!')
continue
else:
break
except Exception as e:
assert 'Failed to change to next page'
return False