解决页面滚动并滚动停止时间问题案例


文章目录

  • 1. 问题引入
  • 2. 屏幕滚动问题
  • 3. 滚动停止的方法
  • 4. 案例

1. 问题引入 现在的网页都是采用ajax加载的,如果我们要用selenium爬取网页的全部内容,就必须等待网页彻底加载完毕。而一页很显然不能加载完,那就需要拖动滚动条,直到所有内容加载完。而且,如果你爬取的时多个网页,那么你要控制住,当页面内容加载完后停止滚动。然后开始获取页面内容并解析爬取。本文就是介绍这两点内容的。我查找了许多帖子和博客,最终没有能够如愿解决。后来结合查到的信息内容和自己的思想解决了问题。全用的python和selenium知识。如你有更好的方法欢迎留言,留链接,一定借鉴。
2. 屏幕滚动问题 滚屏问题,我查了很多帖子,都是操作滚动条。而我的案例滚动条时隐藏的,很多次都没有成功。后来采用了send_keys(Keys.PAGEUP)解决了问题。具体代码如下:
from selenium import webdriver from selenium.webdirver.commen.keys import Keys import time # 实例化web驱动 driver = webdriver.Chrome() # 你要爬取的网页地址,建议换成自己的,我这个需要扫码登录 url='https://www.pypypy.cn/#/apps/1/lecture/5cd9766a19bbcf00015547d0 driver.get(url) time.sleep(2) # 让页面加载完毕再操作,避免无效操作 driver.find_element_by_tag_name('body').click()# 这一步的意思就是在获得的页面上点击一下,这步很关键,如果不点击,后面的翻页动作将不会进行 for i in range(20): driver.find_element_by_tag_name('body').send_keys(Keys.PAGE_UP) # 向上翻页20次,暂时先用这种办法,后面会介绍更好的控制方法 driver.quit() # 退出网页

这是页面滚动方法,如果你的电脑支持快捷键组合“Ctrl+Home”快速回到页面首,那就直接发送这个组合键将更快。无奈我的这个组合键时“Fn+Home”,而Selenium中没有这个组合键,所以就只能用PageUp多翻几次了。
3. 滚动停止的方法 【解决页面滚动并滚动停止时间问题案例】我查了一下网上提供的方法,有判断页面是否加载完毕的方法,嫌麻烦,关键是我没有操作成功。故而又从一个人的建议那里得到了灵感。可以找这个页面经常出现的标签,大部分是“div”标签,可以len一下当前的标签数目,然后让页面滚动一阵子,再次len一下此时的标签数,如果不相等,那么肯定还没有加载完啦。所以有了下面的代码。
from selenium import webdriver import time from selenium.webdriver.common.keys import Keys from bs4 import BeautifulSoup # 这是我要爬取的页面的url,构成一个列表,你要换成自己的哦 urls= ['https://www.pypypy.cn/#/apps/2/lecture/5dc547a8faeb8f00015a0ea8','https://www.pypypy.cn/#/apps/2/lecture/5dc547a9faeb8f00015a0ead','https://www.pypypy.cn/#/apps/2/lecture/5dc547aafaeb8f00015a0eb0'] # 实例化web驱动 driver = webdriver.Chrome() for url in urls: driver.get(url) time.sleep(1)让页面加载完毕,具体等待时间根据网页反应时间定 driver.find_element_by_tag_name('body').click()# 点击一下页面 s_num = 1# 后面用来记初始div标签的数目,暂时赋值为1为了启动循环 f_num = 0# 记录滚动后div标签的数目 while s_num > f_num:# 开启while循环,如果满足这个条件就一直循环下去,直到页面加载完毕后s_num== f_num 循环结束 source = driver.page_source# 获取网页内容 soup = BeautifulSoup(source,'lxml')# 解析 elements = soup.find_all('div')# 查找当前所有的div f_num = len(elements)# len()函数记录div数目,并赋值给f_num driver.find_element_by_tag_name('body').click()# 点击一下,后面要开始翻页了,每次开始翻页前都要点一下啊 for i in range(50):# 滚动50次,一般滚动几次div数肯定就不一样了 driver.find_element_by_tag_name('body').send_keys(Keys.PAGE_UP)# 翻页 time.sleep(0.01) # 每次翻页时间间隔,你也可以自己设定 time.sleep(0.1) # 页面加载时间 source = driver.page_source# 再次获取网页内容 soup = BeautifulSoup(source, 'lxml')# 解析 elements = soup.find_all('div') # 查找滚动后的所有div标签 s_num = len(elements)# 结束时的元素数赋值给 s_num

以上是判断页面是否加载完毕,加载完毕后即停止翻动。
4. 案例 下面是我的一个案例,我要爬取多个网页,并且需要扫码登录的。爬取网页的文字内容,并且保存为txt文档。仔细看注释:
# 导入必要模块 from selenium import webdriver import time from selenium.webdriver.common.keys import Keys from bs4 import BeautifulSoup # 实例化驱动 driver = webdriver.Chrome() url_0 = 'https://www.pypypy.cn/#/app-center'# 登录页面的网址 # 要爬取的网页的网址列表 urls= ['https://www.pypypy.cn/#/apps/2/lecture/5dc547a8faeb8f00015a0ea8','https://www.pypypy.cn/#/apps/2/lecture/5dc547a9faeb8f00015a0ead','https://www.pypypy.cn/#/apps/2/lecture/5dc547aafaeb8f00015a0eb0'] # 登录页面 driver.get(url_0) time.sleep(15)# 趁这个时间扫码登录,由于网页记住了cookie,后面再循环登录其他网页的时候就不需要扫码了 k = 0# 用来计算,写入文章标题时传入。 for url in urls_s: driver.get(url) driver.implicitly_wait(5) # 隐式等待,实际不需要5秒,什么时候加载完页面什么时候进行下一步 driver.maximize_window()# 窗口最大化 driver.implicitly_wait(5) s_num = 1 f_num = 0 while s_num > f_num: source = driver.page_source soup = BeautifulSoup(source,'lxml') elements = soup.find_all('div') f_num = len(elements)# 开始的元素数 driver.find_element_by_tag_name('body').click() # 先翻页一阵子,这里我定义50次 for i in range(50): driver.find_element_by_tag_name('body').send_keys(Keys.PAGE_UP) time.sleep(0.01) time.sleep(0.1) source = driver.page_source soup = BeautifulSoup(source, 'lxml') elements = soup.find_all('div') s_num = len(elements)# 结束时的元素数 time.sleep(1)# 全部加载完毕了,等待一下,保证下面要获取网页内容的完整性 # 获取网页内容 pageSource = driver.page_source soup = BeautifulSoup(pageSource, 'lxml') # 解析 contents = soup.find_all('div', class_="plugin-markdown-chat") # 所要的字符串藏再这个标签里,把所有此类标签找出来,结果是列表 with open('python_spider_0.txt', 'a', encoding='utf_8') as f:# 新键文本写入对象 f.write('\n')# 写入前换行 f.write('# **=第{}关=** #'.format(k))# 标题 f.write('\n')# 标题后换行 for i in contents:# 遍历 contents列表 f.write(i.text)#提取出字符串文本并写入 f.write('\n')# 这里每句换行 f.write('*=' * 100) # 写完一篇后画分割线 k += 1# 计数 time.sleep(1)# 开始下个页面前的短暂等待 print('over')# 所有页面爬取完的提示 time.sleep(1)# 1秒后退出浏览器 driver.quit()# 退出

以上的这个案例用到了前面介绍的所有内容,重复的步骤就不再注释。如有更好的建议欢迎留言,相互学习。

    推荐阅读