import socket
import struct
import csv

class CzIp:
    def __init__(self, db_file='qqwry_lastest.dat', csv_file = '场所客户端IP.csv'):
        self.f_db = open(db_file, "rb")
        self.csv_file = csv_file
        bs = self.f_db.read(8)
        (self.first_index, self.last_index) = struct.unpack('II', bs)
        self.index_count = int((self.last_index - self.first_index) / 7 + 1)
        self.cur_start_ip = None
        self.cur_end_ip_offset = None
        self.cur_end_ip = None
        print(self.get_version(), " 纪录总数: %d 条 "%(self.index_count))

    def get_version(self):
        '''
        获取版本信息，最后一条IP记录 255.255.255.0-255.255.255.255 是版本信息
        :return: str
        '''
        s = self.get_addr_by_ip(0xffffff00)
        # print(s)
        return s

    def _get_area_addr(self, offset=0):
        if offset:
            self.f_db.seek(offset)
        bs = self.f_db.read(1)
        (byte,) = struct.unpack('B', bs)
        if byte == 0x01 or byte == 0x02:
            p = self.getLong3()
            if p:
                return self.get_offset_string(p)
            else:
                return ""
        else:
            self.f_db.seek(-1, 1)
            return self.get_offset_string(offset)

    def _get_addr(self, offset):
        '''
        获取offset处记录区地址信息(包含国家和地区)
        如果是中国ip，则是 "xx省xx市 xxxxx地区" 这样的形式
        (比如:"福建省 电信", "澳大利亚 墨尔本Goldenit有限公司")
        :param offset:
        :return:str
        '''
        self.f_db.seek(offset + 4)
        bs = self.f_db.read(1)
        (byte,) = struct.unpack('B', bs)
        if byte == 0x01:    # 重定向模式1
            country_offset = self.getLong3()
            self.f_db.seek(country_offset)
            bs = self.f_db.read(1)
            (b,) = struct.unpack('B', bs)
            if b == 0x02:
                country_addr = self.get_offset_string(self.getLong3())
                self.f_db.seek(country_offset + 4)
            else:
                country_addr = self.get_offset_string(country_offset)
            area_addr = self._get_area_addr()
        elif byte == 0x02:  # 重定向模式2
            country_addr = self.get_offset_string(self.getLong3())
            area_addr = self._get_area_addr(offset + 8)
        else:   # 字符串模式
            country_addr = self.get_offset_string(offset + 4)
            area_addr = self._get_area_addr()
        return country_addr + " " + area_addr

    def dump(self, first, last):
        '''
        打印数据库中索引为first到索引为last(不包含last)的记录
        :param first:
        :param last:
        :return:
        '''
        if last > self.index_count:
            last = self.index_count
        for index in range(first, last):
            offset = self.first_index + index * 7
            self.f_db.seek(offset)
            buf = self.f_db.read(7)
            (ip, of1, of2) = struct.unpack("IHB", buf)
            address = self._get_addr(of1 + (of2 << 16))
            print("%d %s %s" % (index, self.ip2str(ip), address))

    def _set_ip_range(self, index):
        offset = self.first_index + index * 7
        self.f_db.seek(offset)
        buf = self.f_db.read(7)
        (self.cur_start_ip, of1, of2) = struct.unpack("IHB", buf)
        self.cur_end_ip_offset = of1 + (of2 << 16)
        self.f_db.seek(self.cur_end_ip_offset)
        buf = self.f_db.read(4)
        (self.cur_end_ip,) = struct.unpack("I", buf)

    def get_addr_by_ip(self, ip):
        '''
        通过ip查找其地址
        :param ip: (int or str)
        :return: str
        '''
        if type(ip) == str:
            ip = self.str2ip(ip)
        L = 0
        R = self.index_count - 1
        while L < R - 1:
            M = int((L + R) / 2)
            self._set_ip_range(M)
            if ip == self.cur_start_ip:
                L = M
                break
            if ip > self.cur_start_ip:
                L = M
            else:
                R = M
        self._set_ip_range(L)
        # version information, 255.255.255.X, urgy but useful
        if ip & 0xffffff00 == 0xffffff00:
            self._set_ip_range(R)
        if self.cur_start_ip <= ip <= self.cur_end_ip:
            address = self._get_addr(self.cur_end_ip_offset)
        else:
            address = "未找到该IP的地址"
        # print("address:"+address)
        return address

    def get_ip_range(self, ip):
        '''
        返回ip所在记录的IP段
        :param ip: ip(str or int)
        :return: str
        '''
        if type(ip) == str:
            ip = self.str2ip(ip)
        self.get_addr_by_ip(ip)
        range = self.ip2str(self.cur_start_ip) + ' - ' \
                + self.ip2str(self.cur_end_ip)
        return range

    def get_offset_string(self, offset=0):
        '''
        获取文件偏移处的字符串(以'\0'结尾)
        :param offset: 偏移
        :return: str
        '''
        if offset:
            self.f_db.seek(offset)
        bs = b''
        ch = self.f_db.read(1)
        (byte,) = struct.unpack('B', ch)
        while byte != 0:
            bs += ch
            ch = self.f_db.read(1)
            (byte,) = struct.unpack('B', ch)
        return bs.decode('gbk')

    def ip2str(self, ip):
        '''
        整数IP转化为IP字符串
        :param ip:
        :return:
        '''
        return str(ip >> 24) + '.' + str((ip >> 16) & 0xff) + '.' + str((ip >> 8) & 0xff) + '.' + str(ip & 0xff)

    def str2ip(self, s):
        '''
        IP字符串转换为整数IP
        :param s:
        :return:
        '''
        (ip,) = struct.unpack('I', socket.inet_aton(s))
        return ((ip >> 24) & 0xff) | ((ip & 0xff) << 24) | ((ip >> 8) & 0xff00) | ((ip & 0xff00) << 8)

    def getLong3(self, offset=0):
        '''
        3字节的数值
        :param offset:
        :return:
        '''
        if offset:
            self.f_db.seek(offset)
        bs = self.f_db.read(3)
        (a, b) = struct.unpack('HB', bs)
        return (b << 16) + a
    def get_csv_data(self):
        csv_files = csv.reader(open(self.csv_file, 'r'))
        # print(csv_files)  # 可以先输出看一下该文件是什么样的类型

        content = []  # 用来存储整个文件的数据，存成一个列表，列表的每一个元素又是一个列表，表示的是文件的某一行

        for line in csv_files:
            # print(line) #打印文件每一行的信息
            content.append(line)
        # print("该文件中保存的数据为:\n", content[1:])

        return content[1:]

