1

问题

在进行网络数据采集(爬虫)时,可能会遇到这样的情况:需爬取的网站为动态网站。

举例来说,在网页界面,如果使用鼠标进行悬停、点击某处等操作,可以 “唤出” 额外的内容(如图1,弹窗中包含文字和图片信息),此时这些额外内容的 HTML 源码从隐藏变为可见,但网页的 URL 却未改变。

若想采集这些 “隐藏的信息” ,用于爬取静态网页的 requests 就力不从心了。此时可以使用 selenium 来模拟用户使用浏览器的操作,以获取 “隐藏的信息” 。

知乎主页点击 “私信” 展示的弹窗
图1:点击知乎主页的 “私信”,即可得到一个包含文字和图片信息的弹窗

解决方案

1.1 文字信息

功能:点击网页中某处后出现弹窗,获取弹窗中的文字信息

  1. 在网上下载 selenium 适用于 Firefox 浏览器的驱动文件 geckodriver.exe,并将其存储至 python 项目的路径中。

  2. 导入本例中所需的包和模块:

    • 注:对于 pyautogui,直接在 cmd 中输入 “pip install pyautogui” 可能会安装失败。可以在 PyAutoGUI 官网 下载安装程序,再在 cmd 中进入该文件的目录,执行 “python setup.py install” 即可安装成功。
    import pandas as pd
    from selenium import webdriver
    import os, time, random
    from selenium.webdriver.common.action_chains import ActionChains
    import pyautogui
  3. 利用 selenium 中的 webdriver 模块,打开 Firefox 浏览器并进入网页。此时会自动弹出一个浏览器界面,可以自动/手动进行操作。

    driver = webdriver.Firefox() # 驱动打开Firefox浏览器
    url = '请输入爬取网站的URL'
    driver.get(url)  # 驱动进入网页
    time.sleep(3)  # 设置爬虫时间间隔:IP保护
  4. warning:网页若需要输入验证码、登录账号,则需手动操作完毕后,再运行后续代码。
  5. 利用 pandas 创建一个 dataframe,用来保存爬取到的信息。

    df = pd.DataFrame(columns=['']) # 请在 columns 参数后输入列名
  6. 获取弹窗中的文字信息:

    # 请额外加入循环代码,以自动获取数据:
    
    xpath = '点击按钮的xpath'
    xpath_info = '弹窗中显示的文字信息的xpath'
    xpath_close = '弹出窗口关闭按钮的xpath'
    
    try:
     driver.find_element_by_xpath(xpath).click()  # 驱动点击按钮
     text = driver.find_element_by_xpath(xpath_info).text  # 获取数据
     driver.find_element_by_xpath(xpath_close).click()  # 驱动关闭按钮
     time.sleep(random.random() * 3)  # IP保护
    except Exception as e:
     print(repr(e))
    
    driver.quit()  # 关闭所有浏览器窗口
  7. 输出表格数据:

    df.to_excel('文件存储位置' + os.sep + '文件名.xlsx', index=False)  # 数据输出

1.2 图片信息

功能:弹窗中存在图片信息,需要右键点击,并保存至本地

  1. 打开浏览器及网页,手动输入验证码、进行账号登录等操作同上。此处不再赘述。
  2. 右键点击图片,并保存至本地默认存储位置:

    • warning:请运行下面循环后,迅速将界面切换至驱动打开的 Firefox 浏览器界面(保持浏览器界面为当前窗口)!否则图片无法保存!
    xpath = '图片的xpath'
    name = '图片名称'
    
    # 请额外加入循环代码,以自动获取数据:
    
    try:
     context_click = driver.find_element_by_xpath(xpath)
     time.sleep(2)
     ActionChains(driver).context_click(context_click).perform()  # 实现点击鼠标右键
     time.sleep(1)
     pyautogui.typewrite(['v'])  # 敲击V进行保存
     time.sleep(1)
     pyautogui.typewrite(name)  # 重命名
     time.sleep(1)
     pyautogui.typewrite(['enter']) # 确定保存
     time.sleep(1)
     pyautogui.typewrite(['enter'])
     pyautogui.typewrite(['enter'])  # 电脑存在bug,敲击一次enter有时无法保存,因此连按3次
     time.sleep(random.random() * 3)  # IP保护
    except Exception as e:
     print(repr(e))

讨论

  • 本文代码未涉及到反爬虫问题。在爬取某些网站时,可能需要采取反爬虫措施。
  • 本文代码仅解决了 “鼠标点击某处,出现弹窗,需获取其中信息” 的问题。仍然存在其他的动态网页形式,如滚动产生新数据(信息流)等形式,可参考 selenium 的其他用法。

参考

注:转载请注明出处

去码头整点薯条
1 声望1 粉丝

Internal Server Error