实战02-selenium模拟QQ邮箱登录并批量爬取指定邮件的附件——体验版

实战02-selenium模拟QQ邮箱登录并批量爬取指定邮件的附件

        • 1.功能需求
        • 2.直接上代码
        • 3.数据作证
        • 4.掉坑经历

1.功能需求

诞生的背景:作为一个学委,尤其受疫情影响,同学发的一大堆邮件单个下载非常耗时,而且无聊。
由此想到了用爬虫可以批量抓取,学了一天,果断四处找资源,终于可以解放收作业了(不过,还有待完善的地方,后面再贴出来)

这个爬虫脚本实现的功能:首先模拟用户登录(通过账号、密码)qq邮箱,然后进去收件箱后,获取已读/未读的邮件列表,
写了个正则表达式用于筛选指定的邮件(可按需你需求替换正则模板即可),接着点进去下载附件(也就是,这也有个隐式条件,
里面一定要有附件,且只下载一个,这也是不够完善的地方)。下载完后直接返回,如此循环遍历(怪我写的很粗糙:)批量下载指定的文件

2.直接上代码

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from config import *
import time
import re

# 这里是浏览器驱动路径,也可防止系统环境变量就不用指定了
browser = webdriver.Chrome(executable_path="./chromedriver.exe")
wait = WebDriverWait(browser, 10)   # 设置下隐式等待时间10s


def mail_qq_login():
    try:
        browser.get("https://mail.qq.com/")
        browser.switch_to.frame("login_frame")
        login_bt = wait.until(
            EC.presence_of_element_located((By.CSS_SELECTOR, '#switcher_plogin'))
        )
        login_bt.click()    # 账号密码登录
        qq_nb = wait.until(
            EC.presence_of_element_located((By.ID,"u"))
        )
        qq_pw = wait.until(
            EC.presence_of_element_located((By.ID,"p"))
        )
        login_bt = wait.until(
            EC.element_to_be_clickable((By.CSS_SELECTOR,"#login_button"))
        )
        qq_nb.send_keys(QQ_NB)  # 账号 QQ_NB和QQ_PW放置在配置文件中,注意替换
        qq_pw.send_keys(QQ_PW)  # 密码
        login_bt.click()
    except TimeoutException:
        print("超时错误,重新登录...")
        mail_qq_login()


pattern = re.compile("^机.*17.*")    # 注意:这里需替换成你想爬取什么主题的邮件


def print_one_unread_mail(index):
    try:
        print(browser.page_source)
        mail_list = browser.find_elements_by_css_selector('.tf.no')
        print("print_one_unread_mail:%d" % len(mail_list))
        if re.match(pattern, mail_list[index].find_element_by_class_name('tt').text):
            print(mail_list[index].find_element_by_class_name('tt').text)
            mail_list[index].click()
            browser.find_element_by_partial_link_text("下载").click()
            print(browser.page_source)
            browser.back()
            time.sleep(2)
            browser.refresh()
            recv_option = wait.until(
                EC.presence_of_element_located((By.PARTIAL_LINK_TEXT, "收件箱"))
            )
            recv_option.click()
            main_frame = wait.until(
                EC.presence_of_element_located((By.CSS_SELECTOR, "#mainFrame"))
            )
            browser.switch_to.frame(main_frame)
        else:
            print(mail_list[index].find_element_by_class_name('tt').text)
            return
    except TimeoutException:
        print_one_unread_mail(index)


def main():
    mail_qq_login()
    recv_option = wait.until(
        EC.presence_of_element_located((By.PARTIAL_LINK_TEXT, "收件箱"))
    )
    recv_option.click()

    main_frame = wait.until(
        EC.presence_of_element_located((By.CSS_SELECTOR, "#mainFrame"))
    )
    browser.switch_to.frame(main_frame)
    mail_list = browser.find_elements_by_class_name("M")
    mail_num = len(mail_list)
    print(mail_num)

    mail_list = browser.find_elements_by_css_selector('.tf.no')
    print(len(mail_list))
    for i in range(len(mail_list)):
        print(i)
        print_one_unread_mail(i)


if __name__ == '__main__':
    main()

3.数据作证

实战02-selenium模拟QQ邮箱登录并批量爬取指定邮件的附件——体验版_第1张图片

4.掉坑经历

如图所示,道路千万条,安全第一条。。。
实战02-selenium模拟QQ邮箱登录并批量爬取指定邮件的附件——体验版_第2张图片

解决:采取了个简单的办法,在for循环每次调用print_un_read_mail前 睡眠一会,time.sleep(x)
  		有更好的办法,欢迎交流呀(我是爬虫小白)
此外,还有几个特别需注意的地方:
1.模拟登陆时,因为腾讯(不止qq邮箱,还有qq)的登陆页面用的是iframe,故先切换到登录的iframe才能找到用账号密码登录的选项
2.进去“收件箱”后,注意切换回“mainFrame”<----很重要,我掉坑了(一直定位不到邮件的主题元素),还折腾了好久
3.返回之后,记得刷新一下(因为qq邮箱用了JS动态渲染),里面iframe的上下文在返回后会刷新,再次定位元素会
	找不到的,如这个报错:element is not  attach  to  the  page  document,就是页面过时的问题

你可能感兴趣的:(Python爬虫)