鱼C论坛

 找回密码
 立即注册
查看: 3180|回复: 5

[技术交流] Do interesting things with Python —— 微信自动喊话【2】

[复制链接]
发表于 2016-7-15 11:51:17 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
f430c525ee30bb18bb59c66194233aec27c9a7ec1d00d-JM6CyV_fw658.png


上节说到抓包重发的方法已经行不通了,
所以我们选择另辟蹊径。

这里我选择了使用selenium来进行后续操作。

0.  简单定位与初步分析。

了解selenium或者看了番外的同学,
在脑海中应该已经有了大体思路,
没错,我们就是通过selenium模拟发信息的。

下面我们一起来实现一下这一程序。

>>> from selenium import webdriver
>>> browser = webdriver.Firefox()


先打开我们的浏览器。

然后我们尝试用get方法打开web微信的页面。
>>> browser.get("https://wx.qq.com")

但是你发现一个问题,页面打开完成,而selenium却迟迟没有返回信息。

那我们先不管,扫码登陆。

OK,我们看看selenium到底获取到什么没有。
>>> browser.page_source


又经过了特特特特别长的时间终于返回了页面信息。
360截图20160715105758756.jpg

谁会等那么长时间啊喂,selenium什么效率。

很遗憾,我并不清楚其中到底发生了什么导致selenium变得
那!么!慢!

推测可能是微信建立的一个长连接,使得selenium一直等待。

好吧,虽然我不知道原理,但是发现了解决办法。

游客,如果您要查看本帖隐藏内容请回复


OK,我们的准备工作已经完成。

下面继续深入。

1. 整理之后的思路。

360截图20160715111601546.jpg

根据正常的聊天流程,我们应该是
点击通讯录 (1).png

但是微信联系人列表里并不提供群。

在上面选项的发起聊天处我们发现了发起群聊的信息。

360截图20160715113355364.jpg

我们目标很明确了,

点击选项按钮.png


2. 步步为营。
360截图20160715120823804.jpg
首先我们来获取那个选项卡。
<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


我们再来获取"发起聊天"这个部分。
同样审查元素。
360截图20160715114153796.jpg
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



360截图20160715120932444.jpg
这里发现有两个一样的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

360截图20160715121222572.jpg
定位编辑内容的框。
<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说明失败了,重新来过。
360截图20160715120112308.jpg

发送按钮审查元素。
<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()

不知道你的信息发没发出去呢。
360截图20160715120346428.jpg

最后的封装?
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()




最后一个打包代码。

游客,如果您要查看本帖隐藏内容请回复

本帖被以下淘专辑推荐:

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2016-7-15 14:47:29 | 显示全部楼层
哇塞 好厉害的样子啊
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-7-15 15:15:25 | 显示全部楼层
想要的答案!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-9-26 09:31:45 | 显示全部楼层
学习了,多谢分享
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-9-28 22:07:19 | 显示全部楼层
用edge发出去啦
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-1-2 22:31:28 | 显示全部楼层
好厉害
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-11-22 13:43

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表