Python实战:构建一个自动化的MOOC课程评论爬虫

作者信息
Name :Zing ;
Ema i l : bwcxzsj@stu. hbnu. edu. cn

目录

一、自动化流程介绍

1.1获取登录二维码

1.2用户扫描二维码

1.3验证登录状态

1.4课程搜索及保存封面图片

1.5点击指定搜索结果

1.6获取课程评价信息

二、代码实现

(一)准备工作

a.自动化流程图

b.导入需要的包

(二)定义功能函数并调试程序

1.def del_and_create_dir(filename):

2.def get_browser_version():

3.def auto_update_driver():

4.def save_course_images(driver, num_images):

5.def download_qr_code():

6 .def qr_code_login():

7.def get_MOOC(browser, url, search_text, sum_page, num_images):

8.编写主程序调用功能函数运行


简单说明

    在上一篇博客中,我们了解了爬虫的基本概念和基础功能,并用python实现了一个简单的收集慕课网站上相关课程的评论的爬虫程序。在这篇文章中我们基于这个程序做了简单的改进,增加了一些新的功能,如增添了一个用户扫码登录功能,以及爬取到的内容不仅是评论的文字也能收集该课程的封面图片等。下面我将对这个爬虫程序进行详细的讲解。

一、自动化流程介绍

该实战代码主要实现了通过扫码登录并利用Selenium爬取MOOC课程信息的完整流程。

1.1获取登录二维码

      通过download_qr_code函数获取扫码登录页面的二维码图片及其对应的唯一标志key(pollKey)。该函数访问MOOC网站的扫码登录接口,下载并保存二维码图片,同时返回用于轮询登录状态的pollKey。

1.2用户扫描二维码

    poll_server函数利用pollKey进行轮询,检查用户是否已扫码并确认登录。通过持续请求服务器,判断扫码状态是否变更为已扫码成功状态,一旦成功,则获取服务器返回的token。

1.3验证登录状态

    login_with_token函数使用获取的token向服务器验证登录状态,并获取登录后的cookies。整个扫码登录流程通过qr_code_login函数协调执行,返回登录后的cookies。

    在获取到登录后的cookies后,代码进入下一阶段。get_MOOC函数首先初始化Selenium的Edge浏览器驱动并打开MOOC网站。然后,通过调用qr_code_login函数获取登录后的cookies,并将这些cookies添加到Selenium浏览器会话中,确保浏览器具有登录状态。

1.4课程搜索及保存封面图片

    代码进行课程搜索。在页面加载完成后,利用Selenium找到搜索框并输入搜索关键词,然后点击搜索按钮。搜索结果加载后,切换到新打开的窗口,保存指定数量的课程封面图片。

1.5点击指定搜索结果

    在保存封面图片后,点击搜索结果中的第一个课程,进入课程详情页面。然后点击页面中的“课程评价”按钮,打开评价页面。

1.6获取课程评价信息

    代码随后开始爬取评价信息。通过PyQuery解析页面内容,获取当前页面的所有评价文本,并保存到本地文件中。同时,代码会对当前页面截图保存。爬取当前页面的评价信息后,点击“下一页”按钮,重复上述过程,直到爬取完指定数量的页面。

以上是基于整个流程的总体介绍,下面我们来编写代码进行详细解释。

二、代码实现

(一)准备工作

a.自动化流程图

b.导入需要的包
import requests
import time
import os
import re
import xml.dom.minidom
import urllib.request
from selenium import webdriver
from selenium.webdriver.edge.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from pyquery import PyQuery

 注意:最开始导入这些库的时候,部分库可能不存在电脑上,需要手动在pycharm或其他编译软件终端 输入 (以requests库不存在为例)pip install requests 并按回车键

(二)定义功能函数并调试程序

1.def del_and_create_dir(filename):

  创建一个函数del_and_create_dir用于删除已存在的文件并创建一个新的目录。它首先获取文件名的目录部分,然后检查该目录是否存在,如果不存在则创建它。如果文件已存在,则删除它。

def del_and_create_dir(filename):
    directory = os.path.dirname(filename)
    if not os.path.exists(directory):
        os.makedirs(directory)
    if os.path.exists(filename):
        os.remove(filename)
