└── com ├── CrawlerQQ.py ├── ReadFileSendMail.py ├── SendMailUtil.py ├── Test.py └── chromedriver.exe /com/CrawlerQQ.py: -------------------------------------------------------------------------------- 1 | import csv 2 | import time 3 | from lxml import html 4 | from selenium import webdriver 5 | from com.SendMailUtil import SendMail 6 | 7 | etree = html.etree 8 | 9 | 10 | def parser(): 11 | driver = webdriver.Chrome("chromedriver.exe") 12 | return driver 13 | 14 | 15 | def login(url): 16 | driver = parser() 17 | driver.get(url) 18 | time.sleep(5) 19 | get_data(driver) 20 | return driver 21 | 22 | 23 | def get_data(driver): 24 | for _ in range(10): # 可根据群成员的数量大小调整此数值,数值越大耗时越长 25 | scroller(driver) 26 | time.sleep(1) 27 | data = driver.page_source 28 | html = etree.HTML(data) 29 | mem_info_list = html.xpath('//*[@id="groupMember"]/tbody[@class="list"]/tr') # TODO QQ群成员列表 30 | 31 | with open('QQ.csv', 'a+', newline='', encoding='utf-8') as f: 32 | writer = csv.writer(f, dialect="excel") 33 | writer.writerow(['成员', 'QQ号', '性别', 'Q龄', '入群时间', '最后发言']) 34 | 35 | for mem_info in mem_info_list: 36 | 37 | data = {'成员': str(mem_info.xpath('./td[3]//text()')[3]).replace('\U0001f60a', '').strip(), 38 | 'QQ号': str(mem_info.xpath('./td[5]//text()')[0]).replace('\U0001f60a', '').strip(), 39 | '性别': str(mem_info.xpath('./td[6]//text()')[0]).replace('\U0001f60a', '').strip(), 40 | 'Q龄': str(mem_info.xpath('./td[7]//text()')[0]).replace('\U0001f60a', '').strip(), 41 | '入群时间': str(mem_info.xpath('./td[8]//text()')[0]).replace('\U0001f60a', '').strip(), 42 | '最后发言': str(mem_info.xpath('./td[9]//text()')[0]).replace('\U0001f60a', '').strip()} 43 | print(data) 44 | 45 | if data: 46 | # writer.writerow(['成员', 'QQ号', '性别', 'Q龄', '入群时间', '最后发言']) 47 | # writer.writerow( 48 | # [data['成员'].replace('\xa0', ''), data['QQ号'].replace('\xa0', ''), 49 | # data['性别'].replace('\xa0', ''), data['Q龄'].replace('\xa0', ''), 50 | # data['入群时间'].replace('\xa0', ''), data['最后发言'].replace('\xa0', '')]) 51 | writer.writerow( 52 | [data['成员'], data['QQ号'], 53 | data['性别'], data['Q龄'], 54 | data['入群时间'], data['最后发言']]) 55 | 56 | # 发送邮件 57 | sendmail(data['QQ号'] + "@qq.com"); 58 | 59 | 60 | def sendmail(user): 61 | SendMail().sendmail("are you ok", "最近过的还好吗,加我微信聊聊天吧WX666", user) 62 | 63 | 64 | def logout(driver): 65 | driver.find_element_by_class_name("logout").click() 66 | # driver.close()需要在driver.quit()前面,因为driver.quit()方法会先关闭所有窗口并退出驱动,如果再次调用close则会报错 67 | driver.close() 68 | driver.quit() 69 | 70 | 71 | def scroller(driver): 72 | js = "var q=document.documentElement.scrollTop=100000" 73 | driver.execute_script(js) 74 | 75 | 76 | def run(): 77 | QQnum = input('请输入一个【一个或多个QQ群号】:') 78 | for num in QQnum.split(','): 79 | url = "https://qun.qq.com/member.html#gid=" + num 80 | driver = login(url) 81 | 82 | logout(driver) # TODO 退出登录 83 | 84 | 85 | if __name__ == '__main__': 86 | run() 87 | -------------------------------------------------------------------------------- /com/ReadFileSendMail.py: -------------------------------------------------------------------------------- 1 | from com.SendMailUtil import SendMail 2 | 3 | 4 | class ReadFileSendMail(object): 5 | 6 | # 读取文件返回一个列表 7 | @staticmethod 8 | def readfile(filepath): 9 | file = open(filepath, "r") 10 | # file = open("emails.txt", "r") 11 | 12 | lines = file.readlines() 13 | 14 | return lines 15 | 16 | # 参数为接收者列表 17 | @staticmethod 18 | def sendmail(title, content, emails): 19 | for _ in range(len(emails)): 20 | emails[_] = emails[_].strip() # 去掉每一行前后的换行符 21 | 22 | SendMail.sendmail(title, content, emails) 23 | 24 | 25 | if __name__ == "__main__": 26 | path = input("输入列表文件的路径") 27 | 28 | ReadFileSendMail.sendmail("JND-群:36103909709,上分,送烟", "你好;JND-群:36103909709,上分,送烟只是测试若有打扰;请您包含", 29 | ReadFileSendMail.readfile(path)) 30 | -------------------------------------------------------------------------------- /com/SendMailUtil.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: UTF-8 -*- 3 | # 上面这两行是因为python在默认的情况下不支持源码中的中文编码,加上后会忽略中文编码 4 | 5 | 6 | import smtplib 7 | from email.mime.text import MIMEText 8 | from email.mime.multipart import MIMEMultipart 9 | from email.header import Header 10 | from email import encoders 11 | 12 | 13 | class SendMail(object): 14 | 15 | # 静态方法不需要第一个参数self,可以直接类名调用 16 | @staticmethod 17 | def sendmail(title, content, users): 18 | # 申明第三方服务关键信息 19 | 20 | # mail_host = "smtp.qq.com" 21 | # mail_user = "503203440@qq.com" 22 | # mail_pass = "***" 23 | # sender = "503203440@qq.com" # 发送者邮箱 24 | 25 | mail_host = "smtp.163.com" 26 | mail_user = "yx503203440@163.com" 27 | mail_pass = "***" 28 | sender = 'yx503203440@163.com' # 发送者邮箱 29 | 30 | receivers = users # 接收者邮箱(数组) 31 | 32 | # 创建一个带附件的实例 33 | message = MIMEMultipart() 34 | message['From'] = Header('小熊科技', 'utf-8') 35 | # message['To'] = Header('YOU', 'utf-8') # 这里可以不用设置 36 | subject = title 37 | message['Subject'] = Header(subject, 'utf-8') 38 | 39 | # 邮件正文内容 40 | message.attach(MIMEText(content, 'plain', 'utf-8')) 41 | # # 构造附件 42 | # file_name = 'zcpd_backup.sql' 43 | # attr = MIMEText(open('C:/Users/YX/Desktop/zcpd_20190715_003047.sql', 'rb').read(), 'base64', 'utf-8') # 文件路径 44 | # attr['Content-Type'] = 'application/octet-stream' 45 | # 46 | # # 这么写不行,附件会变成.bin后缀名的文件 47 | # # attr['Content-Disposition'] = 'i;filename=sql备份.sql' # + file_name 48 | # 49 | # # 这样设置附件名 50 | # attr.add_header('Content-Disposition', 'attachment', filename=file_name) 51 | # 52 | # # encoders.encode_base64(attr) 53 | # 54 | # # 添加附件 55 | # message.attach(attr) 56 | # 如果有多个附加,可以按此方式构造多个附件多次调用message.attach() 57 | 58 | # try: 59 | # smtpObj = smtplib.SMTP() 60 | # smtpObj.connect(mail_host) 61 | # smtpObj.login(mail_user, mail_pass) 62 | # smtpObj.sendmail(sender, receivers, message.as_string()) 63 | # print('发送成功') 64 | # except smtplib.SMTPException: 65 | # print('发送失败') 66 | 67 | smtpObj = smtplib.SMTP() 68 | smtpObj.connect(mail_host) 69 | smtpObj.login(mail_user, mail_pass) 70 | smtpObj.sendmail(sender, receivers, message.as_string()) 71 | print('发送成功') 72 | -------------------------------------------------------------------------------- /com/Test.py: -------------------------------------------------------------------------------- 1 | from com.SendMailUtil import SendMail 2 | from com.ReadFileSendMail import * 3 | 4 | 5 | class Test(object): 6 | 7 | def __init__(self): 8 | print("开始运行") 9 | # SendMail.sendmail("你好", "我是测试", "yx503203440@163.com") 10 | path = input("输入文件的路径") 11 | mails = ReadFileSendMail.readfile(path) 12 | ReadFileSendMail.sendmail("晚上好", "我在测试发送邮件", mails) 13 | 14 | 15 | if __name__ == "__main__": 16 | Test() 17 | -------------------------------------------------------------------------------- /com/chromedriver.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/503203440/Crawler/4c3df1127f1bf6614af172bdb4ccb65c1579f54f/com/chromedriver.exe --------------------------------------------------------------------------------