selenium实战

当有些网页是用js生成的,用requests获取到的网页里面啥都没有怎么办呢。这个时候最简单的方法就是用selenium模拟页面渲染,当页面渲染完成之后再去根据标签或者xpath就可以获取到自己想要的东西了。
这里只讲实战,关于粉笔答题页面的学习。本来无聊的时候想写个脚本,不用打开网页在命令行里答题,这里记录一下,ps,最后没有成功,所以本文以selenium使用为主

遇到的坑

前排记录下使用selenium时遇到的坑

  • 关闭chrome的自动更新,不然chromedriver的版本跟不上
  • add_experimental_option('w3c', True),为false时有些element会返回dict类型
  • cookie中"sameSite"为"unspecified"的时候,直接删掉这个选项
  • 需要等js渲染完成之后去获取element,不然会为空。driver.implicitly_wait(5)和WebDriverWait两种方法
  • ActionChains(driver).move_to_element(label).click().perform() 需要页面可见

实战开始

等待页面渲染完成

以粉笔为例,查看他的网页源代码如下:

可以看到,html中是无法获取到自己想要的内容的,但是右键检查是可以看到内容的。此时我们就需要等页面渲染完成。
最简单的方法就是加个sleep,停个五六秒,但是这样很慢。这个时候就有了上面提到的driver.implicitly_wait(5)和WebDriverWait两种方法,想要深入了解的可以去搜一下隐形等待和显性等待。等待页面渲染完成之后就可以获取到element了。

登陆问题

以粉笔网页为例,你会发现自己在chrome中打开是不需要登陆的,但是用selenium打开页面却是登陆页面了。
有两种解决方案,一种是老老实实的在页面中填入对应元素。但是有人机验证的问题,有些图形验证码不是很好点。另一种就是用cookie登陆,现在网页里登陆,然后导出cookie,给driver添加cookie,然后再打开想要打开的页面,你会发现不会跳转登陆页面了。代码如下

driver.add_cookie(item)

获取子节点

利用获取到的element,可以看到有个find_element,可以利用它获取到子节点。那遇到ul里一堆li都需要的情况呢,只需要调用find_elements即可,返回的是符合条件的element数组。比方说可以利用一下代码,获取question这个element下面的article标签。

article = question.find_element(By.TAG_NAME,'article')

使用下面的代码可以获取该节点下所有element

answers = answers.find_elements(By.XPATH,"*")

代码环节

贴一下我这次的代码,也方便理解。我想要通过在命令行的输入,完成对粉笔题库的答题,结果在点击答案时遇到了问题。当被点击的选项没显示的时候,执行click会报错,让选项直接划到页面的时候也会,还存在各种问题,尝试多次无果,遂放弃。

from ctypes import pointer from lib2to3.pgen2 import driver from selenium import webdriver from selenium.webdriver.common.desired_capabilities import DesiredCapabilities from selenium.webdriver.support.wait import WebDriverWait#引入 WebDriverWait对象 from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By from selenium.webdriver.chrome.options import Options from selenium.webdriver.common.action_chains import ActionChains from selenium.webdriver.common.keys import Keys import time import requests import json import re def getUrl(): global driver d = DesiredCapabilities.CHROME d['loggingPrefs'] = { 'performance':'ALL' } chrome_options = Options() # 解决方法 chrome_options.add_experimental_option('w3c', False) driver = webdriver.Chrome(desired_capabilities=d, options=chrome_options) #主页链接 homePageUrl = "https://spa.fenbi.com/tiku/guide/catalog/xingce?prefix=xingce" driver.implicitly_wait(5) driver.get(homePageUrl) #加载cookie cookies = [ ] for item in cookies: driver.add_cookie(item) driver.get(homePageUrl) keyPointTreeXpath = '//*[@id="calalog-page"]/main/div[1]/div[2]/app-keypoint-catalog/div/div[2]/ul' keyPointTree = driver.find_element(By.XPATH,keyPointTreeXpath) print(type(keyPointTree)) # 获取子节点 keyPoints = keyPointTree.find_elements(By.XPATH,'*') for keyPoint in keyPoints: print(keyPoint.text) choose = input() choosePoint = keyPoints[int(choose)] choosePoint.click() pointTree = choosePoint.find_elements(By.XPATH,'*') points = pointTree[1].find_elements(By.XPATH,'*') for point in points: detailText = point.find_elements(By.TAG_NAME,'p') print(detailText[0].text,detailText[1].text) choose = input() divs = points[int(choose)].find_elements(By.TAG_NAME,'div') divs[1].click() wait = WebDriverWait(driver,10) allQuestionsXpath = '//*[@id="app-practice"]/main/section' allQuestions = wait.until(EC.presence_of_element_located((By.XPATH,allQuestionsXpath))) questions = allQuestions.find_elements(By.XPATH,'*') for question in questions: article = question.find_element(By.TAG_NAME,'article') print(article.text) answers = question.find_element(By.TAG_NAME,'ul') answers = answers.find_elements(By.XPATH,"*") for answer in answers: print(answer.text) choose = input() label = answers[int(choose)].find_element(By.TAG_NAME,'p') driver.execute_script("arguments[0].scrollIntoView();", label) label.click() # print(type(label)) # element = driver.find_element() # # label = driver.find_element(By.XPATH,xpath) 1 # request_log = driver.get_log('performance') # for log in request_log: # msg = json.loads(log['message']) # request = msg['message']['params'].get('request') # if(request is None): # continue # url = request.get('url') # questionUrl = 'https://tiku.fenbi.com/api/xingce/questions' # if(questionUrl in url): # print(url) # driver.get(url) # source = etree.HTML(driver.page_source) # test = source.xpath('/html/body/pre/text()')[0] # print('========================================') # 2 # data = json.loads(test) # for item in data: # str = item['content'] # str = str.replace('<u>','') # str = str.replace('</u>','') # str = str.replace('<p>','') # str = str.replace('</p>','') # str = str.replace(' ','') # print(str) # answer = item['accessories'] # options = answer[0]['options'] # index = 0 # for option in options: # print(index,"."+option) # index += 1 # x = input() # correctAnswer = item['correctAnswer'] # if(x==correctAnswer['choice']): # print("right!") # else: # print("false!正确答案是:",correctAnswer['choice']) if '_main_': getUrl()

如果想看看效果,填入自己的cookie即可。

直接获取数据

当我想模拟页面点击失效后,我就换了个思路,直接去获取页面加载的接口。
使用如下方法获取到所有接口,然后根据自己观察,找到匹配的接口。直接打开接口页面获取数据。

driver.get_log('performance')

不过我观察了下粉笔的网站,原本有数据那个接口,现在返回为空,具体原因不清楚了。
ps,要调用上面的方法,上面说的w3c属性要改成false。


__EOF__

本文作者阿飞飞啊飞
本文链接https://www.cnblogs.com/afei123/p/16379295.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   阿飞飞啊飞  阅读(159)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
点击右上角即可分享
微信分享提示