2.def get_browser_version():

  创建一个get_browser_version(函数用于获取Edge浏览器的版本。它解析Edge浏览器安装目录下的一个XML文件,从中提取版本信息。

def get_browser_version():
    dom = xml.dom.minidom.parse(r'C:\Program Files (x86)\Microsoft\Edge\Application\msedge.VisualElementsManifest.xml')
    dom_ele = dom.documentElement
    ve = dom_ele.getElementsByTagName('VisualElements')
    ve_text = ve[0].toxml()
    rematch = re.match(r'(.*)\"(.*)\\VisualElements\\Logo.png', ve_text)
    edge_version = rematch.group(2)
    return edge_version
3.def auto_update_driver():

  创建一个auto_update_driver函数用于自动更新Edge浏览器的驱动程序。它指定驱动程序的路径,创建一个Service对象,然后使用这个服务创建一个webdriver.Edge实例,并最大化浏览器窗口。

def auto_update_driver():
    driver_path = 'c:\\...\\mse...exe'
    service = Service(executable_path=driver_path)
    driver = webdriver.Edge(service=service)
    driver.maximize_window()
    return driver

注意:这里需要将driver_path换成你自己下载下来的浏览器驱动路径

4.def save_course_images(driver, num_images):

  创建一个save_course_images函数用于保存课程图片。它使用Selenium找到页面上的图片元素,然后下载并保存指定数量的图片。

def save_course_images(driver, num_images):
    images = driver.find_elements(By.CSS_SELECTOR, ".m-course-card-list .u-img img")
    for index, img in enumerate(images):
        if index >= num_images:
            break
        src = img.get_attribute('src')
        if src:
            filename = f"result\\course_image_{index}.jpg"
            del_and_create_dir(filename)
            urllib.request.urlretrieve(src, filename)
            print(f"Saved image {index} to {filename}")

  首先 使用 driver.find_elements(By.CSS_SELECTOR, ".m-course-card-list .u-img img") 通过CSS选择器找到网页上所有类名为 .m-course-card-list .u-img img 的图片元素。

  然后 遍历这些图片元素。对于每个元素,执行以下操作:

   ▷使用 enumerate 获取当前图片的索引 index 和图片元素 img

   ▷如果当前索引 index 大于或等于指定的图片数量 num_images,则跳出循环。

   ▷获取图片元素的 src 属性,即图片的URL。

   ▷如果 src 存在,定义一个文件名 filename,格式为 "result\\course_image_{index}.jpg"

   ▷调用 del_and_create_dir 函数确保保存图片的目录存在且为空。

   ▷使用 urllib.request.urlretrieve 从 src URL下载图片并保存到 filename

   ▷打印一条消息,表明图片已保存。

5.def download_qr_code():

  创建一个download_qr_code函数用于下载登录用的二维码。它创建一个`requests`会话,发送HTTP请求以获取二维码的URL和轮询密钥,然后下载并保存二维码图片。

def login_with_token(session, token):
    vaildateUrl = f'https://www.icourse163.org/passport/logingate/mocMobChangeCookie.htm?token={token}&returnUrl=aHR0cHM6Ly93d3cuaWNvdXJzZTE2My5vcmcvaW5kZXguaHRt'
    header = {
        'referer': 'https://www.icourse163.org/',
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36'
    }
    session.get(vaildateUrl, headers=header)
    print("登录成功")
    return session.cookies.get_dict()

该段代码的具体操作如下:

     ▷定义一个vaildateUrl ,这个URL指向一个生成二维码的接口。

     ▷创建一个请求头 header,包含了一些必要的HTTP头信息,如 referer(表示请求来源)和 user-agent(模拟用户代理,即浏览器信息)。

     ▷使用 session.get(url, headers=header) 发送一个GET请求到指定的URL,并将响应内容解析为JSON格式。

     ▷函数返回创建的会话对象 session 和 pollKey

6 .def qr_code_login():

定义了一个名为 qr_code_login 的函数,其功能是使用二维码进行登录。

def qr_code_login():
    session, pollKey = download_qr_code()
    os.system('start qr_code.jpg')
    token = poll_server(session, pollKey)
    if token:
        return login_with_token(session, token)
    else:
        print("扫码超时,请重试。")
        return None

 这段代码的具体操作如下:

·调用 download_qr_code 函数

这个函数访问MOOC网站的扫码登录接口,下载并保存二维码图片,并返回一个会话对象 session 和一个用于轮询登录状态的密钥 pollKey。 

·显示二维码图片

os.system('start qr_code.jpg') 这行代码会在操作系统中打开名为 qr_code.jpg 的二维码图片,以便用户扫描。

·调用 poll_server 函数

这个函数会使用 session 和 pollKey 对服务器进行轮询,检查用户是否已经扫描二维码并确认登录。如果用户扫码成功,这个函数将返回一个 token

·使用 token 进行登录验证

如果 token 存在(即用户已成功扫码),则调用 login_with_token 函数。这个函数使用 token 向服务器验证登录状态,并获取登录后的 cookies。

·处理登录结果:如果 token 存在且登录成功,qr_code_login 函数将返回登录后的 cookies。如果 token 不存在(可能是由于扫码超时或其他原因),函数将打印一条消息提示用户扫码超时,并返回 None

7.def get_MOOC(browser, url, search_text, sum_page, num_images):

  这段代码定义了一个名为 get_MOOC 的函数,其功能是自动登录一个MOOC(大规模开放在线课程)网站,搜索特定的课程,并获取课程的评论。
 

def get_MOOC(browser, url, search_text, sum_page, num_images):
    driver = auto_update_driver()
    driver.get(url)
    time.sleep(5)

    cookies = qr_code_login()
    if not cookies:
        driver.quit()
        return

    # 将cookies添加到Selenium会话中
    for cookie_name, cookie_value in cookies.items():
        driver.add_cookie({'name': cookie_name, 'value': cookie_value, 'domain': '.icourse163.org'})

    driver.refresh()
    time.sleep(5)

    try:
        search_box = WebDriverWait(driver, 10).until(
            EC.presence_of_element_located((By.CSS_SELECTOR, "input.j-textarea.inputtxt"))
        )
        driver.execute_script("arguments[0].value = arguments[1];", search_box, search_text)

        search_button = WebDriverWait(driver, 10).until(
            EC.element_to_be_clickable((By.CSS_SELECTOR, "span.u-icon-search2.j-searchBtn"))
        )
        search_button.click()
        time.sleep(5)

        main_window = driver.current_window_handle
        all_windows = driver.window_handles
        for window in all_windows:
            if window != main_window:
                driver.switch_to.window(window)
                break

        save_course_images(driver, num_images)

        first_result = WebDriverWait(driver, 10).until(
            EC.element_to_be_clickable((By.CSS_SELECTOR, ".u-clist .f-thide"))
        )
        first_result.click()
        time.sleep(5)

        main_window = driver.current_window_handle
        all_windows = driver.window_handles
        for window in all_windows:
            if window != main_window:
                driver.switch_to.window(window)
                break

        review_button = WebDriverWait(driver, 10).until(
            EC.element_to_be_clickable((By.ID, "review-tag-button"))
        )
        review_button.click()
        time.sleep(2)

        for page in range(sum_page):
            next_source = driver.page_source
            next_query = PyQuery(next_source)
            content = next_query(".ux-mooc-comment-course-comment_comment-list_item_body_content")
            time_flag = time.strftime("%Y_%m_%d_%H_%M_%S", time.localtime())
            filename = f"result\\comment_{time_flag}.txt"
            del_and_create_dir(filename)

            with open(filename, "a", encoding="utf-8") as f:
                for item in content.items():
                    item_text = item.children().text()
                    f.write(item_text + "\n")

            screenshot_filename = f"result\\screenshot_{time_flag}.png"
            del_and_create_dir(screenshot_filename)
            driver.save_screenshot(screenshot_filename)

            try:
                next_element = driver.find_element(By.CLASS_NAME, "ux-pager_btn__next")
                next_element.click()
                time.sleep(3)
            except Exception as e:
                print("No more pages or error occurred:", e)
                break

    except Exception as e:
        print(f"An error occurred: {e}")
    finally:
        driver.quit()

具体步骤如下:

▷使用 auto_update_driver 函数初始化并启动一个Edge浏览器的WebDriver。

▷使用 driver.get(url) 打开指定的MOOC网站的URL。

▷等待5秒,确保页面加载完成。

▷调用 qr_code_login 函数进行二维码登录。如果登录失败,关闭浏览器并退出函数。

▷将登录成功后获取的cookies添加到Selenium会话中,以保持登录状态。

▷刷新页面,并再次等待5秒。

▷使用WebDriverWait和EC(预期条件)等待搜索框出现,并输入搜索文本。

▷点击搜索按钮,并等待5秒。

▷切换到新打开的窗口(通常是搜索结果页面)。

▷调用 save_course_images 函数保存指定数量的课程图片。

▷点击搜索结果中的第一个课程,并等待5秒。

▷再次切换到新打开的窗口(通常是课程详情页面)。

▷点击评论按钮,并等待2秒。

▷循环指定的页数,对于每一页执行以下操作:

  • 获取当前页面的源代码。
  • 使用PyQuery解析源代码,提取评论内容。
  • 将评论内容保存到文本文件中。
  • 保存当前页面的截图。
  • 尝试点击下一页按钮,如果失败(比如没有更多页面或发生错误),则跳出循环。

▷ 如果在执行过程中发生任何异常,打印错误信息。

▷ 最后,无论是否发生异常,关闭浏览器。

8.编写主程序调用功能函数运行
if __name__ == '__main__':
    browser = "edge"
    url = "https://www.icourse163.org"
    search_text = "Python语言程序设计"
    sum_page = 3
    num_images = 3
    get_MOOC(browser, url, search_text, sum_page, num_images)
    print("Current Browser Version:", get_browser_version())

  • 13
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值