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

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()   # 退出

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

猜你喜欢

转载自blog.csdn.net/m0_46738467/article/details/113101506