上节说到抓包重发的方法已经行不通了,
所以我们选择另辟蹊径。
这里我选择了使用selenium来进行后续操作。
0. 简单定位与初步分析。
了解selenium或者看了番外的同学,
在脑海中应该已经有了大体思路,
没错,我们就是通过selenium模拟发信息的。
下面我们一起来实现一下这一程序。
>>> from selenium import webdriver
>>> browser = webdriver.Firefox()
先打开我们的浏览器。
然后我们尝试用get方法打开web微信的页面。>>> browser.get("https://wx.qq.com")
但是你发现一个问题,页面打开完成,而selenium却迟迟没有返回信息。
那我们先不管,扫码登陆。
OK,我们看看selenium到底获取到什么没有。
又经过了特特特特别长的时间终于返回了页面信息。
谁会等那么长时间啊喂,selenium什么效率。
很遗憾,我并不清楚其中到底发生了什么导致selenium变得
那!么!慢!
推测可能是微信建立的一个长连接,使得selenium一直等待。
好吧,虽然我不知道原理,但是发现了解决办法。
OK,我们的准备工作已经完成。
下面继续深入。
1. 整理之后的思路。
根据正常的聊天流程,我们应该是
但是微信联系人列表里并不提供群。
在上面选项的发起聊天处我们发现了发起群聊的信息。
我们目标很明确了,
2. 步步为营。
首先我们来获取那个选项卡。
<a class="opt" href="javascript:;" ng-show="account.HeadImgUrl" ng-click="toggleSystemMenu()"><i class="web_wechat_add"></i></a>
他有一个class名为opt,
我们先用审查元素搜了一下发现有8个class带有opt的元素,
但是只有一个元素为a。
使用css_selector方法。>>> browser.find_element_by_css_selector('a[class="opt"]')
<selenium.webdriver.remote.webelement.WebElement (session="c7f1c0f9-c0c8-448a-9d34-33c603cbf0aa", element="{3d39be4a-33b5-4865-8c0e-2b3ecbc87f14}")>
OK,成功获取。
封装这个部分。
def get_address(browser):
# 获取选项按钮。
opt = browser.find_element_by_css_selector('a[class="opt"]')
return opt
我们再来获取"发起聊天"这个部分。
同样审查元素。
title作为唯一标识还是可以的。
再次用css_selector。>>> browser.find_element_by_css_selector('a[title="发起聊天"]')
<selenium.webdriver.remote.webelement.WebElement (session="c7f1c0f9-c0c8-448a-9d34-33c603cbf0aa", element="{eabe9965-a219-41ad-943d-554020e86bbf}")>
OK,获取出了。
---
有的小伙伴这里可能报错了,
那是因为你需要先点击我们第一步获取的opt才能进行下一步,
可以手动点击浏览器,也可以用click方法。
我们封装这个部分。def get_peoples(browser):
# 选择发起聊天。
peoples = browser.find_element_by_css_selector('a[title="发起聊天"]')
return peoples
这里发现有两个一样的li,<li class="nav_tab selected" ng-class="{'selected':$parent.index==0}" ng-click="$parent.index=0">选择联系人</li>
<li class="nav_tab" ng-class="{'selected':$parent.index==1}" ng-click="$parent.index=1">选择群聊</li>
经过测试发现每次打开都会默认到选择联系人上,选择中的li的class会变成selected,所以我们直接通过class就可以获取到了。
>>> browser.find_element_by_css_selector('li[class="nav_tab"]')
<selenium.webdriver.remote.webelement.WebElement (session="c7f1c0f9-c0c8-448a-9d34-33c603cbf0aa", element="{4f70a68a-d35a-43cc-93b8-7ee81f4001db}")>
我们再次封装。def get_talks(browser):
# 选择群聊。
talks = browser.find_element_by_css_selector('li[class="nav_tab"]')
return talks
我们先定位一下群的特征。<h4 class="nickname ng-binding" ng-bind-html="user.getDisplayName()">马赛克</h4>
<h4 class="nickname ng-binding" ng-bind-html="user.getDisplayName()">马赛克2</h4>
我这里只有很少一部分联系人,
所以搜了一下有15个,
而且个个都是h4标签,
我只有这两个群。
总不能全获取了在过滤吧,那样效率又会拉低很多。
好在selenium提供了方法。
我们点击"选择群聊"后会出现一个承载它的div,这个div是<div style="position: relative;" class="scroll-wrapper rooms J_ContactScrollBody scrollbar-dynamic contact_list ng-isolate-scope">
比较长的class,搜一下是唯一的。
我们先获取出这个div,然后从这个div里获取a标签。
>>> temp = browser.find_element_by_css_selector('div[class="scroll-wrapper rooms J_ContactScrollBody scrollbar-dynamic contact_list ng-isolate-scope"]')
>>> temp.find_elements_by_css_selector('h4[class="nickname ng-binding"]')
[<selenium.webdriver.remote.webelement.WebElement (session="c7f1c0f9-c0c8-448a-9d34-33c603cbf0aa", element="{cf46846d-86ff-4cf8-bdcb-48372bd6056d}")>, <selenium.webdriver.remote.webelement.WebElement (session="c7f1c0f9-c0c8-448a-9d34-33c603cbf0aa", element="{4617ba44-54d1-4b62-9855-33b56fadf47a}")>]
OK,成功获取到了这两个货。
封装封装。def get_all_talks(browser):
# 获取全部群。
all_talks = browser.find_element_by_css_selector(
'div[class="scroll-wrapper rooms J_ContactScrollBody scrollbar-dynamic contact_list ng-isolate-scope"]')\
.find_elements_by_css_selector('h4[class="nickname ng-binding"]')
return all_talks
定位编辑内容的框。<pre id="editArea" contenteditable-directive="" mm-paste="" class="flex edit_area ng-isolate-scope ng-pristine ng-valid" ng-blur="editAreaBlur($event)" ng-model="editAreaCtn" ng-click="editAreaClick($event)" ng-keyup="editAreaKeyup($event)" ng-keydown="editAreaKeydown($event)" contenteditable="true"></pre>
OK,有id,简单省事。>>> browser.find_element_by_id('editArea')
<selenium.webdriver.remote.webelement.WebElement (session="c7f1c0f9-c0c8-448a-9d34-33c603cbf0aa", element="{ddc6347a-2ef9-4d25-bd09-639924e1d609}")>
好吧,和send一起封装。>>> browser.find_element_by_id('editArea').send_keys("test")
如果你的框里没有出现test说明失败了,重新来过。
发送按钮审查元素。<a class="btn btn_send" href="javascript:;" ng-click="sendTextMessage()">发送</a>
只有一个a标签的class为这个。>>> browser.find_element_by_css_selector('a[class="btn btn_send"]').click()
不知道你的信息发没发出去呢。
最后的封装?def edit_messages(browser):
# 定位到编辑区。
edit_messages = browser.find_element_by_id('editArea')
return edit_messages
def send_messages(browser):
# 发送编辑好的消息。
send_message = browser.find_element_by_css_selector('a[class="btn btn_send"]')
send_message.click()
最后一个打包代码。