if __name__ == '__main__':
    cz = CzIp()
    ips = cz.get_csv_data()
    csvFile = open("场所客户端.csv", "w" ,newline='')  # 创建csv文件
    writer = csv.writer(csvFile)  # 创建写的对象
    writer.writerow(["site_ap_ip", " ", "address", " ", "运营商"])  # 写入列的名称
    for ip in ips:
        # print(ip[0])
        address = cz.get_addr_by_ip(ip[0])
        # print(address)
        add = address.split()
        writer.writerow([ip[0], ' ', add[0], ' ', add[1]])
e7427134a4d27604b05ead33a4c329d0b51a9e47
<mask token>


class CzIp:

    def __init__(self, db_file='qqwry_lastest.dat', csv_file='场所客户端IP.csv'):
        self.f_db = open(db_file, 'rb')
        self.csv_file = csv_file
        bs = self.f_db.read(8)
        self.first_index, self.last_index = struct.unpack('II', bs)
        self.index_count = int((self.last_index - self.first_index) / 7 + 1)
        self.cur_start_ip = None
        self.cur_end_ip_offset = None
        self.cur_end_ip = None
        print(self.get_version(), ' 纪录总数: %d 条 ' % self.index_count)

    def get_version(self):
        """
        获取版本信息，最后一条IP记录 255.255.255.0-255.255.255.255 是版本信息
        :return: str
        """
        s = self.get_addr_by_ip(4294967040)
        return s
    <mask token>
    <mask token>
    <mask token>
    <mask token>

    def get_addr_by_ip(self, ip):
        """
        通过ip查找其地址
        :param ip: (int or str)
        :return: str
        """
        if type(ip) == str:
            ip = self.str2ip(ip)
        L = 0
        R = self.index_count - 1
        while L < R - 1:
            M = int((L + R) / 2)
            self._set_ip_range(M)
            if ip == self.cur_start_ip:
                L = M
                break
            if ip > self.cur_start_ip:
                L = M
            else:
                R = M
        self._set_ip_range(L)
        if ip & 4294967040 == 4294967040:
            self._set_ip_range(R)
        if self.cur_start_ip <= ip <= self.cur_end_ip:
            address = self._get_addr(self.cur_end_ip_offset)
        else:
            address = '未找到该IP的地址'
        return address
    <mask token>

    def get_offset_string(self, offset=0):
        "\n        获取文件偏移处的字符串(以'\x00'结尾)\n        :param offset: 偏移\n        :return: str\n        "
        if offset:
            self.f_db.seek(offset)
        bs = b''
        ch = self.f_db.read(1)
        byte, = struct.unpack('B', ch)
        while byte != 0:
            bs += ch
            ch = self.f_db.read(1)
            byte, = struct.unpack('B', ch)
        return bs.decode('gbk')

    def ip2str(self, ip):
        """
        整数IP转化为IP字符串
        :param ip:
        :return:
        """
        return str(ip >> 24) + '.' + str(ip >> 16 & 255) + '.' + str(ip >> 
            8 & 255) + '.' + str(ip & 255)

    def str2ip(self, s):
        """
        IP字符串转换为整数IP
        :param s:
        :return:
        """
        ip, = struct.unpack('I', socket.inet_aton(s))
        return ip >> 24 & 255 | (ip & 255) << 24 | ip >> 8 & 65280 | (ip & 
            65280) << 8

    def getLong3(self, offset=0):
        """
        3字节的数值
        :param offset:
        :return:
        """
        if offset:
            self.f_db.seek(offset)
        bs = self.f_db.read(3)
        a, b = struct.unpack('HB', bs)
        return (b << 16) + a
    <mask token>


