背景
手机流量经常不够用,所以在某多上选择了一款流量卡,9元/30g通/30g定/300分钟,快递过来之后,要根据他们的小纸条激活,然后再通过一个他们的专属链接充值100然后送100,再给你自动开通一个流量套餐,送的100按月返还,能抵一部分套餐,激活的时候是在线选号,这是大部分流量卡的套路。
激活
激活的流程是扫码他们的二维码:
而且还提供了搜索的功能,这样选的话其实挺眼花缭乱的,一页一页的选的话,可能看两页就放弃了,选择的号码可能不是最优解,但是如果这个能抓包的话,我可以通过轮询这个接口就可以把他们所有的号全部拿下来,然后通过排序,正则的方式选择出靓号和自己喜欢的号码。
这个过程需要注意两点:
1.抓包-如果这个接口是有https的私签认证,就可能抓包过程就失败。
2.鉴权-如果接口有签名校验,那么改动任何参数就无法成功通过。
抓包
抓包使用Charles工具,这个过程很顺利,出乎我的意料,接口是通用的Https,没有签名校验
这样我不仅能拿到电话的数据,还能知道分页和整个数据的条目。
Charles有一个Compose的功能,允许你像PostMan工具一样去修改历史接口中的每个信息,然后重新运行,观察接口的返回情况。利用这个功能,我试探出了pageSize最大支持的个数是99,超过这个数字就会报错,那么3000条数据就可以通过31次的请求就可以都拿到。
我把这个接口的参数信息用Charles的Copy cURL Request 功能导出.
curl
-H 'Host: www.189.cn'
-H 'Cookie: SESSION=a376fd82-f40f-4a38-9193-992956a06a50; loginStatus=non-logined; s_fid=78A282DF37C9A607-10DF95D9036C2CAB; trkHmClickCoords=83-115-664; trkId=D9EA4392-7D63-418E-A62A-86FB3045A502; s_sq=eshipeship-189-all%3D%2526pid%253D%25252Fwap%25252FblankCard%25252FsmallWhiteV15_newDetails.html%2526pidt%253D1%2526oid%253Dfunctiononclick%252528event%252529%25257Bhistory.back%252528%252529%25253B%25257D%2526oidt%253D2%2526ot%253DIMG; s_cc=true; lvid=12fb07bdb3a869ffdb9c83c169279339; nvid=1; svid=3035BE8052727411CA9E0DB293C57C4F'
-H 'Accept: application/json, text/javascript, */*; q=0.01'
-H 'User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.3 Mobile/15E148 Safari/604.1'
-H 'Referer: https://www.189.cn/wap/blankCard/publicPages/selectNumber.html?obj=smallWhiteObj'
-H 'Accept-Language: zh-cn'
-H 'X-Requested-With: XMLHttpRequest'
--compressed 'https://www.189.cn/blankcard/product/num/list.do?pid=00000000B459193BEDBA6785E053AE1410AC86D3&pageIndex=1&pageSize=20&minpay=&maxpay=&innumber=&headnumber=&contNumber=&inflag=&islast=&lucky=0'
处理这个文本,我选择用IntelliJ IDEA 家的IDE(Android Studio、webstorm、pychram等任何一款都可以),原因是可以通过一些快捷键(块选择、多光标处理、批量替换等)功能快速处理这些参数,可以快速改造成Python需要的字典格式,比如可以用很短的时间处理成如下格式:
headers
"Host": "www.189.cn",
"Accept": "application/json, text/javascript, */*; q=0.01",
"User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.3 Mobile/15E148 Safari/604.1",
"Referer": "https://www.189.cn/wap/blankCard/publicPages/selectNumber.html?obj=smallWhiteObj",
"Accept-Language": "zh-cn",
"X-Requested-With": "XMLHttpRequest
cookies
"SESSION":"a376fd82-f40f-4a38-9193-992956a06a50",
"loginStatus":"non-logined",
"s_fid":"78A282DF37C9A607-10DF95D9036C2CAB",
"trkHmClickCoords":"83-115-664",
"trkId":"D9EA4392-7D63-418E-A62A-86FB3045A502",
"s_sq":"eshipeship-189-all%3D%2526pid%253D%25252Fwap%25252FblankCard%25252FsmallWhiteV15_newDetails.html%2526pidt%253D1%2526oid%253Dfunctiononclick%252528event%252529%25257Bhistory.back%252528%252529%25253B%25257D%2526oidt%253D2%2526ot%253DIMG",
"s_cc":"true",
"lvid":"12fb07bdb3a869ffdb9c83c169279339",
"nvid":"1",
"svid":"3035BE8052727411CA9E0DB293C57C4F",
params
"pid":"00000000B459193BEDBA6785E053AE1410AC86D3"
"pageIndex":"1"
"pageSize":"20"
"minpay":""
"maxpay":""
"innumber":""
"headnumber":""
"contNumber":""
"inflag":""
"islast":""
"lucky":"0"
剩下的就是用Python 的requests去完成爬虫的功能
爬虫
把上面的信息复制到Python脚本中,写一个模拟接口,看下接口的状态:
response = requests.get('https://www.189.cn/blankcard/product/num/list.do', headers=headers, params=params, cookies=cookies)
print(response.content.decode("utf-8"))
不幸的是,接口报用户未登录异常,但是这个接口是不需要登录,然后我用Charesle 的repeat功能试了,结果也是用户未登录
然后我重新上一步抓包的过程,最后发现还是报这个问题,我怀疑应该是这个会话是有个过期的时间,如果我手动的去拼接这个参数,可能在完成的时候就已经过期了,那么有没有能把cURL的信息快速转换成Python代码呢?
代码
现阶段我认为我能遇到的问题,别人都遇到过了。
一、node js 插件curlconverter
https://www.npmjs.com/package/curlconverter
二、Python第三方库convertcurl
https://www.cnpython.com/pypi/convertcurl
我选了第一种方案:
1、安装curlconverter
npm install --save curlconverter
2、使用JS脚本转换
var curlc = require('curlconverter');
console.log(curlc.toPython('curl -H "User-Agent: Dalvik/2.1.0 (Linux; U; Android 7.0; EVA-AL00 Build/HUAWEIEVA-AL00)" -H "Host: www.google.com" --compressed http://www.google.com/'))
执行js脚本就会帮你快速生成Python脚本:
然后把代码复制到Python脚本中,后面拼接自己的逻辑代码:
……
headers、params、cookies的信息
……
# 生成的是元组,需要转换成字典后面动态改参数的大小
params = dict(params)
# 存放手机号
phoneNum = []
for index in range(1, 30):
print("循环次数:%d" % index)
params["pageSize"] = '99'
params["pageIndex"] = index
response = requests.get('https://www.189.cn/blankcard/product/num/list.do', headers=headers, params=params,
cookies=cookies)
loads = json.loads(response.content.decode("utf-8"))
items = loads.get('dataObject').get("items")
try:
if items:
for item in items:
phone = item.get('phoneNumber')
phoneNum.append(phone)
except OSError:
print(phoneNum)
print(phoneNum)
# 保存成csv,可视化处理
numpy.savetxt("phone.csv", phoneNum, fmt="%s", header="phoneNumber")
筛选
拿到数据准备进行处理:
一、CSV可视化排序
可以按照符合的趋势,选择出自己想要的数据,缺点就是数据太多,容易疲劳。
二、正则。
靓号正则
1.尾号AABB:
^[0-9]{7}(\d)\1((?!\1)\d)\2$
2.尾号AAA:
^[0-9]{8}(\d)\1{2}$
3.尾号AAAB:
^[0-9]{7}(\d)\1{2}((?!\1)\d)$
4.尾号ABAB:
^[0-9]{7}(\d)((?!\1)\d)\1\2$
5.尾号AABA:
^[0-9]{7}(\d)\1((?!\1)\d)\1$
6.尾号ABAA:
^[0-9]{7}(\d)((?!\1)\d)\1{2}$
7.尾号ABBA:
^[0-9]{7}(\d)((?!\1)\d)\2\1$
8.尾号ABCC:
^[0-9]{7}(\d)((?!\1)\d)((?!\1|\2)\d)\3$
拿到数据之后,大体看了一眼,每个号码至少都含有一个数字4。第1、2、3、就不用想了肯定没有,8不想要,所以便宜的不是流量,是号码啊。。
结果
既然都是垃圾,那就在垃圾中找精品。
ABAB
18953587474AABA
18954704454ABAA
18954574644
18954584244
18954704544
18954724744
18954734644ABBA
18953584774
18953592442
18954724334
18954734774
要你你会选择哪个呢?