开开心心爬APP,结果一坑连一坑
三筒 凹凸数据
本文来自「凹凸数据」读者投稿,欢迎大家分享更多优质内容!奖励多多~
大家好,我是新人三筒。
作为凹凸的铁粉,我会经常在历史消息里挖坟寻找我需要的教程。最近因为业务需求,而要爬的数据又刚好没有对应的网页版,使我对手机爬虫教程格外感兴趣,一顿操作之后我发现,在这个过程中我遇到了一些回避不了的坑,需要跟大家分享一下。前文回顾
回顾一下这篇文章用Fiddler篇爬取APP的教程:抓包手机大致分为以下几步(具体的大家可以回顾对不起,我把APP也给爬了):
- 安装软件,设置软件。同时在电脑上安装证书
- 用手机连上和电脑相同的WIFI后,手机端设置代理。
- 手机端安装证书,信任证书。
- 打开抓包软件,刷新手机数据,观察并查找对应url。一般来说,照这几个步骤是能够很顺利的取到数据。但是总有人脸黑,比如我。无论是用Fiddler还是Charles,都只能打开浏览器和高德地图。而打开知乎,小红书,好好住等APP却一律被拒绝访问。(oppo和小米手机都尝试过。)
尽管并非所有人都会踩到这个坑,但是这种进行到90%却突然卡住的感觉真的非常膈应人,查了好几篇博客,比较靠谱的说法是:Android7以后,APP一般不信任用户自己安装的凭据,也就是我们在手机上安装的抓包软件证书。解决方法有两个:- 方法一,用Xposed拦截对证书的验证。
- 方法二、把Fiddler/Charles的证书放进系统的证书目录里。第一种方法仍然有坑,手机能检测到xposed拦截终还是会失败(这里我没有验证过,有兴趣的同学可以试试)。所以我选择planB,这里写下我的过程,作为一份补充参考给大家。
Charles的配置与步骤
在正餐开始之前,我简单说下Charles的配置(和Fiddler一个逻辑。只是界面稍有不同,选择用Fiddler的同学可以跳过这里直接看后面)
Charles的配置
1、软件安装基本上就是一路Next,装好以后进入主界面,进行如下设置:
- 一台root过的安卓机(最好是备用机,我用的是小米)
- Charles或者Fiddler的证书文件(Charles是crt文件,Fiddler是cer文件,后面获取hash值的时候会有差别)
- Windows系统需要下载安装openSSL工具(官网:https://www.openssl.org/,安装完后记得把openssl下的bin文件夹目录加入到环境变量中去)好了,开始我们的操作!step1手机端下载证书后先别着急安装,导到电脑上,复制下它的路径(比如我的是"D:\证书\charles\getssl.crt")step2按Win+R,输入cmd,进入命令窗口,输入:
opensslx509-subject_hash_old-in"D:\证书\charles\getssl.crt"
记得in后面修改为自己的证书路径。执行后我们得到以下内容:
Fiddler的配置与源码
上面都是在说Charles,我们再讲讲Fiddler。
Fiddler的配置
其实Fiddler也是同理,需要我们获取到证书的Hash值,修改证书名后放进系统证书目录。只是因为Fiddler的证书是cer格式,我们需要多一个步骤:先把证书转成crt格式的。
同样是Win+R后输入cmd进入命令窗口。cd到你放置证书的目录,然后输入转换格式的命令。如下(记得你的文件在哪个盘就输入哪个盘,在哪个目录就输入哪个目录):
d:
cd Zhengshu
openssl x509 -inform DER -in FiddlerRoot.cer -out
FiddlerRoot1.crt
此目录下就会生成一个crt格式的证书,然后我们继续用上面的方法读取它的hash值。输入:
opensslx509-subject_hash_old-in FiddlerRoot.crt
得到我们想要的Hash值
爬虫源码
完整的代码如下。
代码稍微有点丑陋大家不爬这个APP的话可以不用看。
#导入相关模块
import requests
import time
import random
#复制请求头,cookies等参数
headers={
'user-agent':'Dalvik/2.1.0 (Linux; U; Android 8.0.0; MI 5 MIUI/8.11.22)hhz4.7.0-did44c043bb9672a88b4eafdfb3ce276c2c-h16946635abc3f22102c7e10-uid597199-ovid_1000000000597199-proxy-emu0',
'accept-encoding':'gzip',
'content-type': 'application/x-www-form-urlencoded',
}
cookies={
'visitor_token':'ovid_1000000000597199',
'hhz_token':'8ebae5a0dd1c47223a76243ce32f1347',
'Token':'8ebae5a0dd1c47223a76243ce32f1347'
}
url='https://yapi.haohaozhu.cn/topic/GetAnswerList460'
remark_list=[]
for i in range(1,28):
#这个参数虽然又规律但是今天我看的时候已经发生变化了,大家如果要爬的话需要重新观察下。
params='topic_id=365&sort_type=1¤t_time=1589453251&page={}&basic_info=%7B%22%24app_version%22%3A%224.7.0%22%2C%22%24carrier%22%3A%22%E5%85%B6%E4%BB%96%22%2C%22%24lib%22%3A%22Android%22%2C%22%24lib_version%22%3A%221.6.19%22%2C%22%24manufacturer%22%3A%22Xiaomi%22%2C%22%24os%22%3A%22Android%22%2C%22%24os_version%22%3A%228.0.0%22%2C%22%24screen_height%22%3A1920%2C%22%24screen_width%22%3A1080%2C%22distinct_id%22%3A%2244c043bb9672a88b4eafdfb3ce276c2c%22%7D'.format(i)
#注意请求方式是POST
res=requests.post(url,headers=headers,cookies=cookies,params=params)
json_obj=res.json()
data=json_obj['data']
list=data['list']
for content in list:
#把评论文本提取出来
comment_box=content['photo']['photo_info']
comment=comment_box['remark']
remark_list.append(comment)
#加入停顿防止被反爬
time.sleep(random.random())
脸黑的朋友们可以考虑下试试我的方法,也许能够解决困扰了你很久的问题。
精彩评论