2019年12月31日的那天晚上,看了网络上再说距离2000年,马上就是走过20个年头了,大学之前还没有微信,那个时候同学们都用QQ联系,后来才有了微信,注册后也不怎么用微信。可是工作以后,QQ逐渐被冷落了,不再更新QQ说说,不在更新QQ日志,不在踩空间,对QQ的热度,也随着青春的消逝,驻足在了回忆里。
2019年的最后一个晚上,有点伤感,感怀青春岁月吧。打开QQ、打开QQ空间,特别想给青葱岁月里的同学们带去久别的问候。从小学、初中、高中到大学,多多少少有留了300多个好友,一个好友发一条留言要1分钟的话,大概也需要5个小时。转念一想,何不写个批量脚本区留言。我不是一个职业写Python的程序员,写完自己的需求后,就随手写了这篇笔记,以便日后复习吧……
分四个步骤讲吧,先从开发环境说起,再是登录QQ空间,再是获取所有QQ好友,再是去留言。
一、开发环境
-
IDE:
PyCharm
-
编程语言:
Python3
,还要需要懂一点点点点前端知识 -
浏览器环境:
Chrome
、或者Firefox
-
浏览器驱动器:
Chrome
浏览器使用chromedriver
,Firefox
使用geckodriver
-
selenium:
pip3 install selenium
上面的驱动器版本要和你的浏览器版本相适应。
二、登录QQ空间
def login_qzone(url):
# 浏览器窗口最大化
driver.maximize_window()
# 浏览器地址定向为qq登陆页面
driver.get(url)
# 定位输入信息frame
# driver.switch_to.frame("login_frame")
"""
扫码登录
"""
"""
账号密码登录
"""
# # 自动点击账号登陆方式
# driver.find_element_by_id("switcher_plogin").click()
# # 账号输入框输入已知qq账号
# driver.find_element_by_id("u").send_keys("qq号码")
# # 密码框输入已知密码
# driver.find_element_by_id("p").send_keys("qq密码")
# # 自动点击登陆按钮
# driver.find_element_by_id("login_button").click()
# waiting_for_page_finish(15)
# driver.switch_to.default_content()
pass
其实,只要打开网页,扫码登录也可以,密码登录也可以,或者你电脑上直接登录QQ,然后使用QQ快捷登录。

三、查找所有的QQ好友
我是通过QQ空间的说说,艾特所有人的方式查找的,网上也有其他方法,我登录的PC端的QQ空间,就直接爬QQ空间提供的数据。
这种方式也挺坑的,当把焦点切换到@
所在的iframe
后,怎么都定位不到,后来在浏览器的一个新的Tab
上打开iframe
的链接时,发现了@
的class_name
。
代码片段:
先定位到 “说说”

