美文网首页
爬取手机号码归属地

爬取手机号码归属地

作者: 飞行员suke | 来源:发表于2017-05-03 17:08 被阅读0次

    去年年底,公司需要建个本地的手机号码归属地库,因为有点时间,又爱好python,就主动说来搞定这个。活接下来了,那么怎么实施呢?分为四步:

    1. 所有手机号码的获取
    2. 归属地的查询来源
    3. 请求数据的组装,返回数据的解析
    4. 有用数据的落地

    一:号码的获取

    国内手机号码十亿级别的,茫茫多的号码,一个一个获取肯定是不现实的,想想数据表得多大?
    那怎么办呢?通过百度百科确认,要查归属地,只要根据前七位就ok了。那么数据只要 ‘151 5220 XXXX’这样就可以了,这样数据量可以压缩一万倍!然后搜索到目前国内三大运营商下面的手机号段分别有:

    电信:
    133、153、180、181、189、177、173、149
    联通:
    130、131、132、155、156、145、185、186、176、175
    移动:
    1340-1348、135、136、137、138、139、150、151、152、157、158、159、182、183、184、187、188、147、178

    共37个号码段。所以我们只要37万条数据就ok了,而不是37亿条!

    二:归属地的查询来源

    国内靠谱点的手机号码归属地查询网站是?
    国内主要的有ip138,114百事通,手机在线等,有些是收费的,有些返回整个html,综合下来:
    适合我的是手机在线v.shouji.com,可免费且返回数据量很小!

    三:请求数据的组装,返回数据的解析

    然后在该网站上输入手机号码查询归属地,并开启charles抓包。


    手机在线查询结果.png Request.png Response.png

    通过抓包分析,请求为:

    http://v.showji.com/Locating/showji.com2016234999234.aspx?m=13900008888&output=json&callback=querycallback&timestamp=1493796438586
    

    其中m为手机号码,output为数据格式json,callback为返回动作,timestamp为时间戳,so只要替换其中的m,就能获取新的手机归属地了!

    通过抓包分析,响应为:

    querycallback({
    "Mobile": "13900008888",
    "QueryResult": "True",
    "TO": "中国移动",
    "Corp": "中国移动",
    "Province": "新疆",
    "City": "乌鲁木齐",
    "AreaCode": "0991",
    "PostCode": "830000",
    "VNO": "",
    "Card": ""
    });
    

    在querycallback()里面是一个json格式的数据包。对应有手机号、运营商、省份、城市等有用信息,Nice啊!这就是我需要的。

    四:有用数据的落地

    重点是落地,落到哪里去,最好的最便捷的还是使用python直接支持的sqlite3啦,轻量快捷!

    五:代码实现

    #coding:utf-8
    import sys
    import urllib2
    import sqlite3
    import json
    import time
    import re
    
    
    class SQLITETool:
        def __init__(self,databaseName):
            self.databaseName = databaseName
            self.create_db()
    
        def create_db(self):
            conn = sqlite3.connect(self.databaseName)
            conn.close();
            
        def execute_table(self,sql):
            conn = sqlite3.connect(self.databaseName);
            cursor = conn.cursor();
            try:
                cursor.execute(sql)
            except Exception, e:
                print(Exception,":",e)
            finally:
                cursor.close()
                conn.commit()
                conn.close()
    
    
    class PhoneInfoSpider:
        def __init__(self,databaseName,phoneSections):
            self.phoneSections = phoneSections
            self.sqlTool = SQLITETool(databaseName)
    
        def phoneInfoHandler(self,jsonData):
                mobile = jsonData['Mobile'];
                corp = jsonData['Corp'];
                province = jsonData['Province'];
                city = jsonData['City'];
                try:
                    sql = 'insert into phone_info_table (mobile, corp, province, city) values(\'{0}\',\'{1}\',\'{2}\',\'{3}\')'.format(mobile,corp,province,city);
                    self.sqlTool.execute_table(sql)
                except Exception,e:
                    print(Exception,":",e)
    
        def requestPhoneInfo(self,phoneNum):
            print(phoneNum);
            try:
                #因为有20次/min的ip限制,所以sleep  3s
                time.sleep(3);
                response = urllib2.urlopen('http://v.showji.com/Locating/showji.com2016234999234.aspx?m={0}&output=json&callback=querycallback&timestamp=1484546664567'.format(phoneNum))
                resStr = response.read()
                jsonStr = re.search(r'querycallback\((.*?)\);',resStr,re.S).group(1)
                jsonData = json.loads(jsonStr)
                self.phoneInfoHandler(jsonData)
            except Exception,e:
                print(Exception,":",e)
    
        def requestAllSections(self):
            #last用于接上次异常退出前的号码
            last = 0
            #自动生成手机号码,后四位补0
            for head in self.phoneSections:
                for i in range(last,10000):
                    middle = str(i).zfill(4)
                    phoneNum = head+middle+"0000"
                    self.requestPhoneInfo(phoneNum)
                last = 0
    
    
    
    if __name__ == '__main__':
        reload(sys);
        sys.setdefaultencoding('utf-8');
    
        #134,135 '136','137','138','139','150','151','152',133','153','180','181','189','177',173','149','182','183','184','178'
        #'157','158','159','187','188','147',   '130','131','132','155','156','185','186','145','176'
        #要爬的号码段
        yys = ['153','180','181','189','177','173','149','182','183','184','178'];
        spider = PhoneInfoSpider('phoneInfo.db',yys)
        sql = 'CREATE TABLE phone_info_table (mobile varchar(11) primary key,corp varchar(32),province varchar(16), city varchar(32));'
        spider.sqlTool.execute_table(sql)
        spider.requestAllSections()
    

    相关文章

      网友评论

          本文标题:爬取手机号码归属地

          本文链接:https://www.haomeiwen.com/subject/bqnktxtx.html