<mask token>

<mask token>


class CzIp:

    def __init__(self, db_file='qqwry_lastest.dat', csv_file='场所客户端IP.csv'):
        self.f_db = open(db_file, 'rb')
        self.csv_file = csv_file
        bs = self.f_db.read(8)
        self.first_index, self.last_index = struct.unpack('II', bs)
        self.index_count = int((self.last_index - self.first_index) / 7 + 1)
        self.cur_start_ip = None
        self.cur_end_ip_offset = None
        self.cur_end_ip = None
        print(self.get_version(), ' 纪录总数: %d 条 ' % self.index_count)

    def get_version(self):
        """
        获取版本信息，最后一条IP记录 255.255.255.0-255.255.255.255 是版本信息
        :return: str
        """
        s = self.get_addr_by_ip(4294967040)
        return s
    <mask token>

    def _get_addr(self, offset):
        """
        获取offset处记录区地址信息(包含国家和地区)
        如果是中国ip，则是 "xx省xx市 xxxxx地区" 这样的形式
        (比如:"福建省 电信", "澳大利亚 墨尔本Goldenit有限公司")
        :param offset:
        :return:str
        """
        self.f_db.seek(offset + 4)
        bs = self.f_db.read(1)
        byte, = struct.unpack('B', bs)
        if byte == 1:
            country_offset = self.getLong3()
            self.f_db.seek(country_offset)
            bs = self.f_db.read(1)
            b, = struct.unpack('B', bs)
            if b == 2:
                country_addr = self.get_offset_string(self.getLong3())
                self.f_db.seek(country_offset + 4)
            else:
                country_addr = self.get_offset_string(country_offset)
            area_addr = self._get_area_addr()
        elif byte == 2:
            country_addr = self.get_offset_string(self.getLong3())
            area_addr = self._get_area_addr(offset + 8)
        else:
            country_addr = self.get_offset_string(offset + 4)
            area_addr = self._get_area_addr()
        return country_addr + ' ' + area_addr
    <mask token>
    <mask token>

    def get_addr_by_ip(self, ip):
        """
        通过ip查找其地址
        :param ip: (int or str)
        :return: str
        """
        if type(ip) == str:
            ip = self.str2ip(ip)
        L = 0
        R = self.index_count - 1
        while L < R - 1:
            M = int((L + R) / 2)
            self._set_ip_range(M)
            if ip == self.cur_start_ip:
                L = M
                break
            if ip > self.cur_start_ip:
                L = M
            else:
                R = M
        self._set_ip_range(L)
        if ip & 4294967040 == 4294967040:
            self._set_ip_range(R)
        if self.cur_start_ip <= ip <= self.cur_end_ip:
            address = self._get_addr(self.cur_end_ip_offset)
        else:
            address = '未找到该IP的地址'
        return address

    def get_ip_range(self, ip):
        """
        返回ip所在记录的IP段
        :param ip: ip(str or int)
        :return: str
        """
        if type(ip) == str:
            ip = self.str2ip(ip)
        self.get_addr_by_ip(ip)
        range = self.ip2str(self.cur_start_ip) + ' - ' + self.ip2str(self.
            cur_end_ip)
        return range

    def get_offset_string(self, offset=0):
        "\n        获取文件偏移处的字符串(以'\x00'结尾)\n        :param offset: 偏移\n        :return: str\n        "
        if offset:
            self.f_db.seek(offset)
        bs = b''
        ch = self.f_db.read(1)
        byte, = struct.unpack('B', ch)
        while byte != 0:
            bs += ch
            ch = self.f_db.read(1)
            byte, = struct.unpack('B', ch)
        return bs.decode('gbk')

    def ip2str(self, ip):
        """
        整数IP转化为IP字符串
        :param ip:
        :return:
        """
        return str(ip >> 24) + '.' + str(ip >> 16 & 255) + '.' + str(ip >> 
            8 & 255) + '.' + str(ip & 255)

    def str2ip(self, s):
        """
        IP字符串转换为整数IP
        :param s:
        :return:
        """
        ip, = struct.unpack('I', socket.inet_aton(s))
        return ip >> 24 & 255 | (ip & 255) << 24 | ip >> 8 & 65280 | (ip & 
            65280) << 8

    def getLong3(self, offset=0):
        """
        3字节的数值
        :param offset:
        :return:
        """
        if offset:
            self.f_db.seek(offset)
        bs = self.f_db.read(3)
        a, b = struct.unpack('HB', bs)
        return (b << 16) + a

    def get_csv_data(self):
        csv_files = csv.reader(open(self.csv_file, 'r'))
        content = []
        for line in csv_files:
            content.append(line)
        return content[1:]


