ip地址归属地检查
问题:在CSV文件(文件中有三列,第一个ip编码,第二个ip编码,国家编码),指定国家编码,检查ip地址是否能与国家编码对应,其中需要调用API检查ip归属。做的时候遇到不少问题,做完之后学到了很多东西。
遇到的问题和解决方法
1. 如何调用API
- API(Application Programming Interface)是应用程序接口。大多数API是基于Web标准设计的,Web API通常使用HTTP来传输信息,并提供响应信息的结构定义。这些响应消息通常都会以 XML 或 JSON 文件的形式来提供。
关于API的解释参考:https://www.redhat.com/zh/topics/api/what-are-application-programming-interfaces
-
JSON文件又是什么?简便的数据交换格式,能在服务器之间交换数据。
参考博客:https://www.cnblogs.com/hwtblog/p/8483573.html -
API传入参数有GET和POST两种
有一些查询ip归属地的API
使用GET传递参数的有:https://ip.mcr.moe/、http://ip-api.com/json、https://ip.seeip.org/geoip/、https://ip.nf/
使用POST传递参数的有:https://www.kda.im/ 、http://open.sevenidc.com/api/ip -
调用API用requests
例如
url = 'https://ip.mcr.moe/?ip='
url1 = url + '1.16.0.0'
reponse = requests.get(url1)
print(reponse.text)
要提取出API返回内容的国家代码,用字典接收返回的信息
url = 'https://ip.nf/'
url1 = url + '1.16.0.0' + '.json'
print(url1)
reponse = requests.get(url1)
dic = reponse.json()
dic1 = dic.get('ip')
print(dic1.get('country'))
2. ip编码后的数字如何转化为ipv4的编码
ipv4使用32位的地址,为了方便人阅读和分析,地址采用点分十进制表示。(即四个字节分开用十进制写,中间用点隔开)
def trans(ip_num):
buf = [0]*4
ip = ''
buf[0] = (ip_num >> 24) & 0xff
buf[1] = (ip_num >> 16) & 0xff
buf[2] = (ip_num >> 8) & 0xff
buf[3] = (ip_num >> 0) & 0xff
flag = 1
for i in range(4):
if flag == 1:
ip += str(buf[i])
flag = 0
else:
ip = ip + '.' + str(buf[i])
return ip
3. 在python上运行数据量很大,运行很慢,怎么解决?
在装有conda环境的linux主机上后台运行python程序
- conda上可以创建环境,激活环境
Conda 是一个开源的软件包管理系统和环境管理系统,用于安装多个版本的软件包及其依赖关系,并在它们之间轻松切换。
1.创建环境: conda create --name tf python=3.6
2.激活环境: conda activate tf
3.查看所有虚拟环境:conda info --envs
- 在linux后台运行程序
使用命令 nohup python -u 你的文件 >log.log 2>&1 &
liunx支持多用户、多任务、多进程
1.nohup(即 no hang up)为不断地执行,在界面关闭后不会停止运行
2.命令最后面的&:指后台运行,不会占据终端
具体参考:https://blog.csdn.net/weixin_42840933/article/details/85780125
3.和linux后台相关指令
jobs:查看工作进展
kill -9 进程号:杀死进程
ps -ef|grep python:终止后台运行的进程
常用命令:https://www.cnblogs.com/kaituorensheng/p/3980334.html
学到的知识
1.和python相关的细节
-
如果程序中有中文,要在程序最开始加上
# coding=UTF-8
,不然用其他打开会乱码 -
编程风格细节
函数上面要空出两行、要在定义函数下面用三个双引号注释函数功能、注释#后面要跟一个空格
2.linux常用指令
- 处理文件相关
vi或者vim: vi是打开文件后是文本文件的格式(相当于记事本),vim是打开文件后有语法高亮(类似notepad++),
touch:新建文件
mv:给文件改名
rm:删除文件
cat:查看文件
tail:查看文件末尾几行内容
进入文件后:
a或者i:编辑文件
ESC:退出编辑,:wq是保存并退出 - 命令自动补全
输入命令前几个字母,按Tab键自动补全 - man是命令手册
常用命令大全参考:https://blog.csdn.net/qq_23329167/article/details/83856430?utm_medium=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromMachineLearnPai2~default-1.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromMachineLearnPai2~default-1.control
3.linux远程传输文件scp指令
scp(secure copy):是 linux 系统下基于 ssh 登陆进行安全的远程文件拷贝命令
从本地复制到远程命令格式:
scp local_file remote_username@remote_ip:remote_folder
参考:https://www.runoob.com/linux/linux-comm-scp.html
4.Windows Power Shell
Windows PowerShell 是一种命令行外壳程序和脚本环境,使命令行用户和脚本编写者可以利用 .NET Framework的强大功能。
可以使用ssh进行远程登陆
命令:ssh username@hostip
5.linux上使用ffmpeg
小知识:多媒体视频处理工具FFmpeg有非常强大的功能包括视频采集功能、视频格式转换、视频抓图、给视频加水印等。
如果会用到:https://eyehere.net/2019/the-complete-guide-for-using-ffmpeg-in-linux/
最后附上整个代码
# coding=UTF-8
import requests
import csv
import time
def trans(ip_num):
"""
将ip编码转化为ipv4格式
:param ip_num:
:return: ip
"""
buf = [0]*4
ip = ''
buf[0] = (ip_num >> 24) & 0xff
buf[1] = (ip_num >> 16) & 0xff
buf[2] = (ip_num >> 8) & 0xff
buf[3] = (ip_num >> 0) & 0xff
flag = 1
for i in range(4):
if flag == 1:
ip += str(buf[i])
flag = 0
else:
ip = ip + '.' + str(buf[i])
return ip
if __name__ == '__main__':
with open(r'/root/ipv4.CSV', 'r') as csvfile:
reader = csv.reader(csvfile)
list1 = [row for row in reader] # list1存放CSV表中所有的行
list2 = [] # list2中存放表中国家代码是KR的行
url = ['http://ip-api.com/json/', 'https://ip.seeip.org/geoip/', 'https://ip.nf/']
for row in list1: # row是list1中一行,也是一个列表
if row[2] == 'KR':
list2.append(row)
for row in range(len(list2)): # 遍历list2中的每一行
# 一行中的ip范围每个255检测一下
for num in range(int(list2[row][0]), int(list2[row][0])+1, 255):
list_country = [] # 存放API返回的国家
ip = trans(num)
flag1 = 1 # ip是否正确的标志,不正确为0
# 每个ip在三个API中检查
for i in range(3):
if i == 2:
url1 = url[i] + ip + '.json'
else:
url1 = url[i] + ip
response = requests.get(url1)
dic = response.json()
# 根据三个API返回的格式不同,分别处理三个API
# 还有一些特殊例子不同成功运行,就特殊处理
if i == 0:
if dic.get('state') == 'fail':
list_country.append('NONE')
else:
list_country.append(dic.get('country'))
if i == 1:
if dic.get('country') == None:
list_country.append('NONE')
else:
list_country.append(dic.get('country'))
if i == 2:
if dic.get('ip').get('country') == '':
if dic.get('ip').get('country_code') == '':
list_country.append('NONE')
else:
list_country.append(dic.get('ip').get('country_code'))
else:
if dic.get('ip').get('country') == 'Korea, Republic of':
list_country.append('South Korea')
else:
list_country.append(dic.get('ip').get('country'))
# 三个API检测的ip有一个不正确就加入列表
if (i == 0 and dic.get('countryCode') != 'KR') or (i == 1 and dic.get('country_code') != 'KR') or (i == 2 and dic.get('ip').get('country_code') != 'KR'):
flag1 = 0
if flag1 == 0:
print(ip + ' ' + str(num) + ' ' + list_country[0] + ', ' + list_country[1] + ', ' + list_country[2])
time.sleep(5) # 运行太频繁会导致requests失败