Python uses the Pure Age database Qqwry.dat to convert physical locations

Source: Internet
Author: User
Tags ord pack unpack

PS: Online directly to find, paste out, convenient to use at any time, thanks to the people who share.

#!/usr/bin/python#encoding:utf-8import socketimport codecsimport mmapfrom struct import pack, Unpackdef decode_str (old        ): "Specifically for pure GBK encoded string decompression returns UTF8 string ' ' Try:return Unicode (old, ' GBK '). Encode (' Utf-8 ') except: # when the string decoding fails, and the most byte value is ' \x96 ', remove it, and then resolve if old[-1] = = ' \x96 ': Try:return Unicode (old[:-1], '            GBK '). Encode (' utf-8 ') + '? ' Except:pass return ' Invalid ' class Qqwry (object): Def __init__ (self, path): Self.path = PA        Th self.db = None self.open_db () self.idx_start, self.idx_end = Self._read_idx () # IP Index Total Self.total = (Self.idx_end-self.idx_start)/7 + 1 def open_db (self): if not self.db:self.db = Open (Self.path, ' rb ') self.db = Mmap.mmap (Self.db.fileno (), 0, Access = 1) return self.db def _read_i DX (self): ' Read the IP index start and end offset values in the database ' ' Self.db.seek (0) Start = unpack (' I ', SELf.db.read (4)) [0] end = Unpack (' I ', Self.db.read (4)) [0] return start, End Def version (self): "        Returns the version information format of the pure IP library such as "Pure Network August 5, 2014 IP data" ' Ip_end_offset = Self.read_offset (Self.idx_end + 4) A_raw, B_raw = Self.read_record (ip_end_offset+4) return decode_str (A_raw + b_raw) def read_ip (self, off, see  K=true): ' Read IP value (4 byte integer value) return IP value ' if Seek:self.db.seek (off) buf =        Self.db.read (4) Return unpack (' I ', buf) [0] def read_offset (self, Off, seek=true): ' reads 3 bytes of offset value Returns the integer value of the offset "if Seek:self.db.seek (off) buf = Self.db.read (3) Return unpack (' I ', buf+ ')             [0] def read_string (self, offset): ' reads the original string (ends with "\") returns the tuple: string "if offset = = 0: Return ' N/A1 ' flag = self.get_flag (offset) if flag = = 0:return ' n/a2 ' elif fl AG = = 2:           # 0x02 indicates that the information is still required to redirect offset = Self.read_offset (offset+1) return self.read_string (offset) Self.db.seek (offset) raw_string = "while true:x = Self.db.read (1) if x = = '        ': ' break raw_string + = x return raw_string def get_flag (self, offset): ' '        Reading the 1-byte integer value at offset qqwry the first byte value of the address information string may be a flag bit, which is a common function. "' Self.db.seek (offset) c = self.db.read (1) if not C:return 0 return ord (c) de F Read_record (self, offset): Self.db.seek (offset) # reads flag flag = Ord (Self.db.read (1)) if FLA G = = 1: # 0x01 indicates that the record area record (country, region) information is redirected # Note: Once redirected, the record may also be a redirect (its flag=0x02) buf = Self.db.rea D (3) A_offset = Unpack (' I ', buf+ ') [0] A_raw = self.read_string (a_offset) # Judging the flag of the new record is No for 0x02, if yes, indicates: #-Country Info redirect Additional address #-region information for new recordStart Address offset 4 bytes A_flag = Self.get_flag (a_offset) if A_flag = = 2:b_raw = Self.read_string (A            _offset+4) Else:b_raw = self.read_string (A_offset+len (A_raw) +1) elif flag = = 2: # 0x02 indicates only country record redirection # region information Offset 4 bytes buf = self.db.read (3) A_offset = Unpack (' I ', buf+ ' ") [0 ] A_raw = self.read_string (a_offset) B_raw = self.read_string (offset+4) Else: # Normal Information record A_raw = self.read_string (offset) B_raw = self.read_string (Offset+len (A_raw) +1) return a _raw, B_raw def output (self, output_file= ' ip.txt '): ' Output all IP information to file ' fp = Codecs.open (ou Tput_file, ' w ', ' UTF8 ') idx = self.idx_start while idx <= self.idx_end:ip_int = self.read_ip ( IDX) Ip_start = Socket.inet_ntoa (Pack ('! I ', ip_int)) Ip_end_offset = Self.read_offset (idx + 4) Ip_int = Self.read_ip (ip_end_offset) ip_end = Socket.inet_ntoa (Pack ('!            I ', ip_int)) A_raw, B_raw = Self.read_record (ip_end_offset+4) A_info = Decode_str (A_raw) B_info = Decode_str (B_raw) fp.write (U '%15s\t%15s\t%s,%s\n '% (Ip_start, Ip_end, a _info.decode (' UTF8 '), b_info.decode (' UTF8 ')) # Step 7 bytes: 4 byte starting IP value + 3 byte end IP Offset value idx + = 7 Fp.clo            SE () def find (self, IP, L, R): "Use dichotomy to find the index record of network byte-encoded IP address" if r-l <= 1: return l m = (L + r)/2 offset = Self.idx_start + M * 7 new_ip = self.read_ip (offset) If IP < New_ip:return self.find (IP, L, m) else:return self.find (IP, M, r) def query (self, I p): "Query IP Information '" # Using network byte encoding IP Address IP = unpack ('! I ', Socket.inet_aton (IP)) [0] # Find the index offset of the IP using the self.find function i = self.find (IP, 0, self.total-1) # get indexed Records        o = Self.idx_start + i * 7 # Index record format is: first 4 bytes IP information + 3 byte offset to IP record information # Here is the use of the last 3 bytes as an offset to get its regular representation (QQWry.Dat with characters        String representation value) O2 = Self.read_offset (O + 4) # IP record offset value +4 can discard the first 4 bytes of IP address information.            (c, a) = Self.read_record (O2 + 4) return (DECODE_STR (c), Decode_str (a)) def __del__ (self): if self.db: Self.db.close () def main (): DBPath = "C:\ipdata\qqwry.dat" IP = "183.61.60.23" Qqwry = Qqwry (dbpath) C , a = Qqwry.query (IP) print '%s%s--%s '% (IP, c.decode (' Utf-8 '), A.decode (' Utf-8 ')) if __name__ = = ' __main__ ': Main ( )

  

Result:

Python uses the Pure Age database Qqwry.dat to convert physical locations

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.