<mask token>

<mask token>


class CzIp:

    def __init__(self, db_file='qqwry_lastest.dat', csv_file='场所客户端IP.csv'):
        self.f_db = open(db_file, 'rb')
        self.csv_file = csv_file
        bs = self.f_db.read(8)
        self.first_index, self.last_index = struct.unpack('II', bs)
        self.index_count = int((self.last_index - self.first_index) / 7 + 1)
        self.cur_start_ip = None
        self.cur_end_ip_offset = None
        self.cur_end_ip = None
        print(self.get_version(), ' 纪录总数: %d 条 ' % self.index_count)

    def get_version(self):
        """
        获取版本信息，最后一条IP记录 255.255.255.0-255.255.255.255 是版本信息
        :return: str
        """
        s = self.get_addr_by_ip(4294967040)
        return s

    def _get_area_addr(self, offset=0):
        if offset:
            self.f_db.seek(offset)
        bs = self.f_db.read(1)
        byte, = struct.unpack('B', bs)
        if byte == 1 or byte == 2:
            p = self.getLong3()
            if p:
                return self.get_offset_string(p)
            else:
                return ''
        else:
            self.f_db.seek(-1, 1)
            return self.get_offset_string(offset)

    def _get_addr(self, offset):
        """
        获取offset处记录区地址信息(包含国家和地区)
        如果是中国ip，则是 "xx省xx市 xxxxx地区" 这样的形式
        (比如:"福建省 电信", "澳大利亚 墨尔本Goldenit有限公司")
        :param offset:
        :return:str
        """
        self.f_db.seek(offset + 4)
        bs = self.f_db.read(1)
        byte, = struct.unpack('B', bs)
        if byte == 1:
            country_offset = self.getLong3()
            self.f_db.seek(country_offset)
            bs = self.f_db.read(1)
            b, = struct.unpack('B', bs)
            if b == 2:
                country_addr = self.get_offset_string(self.getLong3())
                self.f_db.seek(country_offset + 4)
            else:
                country_addr = self.get_offset_string(country_offset)
            area_addr = self._get_area_addr()
        elif byte == 2:
            country_addr = self.get_offset_string(self.getLong3())
            area_addr = self._get_area_addr(offset + 8)
        else:
            country_addr = self.get_offset_string(offset + 4)
            area_addr = self._get_area_addr()
        return country_addr + ' ' + area_addr

    def dump(self, first, last):
        """
        打印数据库中索引为first到索引为last(不包含last)的记录
        :param first:
        :param last:
        :return:
        """
        if last > self.index_count:
            last = self.index_count
        for index in range(first, last):
            offset = self.first_index + index * 7
            self.f_db.seek(offset)
            buf = self.f_db.read(7)
            ip, of1, of2 = struct.unpack('IHB', buf)
            address = self._get_addr(of1 + (of2 << 16))
            print('%d %s %s' % (index, self.ip2str(ip), address))
    <mask token>

    def get_addr_by_ip(self, ip):
        """
        通过ip查找其地址
        :param ip: (int or str)
        :return: str
        """
        if type(ip) == str:
            ip = self.str2ip(ip)
        L = 0
        R = self.index_count - 1
        while L < R - 1:
            M = int((L + R) / 2)
            self._set_ip_range(M)
            if ip == self.cur_start_ip:
                L = M
                break
            if ip > self.cur_start_ip:
                L = M
            else:
                R = M
        self._set_ip_range(L)
        if ip & 4294967040 == 4294967040:
            self._set_ip_range(R)
        if self.cur_start_ip <= ip <= self.cur_end_ip:
            address = self._get_addr(self.cur_end_ip_offset)
        else:
            address = '未找到该IP的地址'
        return address

    def get_ip_range(self, ip):
        """
        返回ip所在记录的IP段
        :param ip: ip(str or int)
        :return: str
        """
        if type(ip) == str:
            ip = self.str2ip(ip)
        self.get_addr_by_ip(ip)
        range = self.ip2str(self.cur_start_ip) + ' - ' + self.ip2str(self.
            cur_end_ip)
        return range

    def get_offset_string(self, offset=0):
        "\n        获取文件偏移处的字符串(以'\x00'结尾)\n        :param offset: 偏移\n        :return: str\n        "
        if offset:
            self.f_db.seek(offset)
        bs = b''
        ch = self.f_db.read(1)
        byte, = struct.unpack('B', ch)
        while byte != 0:
            bs += ch
            ch = self.f_db.read(1)
            byte, = struct.unpack('B', ch)
        return bs.decode('gbk')

    def ip2str(self, ip):
        """
        整数IP转化为IP字符串
        :param ip:
        :return:
        """
        return str(ip >> 24) + '.' + str(ip >> 16 & 255) + '.' + str(ip >> 
            8 & 255) + '.' + str(ip & 255)

    def str2ip(self, s):
        """
        IP字符串转换为整数IP
        :param s:
        :return:
        """
        ip, = struct.unpack('I', socket.inet_aton(s))
        return ip >> 24 & 255 | (ip & 255) << 24 | ip >> 8 & 65280 | (ip & 
            65280) << 8

    def getLong3(self, offset=0):
        """
        3字节的数值
        :param offset:
        :return:
        """
        if offset:
            self.f_db.seek(offset)
        bs = self.f_db.read(3)
        a, b = struct.unpack('HB', bs)
        return (b << 16) + a

    def get_csv_data(self):
        csv_files = csv.reader(open(self.csv_file, 'r'))
        content = []
        for line in csv_files:
            content.append(line)
        return content[1:]