分析网页源码可知,“说说”是一个可以点击的链接的文本,可以使用下面的方式定位。
print('查找说说....')
WebDriverWait(driver, 20, 1).until(
EC.presence_of_element_located((By.LINK_TEXT, '说说'))
)
print('找到了 说说 ,点击说说')
driver.find_element_by_link_text('说说').click()
定位 @
按钮
将焦点切换,切入到子iframe
中。
```python
WebDriverWait(driver, 10, 0.5).until(
EC.presence_of_element_located((By.ID, 'app_canvas_frame'))
)
driver.switch_to.frame('app_canvas_frame')
通过检查
的方式也是可以看到特征值
(我把能够唯一能够一个元素的值成为特征值,不知道职业说法,我这个说法,也好理解),比如classname

把iframe
中的src
拿出来在一个新的标签页打开,发现了运行时的特征值
,如下图所示,然后就用这个值去定位@
就可以了。

print('查找提到的人....')
WebDriverWait(driver, 10, 0.5).until(
EC.presence_of_element_located(
(By.XPATH, '/html/body/div/div[2]/div[3]/div/div[1]/div/div[2]/div/div[6]/div[1]/a[2]'))
)
print('找到了提到的人....')
上面是通过xpath
先判断一下@
是否可见,使用classname
的值at
也是可以的,下面就是使用了这个值来定位的。使用xpath
的好处是可以定位动态属性。
waiting_for_page_finish(2)
driver.find_element_by_class_name('at').click()
driver.find_element_by_class_name('at').click()
waiting_for_page_finish(2)
然后是模拟点击,把那个好友选择框调出来。
如果你问,为什么点两下?那请你自己去实践吧……

获取所有好友
我是使用列表存储的,然后使用集合来去重
friend_qq = []
friend_name = []
for i in range(0, 13):
print("i = " + str(i))
top = 400 * (i + 1)
js = 'document.getElementsByClassName("friend_list")[0].scrollTop=' + str(top)
# 就是这么简单,修改这个元素的scrollTop就可以
driver.execute_script(js)
waiting_for_page_finish(2)
ul = driver.find_element_by_class_name('fSelector_friendlist')
lis = ul.find_elements_by_xpath('li')
for li in lis:
if li.get_attribute('data-uin') is not None:
print(li.text + "---- " + li.get_attribute('data-uin'))
friend_qq.append(li.get_attribute('data-uin'))
friend_name.append(li.text)
qq_num = set(friend_qq)
friend_counts = len(qq_num)
for i in range(0,friend_counts):
print(friend_name[i]+" "+friend_qq[i]+ " index = "+ str(i))
# set_message(friend_name[i], friend_qq[i])
抓取结果:

四、留言部分
这一部分就简单多了,定位、写留言、发表
def set_message(name, qq):
# qq = 270067992
driver.get("https://user.qzone.qq.com/" + str(qq))
waiting_for_page_finish(2)
try:
"""
刚进空间,如果会跳出一个 '我知道了' 按钮,则点击一下该按钮
不点击是否可以执行后面逻辑
"""
driver.find_element_by_link_text("我知道了").click()
waiting_for_page_finish(1)
print("我知道了")
except Exception as e:
print("没有发现 --我知道了-- 弹窗")
# 查看是否有权限访问还有空间
try:
if driver.find_element_by_class_name("btn_v2"):
print("您无权访问此 " + name + " 空间......")
return
except:
print("查找 访问权限 异常...")
# 查看好友是否开通了空间
try:
if driver.find_element_by_link_text("邀请开通"):
print(name + "空间已关闭......")
return
except:
print("查找 是否开通 异常...")
# 找留言板
print("未在主页的主界面发现--留言模块--")
try:
waiting_for_page_finish(1)
"""
通过 悬停 我的主页 按钮 进入留言板主界面
"""
leave_msg_ele = driver.find_element_by_class_name('nav-list-inner')
ActionChains(driver).move_to_element(leave_msg_ele).perform()
waiting_for_page_finish(2)
driver.find_element_by_link_text('留言板').click()
print("找留言编辑框")
waiting_for_page_finish(3) # 等待页面加载
iframe = driver.find_element_by_id("tgb")
driver.switch_to.frame(iframe)
driver.switch_to.frame("veditor1_Iframe")
# 这里通过前面的方式 无法写入数据,这里使用 小path
print("写留言")
driver.find_element_by_xpath("/html/body").send_keys(name + "元旦快乐!python 自动留言脚本测试 -- 请自行删除--抱歉")
driver.switch_to.parent_frame()
if leave_msg:
driver.find_element_by_id("btnPostMsg").click()
return
except Exception as e:
print("最终没有留言....")
写留言

附言
1、代码中,我设置一个开关,因为我是测试,所以用一个开关控制了是否点击那个发表
按钮,如果想发表留言,请开启开关,开关参数为leave_msg
,设置为True
就可以了。
2、你的好友有的可能没有开通,有的可能设置里权限,输出的日志中都有说明的。如果失败,请检查网页是否更改了某些属性的值。
3、如果问题,欢迎留言要讨论。
4、完整代码请移步源码 Qzone
网友评论