用python开发一个影视网站_用python爬一个视频网站,因为一个影视有多个类别,所以在爬数据时会出现重复的影视作品...

2018-12-29 回答

主要思路

从ui获取文本信息是最为简单的方法,于是应该优先逆向ui代码部分。

逆向微信apk

首先解包微信apk,用dex2jar反编译classes.dex,然后用jd-gui查看jar源码。当然,能看到的源码都是经过高度混淆的。但是,继承自安卓重要组件(如activity、service等)的类名无法被混淆,于是还是能从中看到点东西。

首先定位到微信app package。我们知道这个是 com.tencent.mm。

在 com.tencent.mm

中,我们找到一个 ui

包,有点意思。

展开 com.tencent.mm.ui

,发现多个未被混淆的类,其中发现 mmbaseactivity直接继承自 activity

, mmfragmentactivity

继承自 actionbaractivity

, mmactivity

继承自 mmfragmentactivity

,并且 mmactivity

是微信中大多数activity的父类:

public class mmfragmentactivity

extends actionbaractivity

implements swipebacklayout.a, b.a {

...

}

public abstract class mmactivity

extends mmfragmentactivity {

...

}

public class mmbaseactivity

extends activity {

...

}

现在需要找出朋友圈的activity,为此要用xposed hook mmactivity。

创建一个xposed模块

参考 [tutorial]xposed module devlopment,创建一个xposed项目。

简单xposed模块的基本思想是:hook某个app中的某个方法,从而达到读写数据的目的。

小编尝试hook com.tencent.mm.ui.mmactivity.setcontentview这个方法,并打印出这个activity下的全部textview内容。那么首先需要遍历这个activity下的所有textview,遍历viewgroup的方法参考了so的以下代码:

private void getalltextviews(final view v) {if (v instanceof viewgroup) {

viewgroup vg = (viewgroup) v;

for (int i = 0; i < vg.getchildcount(); i++) {view child = vg.getchildat(i);

getalltextviews(child);

}

} else if (v instanceof textview ) {

dealwithtextview((textview)v); //dealwithtextview(textview tv)方法:打印textview中的显示文本}

}

hook mmactivity.setcontentview

的关键代码如下:

findandhookmethod("com.tencent.mm.ui.mmactivity", lpparam.classloader, "setcontentview", view.class, new xc_methodhook() {...

});

在findandhookmethod方法中,第一个参数为完整类名,第三个参数为需要hook的方法名,其后若干个参数分别对应该方法的各形参类型。在这里, activity.setcontentview(view view)方法只有一个类型为 view

的形参,因此传入一个 view.class

现在,期望的结果是运行时可以从log中读取到每个activity中的所有的textview的显示内容。

但是,因为view中的数据并不一定在 setcontentview()时就加载完毕,因此小编的实验结果是,log中啥都没有。

意外的收获

当切换到朋友圈页面时,xposed模块报了一个异常,异常源从 com.tencent.mm.plugin.sns.ui.snstimelineui这个类捕捉到。从类名上看,这个很有可能是朋友圈首页的ui类。展开这个类,发现更多有趣的东西:

这个类下有个子类 a

(被混淆过的类名),该子类下有个名为 gyo的 listview

类的实例。我们知道, listview

是显示列表类的ui组件,有可能就是用来展示朋友圈的列表。

顺藤摸瓜

那么,我们先要获得一个 snstimelineui.a.gyo的实例。但是在这之前,要先获得一个 com.tencent.mm.plugin.sns.ui.snstimelineui.a的实例。继续搜索,发现 com.tencent.mm.plugin.sns.ui.snstimelineui有一个名为 glz

的 snstimelineui.a

实例,那么我们先取得这个实例。

经过测试, com.tencent.mm.plugin.sns.ui.snstimelineui.a(boolean, boolean, string, boolean)这个方法在每次初始化微信界面的时候都会被调用。因此我们将hook这个方法,并从中取得 glz。

findandhookmethod("com.tencent.mm.plugin.sns.ui.snstimelineui", lpparam.classloader, "a", boolean.class, boolean.class, string.class, boolean.class, new xc_methodhook() {@override

protected void afterhookedmethod(methodhookparam param) throws throwable {xposedbridge.log("hooked. ");

object currentobject = param.thisobject;

for (field field : currentobject.getclass().getdeclaredfields()) { //遍历类成员field.setaccessible(true);

object value = field.get(currentobject);

if (field.getname().equals("glz")) {

xposedbridge.log("child a found.");

childa = value;

//这里获得了glz

...

}

}

}

});

现在取得了 snstimelineui.a

的一个实例 glz

,需要取得这个类下的 listview

类型的 gyo

属性。

private void dealwitha() throws throwable{if (childa == null) {

return;

}

for (field field : childa.getclass().getdeclaredfields()) { //遍历属性field.setaccessible(true);

object value = field.get(childa);

if (field.getname().equals("gyo")) { //取得了gyoviewgroup vg = (listview)value;

for (int i = 0; i < vg.getchildcount(); i++) { //遍历这个listview的每一个子view...

view child = vg.getchildat(i);

getalltextviews(child); //这里调用上文的getalltextviews()方法,每一个子view里的所有textview的文本...

}

}

}

}

现在已经可以将朋友圈页面中的全部文字信息打印出来了。我们需要根据textview的子类名判断这些文字是朋友圈内容、好友昵称、点赞或评论等。

private void dealwithtextview(textview v) {string classname = v.getclass().getname();string text = ((textview)v).gettext().tostring().trim().replaceall("\n", " ");if (!v.isshown())

return;

if (text.equals(""))

return;

if (classname.equals("com.tencent.mm.plugin.sns.ui.asynctextview")) {//好友昵称

...

}

else if (classname.equals("com.tencent.mm.plugin.sns.ui.snstextview")) {//朋友圈文字内容

...

}

else if (classname.equals("com.tencent.mm.plugin.sns.ui.masktextview")) {if (!text.contains(":")) {

//点赞

...

} else {

//评论

...

}

}

}

自此,我们已经从微信app里取得了朋友圈数据。当然,这部分抓取代码需要定时执行。因为从 listview中抓到的数据只有当前显示在屏幕上的可见部分,为此需要每隔很短一段时间再次执行,让用户在下滑加载的过程中抓取更多数据。

剩下的就是数据分类处理和格式化输出到文件,受本文篇幅所限不再赘述,详细实现可参考作者github上的源码。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值