<mask token>

import socket
import struct
import csv


class CzIp:

    def __init__(self, db_file='qqwry_lastest.dat', csv_file='场所客户端IP.csv'):
        self.f_db = open(db_file, 'rb')
        self.csv_file = csv_file
        bs = self.f_db.read(8)
        self.first_index, self.last_index = struct.unpack('II', bs)
        self.index_count = int((self.last_index - self.first_index) / 7 + 1)
        self.cur_start_ip = None
        self.cur_end_ip_offset = None
        self.cur_end_ip = None
        print(self.get_version(), ' 纪录总数: %d 条 ' % self.index_count)

    def get_version(self):
        """
        获取版本信息，最后一条IP记录 255.255.255.0-255.255.255.255 是版本信息
        :return: str
        """
        s = self.get_addr_by_ip(4294967040)
        return s

    def _get_area_addr(self, offset=0):
        if offset:
            self.f_db.seek(offset)
        bs = self.f_db.read(1)
        byte, = struct.unpack('B', bs)
        if byte == 1 or byte == 2:
            p = self.getLong3()
            if p:
                return self.get_offset_string(p)
            else:
                return ''
        else:
            self.f_db.seek(-1, 1)
            return self.get_offset_string(offset)

    def _get_addr(self, offset):
        """
        获取offset处记录区地址信息(包含国家和地区)
        如果是中国ip，则是 "xx省xx市 xxxxx地区" 这样的形式
        (比如:"福建省 电信", "澳大利亚 墨尔本Goldenit有限公司")
        :param offset:
        :return:str
        """
        self.f_db.seek(offset + 4)
        bs = self.f_db.read(1)
        byte, = struct.unpack('B', bs)
        if byte == 1:
            country_offset = self.getLong3()
            self.f_db.seek(country_offset)
            bs = self.f_db.read(1)
            b, = struct.unpack('B', bs)
            if b == 2:
                country_addr = self.get_offset_string(self.getLong3())
                self.f_db.seek(country_offset + 4)
            else:
                country_addr = self.get_offset_string(country_offset)
            area_addr = self._get_area_addr()
        elif byte == 2:
            country_addr = self.get_offset_string(self.getLong3())
            area_addr = self._get_area_addr(offset + 8)
        else:
            country_addr = self.get_offset_string(offset + 4)
            area_addr = self._get_area_addr()
        return country_addr + ' ' + area_addr

    def dump(self, first, last):
        """
        打印数据库中索引为first到索引为last(不包含last)的记录
        :param first:
        :param last:
        :return:
        """
        if last > self.index_count:
            last = self.index_count
        for index in range(first, last):
            offset = self.first_index + index * 7
            self.f_db.seek(offset)
            buf = self.f_db.read(7)
            ip, of1, of2 = struct.unpack('IHB', buf)
            address = self._get_addr(of1 + (of2 << 16))
            print('%d %s %s' % (index, self.ip2str(ip), address))

    def _set_ip_range(self, index):
        offset = self.first_index + index * 7
        self.f_db.seek(offset)
        buf = self.f_db.read(7)
        self.cur_start_ip, of1, of2 = struct.unpack('IHB', buf)
        self.cur_end_ip_offset = of1 + (of2 << 16)
        self.f_db.seek(self.cur_end_ip_offset)
        buf = self.f_db.read(4)
        self.cur_end_ip, = struct.unpack('I', buf)

    def get_addr_by_ip(self, ip):
        """
        通过ip查找其地址
        :param ip: (int or str)
        :return: str
        """
        if type(ip) == str:
            ip = self.str2ip(ip)
        L = 0
        R = self.index_count - 1
        while L < R - 1:
            M = int((L + R) / 2)
            self._set_ip_range(M)
            if ip == self.cur_start_ip:
                L = M
                break
            if ip > self.cur_start_ip:
                L = M
            else:
                R = M
        self._set_ip_range(L)
        if ip & 4294967040 == 4294967040:
            self._set_ip_range(R)
        if self.cur_start_ip <= ip <= self.cur_end_ip:
            address = self._get_addr(self.cur_end_ip_offset)
        else:
            address = '未找到该IP的地址'
        return address

    def get_ip_range(self, ip):
        """
        返回ip所在记录的IP段
        :param ip: ip(str or int)
        :return: str
        """
        if type(ip) == str:
            ip = self.str2ip(ip)
        self.get_addr_by_ip(ip)
        range = self.ip2str(self.cur_start_ip) + ' - ' + self.ip2str(self.
            cur_end_ip)
        return range

    def get_offset_string(self, offset=0):
        "\n        获取文件偏移处的字符串(以'\x00'结尾)\n        :param offset: 偏移\n        :return: str\n        "
        if offset:
            self.f_db.seek(offset)
        bs = b''
        ch = self.f_db.read(1)
        byte, = struct.unpack('B', ch)
        while byte != 0:
            bs += ch
            ch = self.f_db.read(1)
            byte, = struct.unpack('B', ch)
        return bs.decode('gbk')

    def ip2str(self, ip):
        """
        整数IP转化为IP字符串
        :param ip:
        :return:
        """
        return str(ip >> 24) + '.' + str(ip >> 16 & 255) + '.' + str(ip >> 
            8 & 255) + '.' + str(ip & 255)

    def str2ip(self, s):
        """
        IP字符串转换为整数IP
        :param s:
        :return:
        """
        ip, = struct.unpack('I', socket.inet_aton(s))
        return ip >> 24 & 255 | (ip & 255) << 24 | ip >> 8 & 65280 | (ip & 
            65280) << 8

    def getLong3(self, offset=0):
        """
        3字节的数值
        :param offset:
        :return:
        """
        if offset:
            self.f_db.seek(offset)
        bs = self.f_db.read(3)
        a, b = struct.unpack('HB', bs)
        return (b << 16) + a

    def get_csv_data(self):
        csv_files = csv.reader(open(self.csv_file, 'r'))
        content = []
        for line in csv_files:
            content.append(line)
        return content[1:]


if __name__ == '__main__':
    cz = CzIp()
    ips = cz.get_csv_data()
    csvFile = open('场所客户端.csv', 'w', newline='')
    writer = csv.writer(csvFile)
    writer.writerow(['site_ap_ip', ' ', 'address', ' ', '运营商'])
    for ip in ips:
        address = cz.get_addr_by_ip(ip[0])
        add = address.split()
        writer.writerow([ip[0], ' ', add[0], ' ', add[1]])

import socket
import struct
import csv

class CzIp:
    def __init__(self, db_file='qqwry_lastest.dat', csv_file = '场所客户端IP.csv'):
        self.f_db = open(db_file, "rb")
        self.csv_file = csv_file
        bs = self.f_db.read(8)
        (self.first_index, self.last_index) = struct.unpack('II', bs)
        self.index_count = int((self.last_index - self.first_index) / 7 + 1)
        self.cur_start_ip = None
        self.cur_end_ip_offset = None
        self.cur_end_ip = None
        print(self.get_version(), " 纪录总数: %d 条 "%(self.index_count))

    def get_version(self):
        '''
        获取版本信息，最后一条IP记录 255.255.255.0-255.255.255.255 是版本信息
        :return: str
        '''
        s = self.get_addr_by_ip(0xffffff00)
        # print(s)
        return s

    def _get_area_addr(self, offset=0):
        if offset:
            self.f_db.seek(offset)
        bs = self.f_db.read(1)
        (byte,) = struct.unpack('B', bs)
        if byte == 0x01 or byte == 0x02:
            p = self.getLong3()
            if p:
                return self.get_offset_string(p)
            else:
                return ""
        else:
            self.f_db.seek(-1, 1)
            return self.get_offset_string(offset)

    def _get_addr(self, offset):
        '''
        获取offset处记录区地址信息(包含国家和地区)
        如果是中国ip，则是 "xx省xx市 xxxxx地区" 这样的形式
        (比如:"福建省 电信", "澳大利亚 墨尔本Goldenit有限公司")
        :param offset:
        :return:str
        '''
        self.f_db.seek(offset + 4)
        bs = self.f_db.read(1)
        (byte,) = struct.unpack('B', bs)
        if byte == 0x01:    # 重定向模式1
            country_offset = self.getLong3()
            self.f_db.seek(country_offset)
            bs = self.f_db.read(1)
            (b,) = struct.unpack('B', bs)
            if b == 0x02:
                country_addr = self.get_offset_string(self.getLong3())
                self.f_db.seek(country_offset + 4)
            else:
                country_addr = self.get_offset_string(country_offset)
            area_addr = self._get_area_addr()
        elif byte == 0x02:  # 重定向模式2
            country_addr = self.get_offset_string(self.getLong3())
            area_addr = self._get_area_addr(offset + 8)
        else:   # 字符串模式
            country_addr = self.get_offset_string(offset + 4)
            area_addr = self._get_area_addr()
        return country_addr + " " + area_addr

    def dump(self, first, last):
        '''
        打印数据库中索引为first到索引为last(不包含last)的记录
        :param first:
        :param last:
        :return:
        '''
        if last > self.index_count:
            last = self.index_count
        for index in range(first, last):
            offset = self.first_index + index * 7
            self.f_db.seek(offset)
            buf = self.f_db.read(7)
            (ip, of1, of2) = struct.unpack("IHB", buf)
            address = self._get_addr(of1 + (of2 << 16))
            print("%d %s %s" % (index, self.ip2str(ip), address))

    def _set_ip_range(self, index):
        offset = self.first_index + index * 7
        self.f_db.seek(offset)
        buf = self.f_db.read(7)
        (self.cur_start_ip, of1, of2) = struct.unpack("IHB", buf)
        self.cur_end_ip_offset = of1 + (of2 << 16)
        self.f_db.seek(self.cur_end_ip_offset)
        buf = self.f_db.read(4)
        (self.cur_end_ip,) = struct.unpack("I", buf)

    def get_addr_by_ip(self, ip):
        '''
        通过ip查找其地址
        :param ip: (int or str)
        :return: str
        '''
        if type(ip) == str:
            ip = self.str2ip(ip)
        L = 0
        R = self.index_count - 1
        while L < R - 1:
            M = int((L + R) / 2)
            self._set_ip_range(M)
            if ip == self.cur_start_ip:
                L = M
                break
            if ip > self.cur_start_ip:
                L = M
            else:
                R = M
        self._set_ip_range(L)
        # version information, 255.255.255.X, urgy but useful
        if ip & 0xffffff00 == 0xffffff00:
            self._set_ip_range(R)
        if self.cur_start_ip <= ip <= self.cur_end_ip:
            address = self._get_addr(self.cur_end_ip_offset)
        else:
            address = "未找到该IP的地址"
        # print("address:"+address)
        return address

    def get_ip_range(self, ip):
        '''
        返回ip所在记录的IP段
        :param ip: ip(str or int)
        :return: str
        '''
        if type(ip) == str:
            ip = self.str2ip(ip)
        self.get_addr_by_ip(ip)
        range = self.ip2str(self.cur_start_ip) + ' - ' \
                + self.ip2str(self.cur_end_ip)
        return range

    def get_offset_string(self, offset=0):
        '''
        获取文件偏移处的字符串(以'\0'结尾)
        :param offset: 偏移
        :return: str
        '''
        if offset:
            self.f_db.seek(offset)
        bs = b''
        ch = self.f_db.read(1)
        (byte,) = struct.unpack('B', ch)
        while byte != 0:
            bs += ch
            ch = self.f_db.read(1)
            (byte,) = struct.unpack('B', ch)
        return bs.decode('gbk')

    def ip2str(self, ip):
        '''
        整数IP转化为IP字符串
        :param ip:
        :return:
        '''
        return str(ip >> 24) + '.' + str((ip >> 16) & 0xff) + '.' + str((ip >> 8) & 0xff) + '.' + str(ip & 0xff)

    def str2ip(self, s):
        '''
        IP字符串转换为整数IP
        :param s:
        :return:
        '''
        (ip,) = struct.unpack('I', socket.inet_aton(s))
        return ((ip >> 24) & 0xff) | ((ip & 0xff) << 24) | ((ip >> 8) & 0xff00) | ((ip & 0xff00) << 8)

    def getLong3(self, offset=0):
        '''
        3字节的数值
        :param offset:
        :return:
        '''
        if offset:
            self.f_db.seek(offset)
        bs = self.f_db.read(3)
        (a, b) = struct.unpack('HB', bs)
        return (b << 16) + a
    def get_csv_data(self):
        csv_files = csv.reader(open(self.csv_file, 'r'))
        # print(csv_files)  # 可以先输出看一下该文件是什么样的类型

        content = []  # 用来存储整个文件的数据，存成一个列表，列表的每一个元素又是一个列表，表示的是文件的某一行

        for line in csv_files:
            # print(line) #打印文件每一行的信息
            content.append(line)
        # print("该文件中保存的数据为:\n", content[1:])

        return content[1:]

if __name__ == '__main__':
    cz = CzIp()
    ips = cz.get_csv_data()
    csvFile = open("场所客户端.csv", "w" ,newline='')  # 创建csv文件
    writer = csv.writer(csvFile)  # 创建写的对象
    writer.writerow(["site_ap_ip", " ", "address", " ", "运营商"])  # 写入列的名称
    for ip in ips:
        # print(ip[0])
        address = cz.get_addr_by_ip(ip[0])
        # print(address)
        add = address.split()
        writer.writerow([ip[0], ' ', add[0], ' ', add[1]])