一个比较独特的"HelloWorld"
为什么说是特殊的helloworld呢
给全世界的服务器发送一个请求,这就是我"打招呼"的方式
核心内容就是:向所有的ipv4地址发送一个请求
即x.x.x.x,如果其是web服务,就拿到其title标签里的内容,
然后看看这个IP(或者说网站)是做什么的,
你问我这么做的意义是什么?
文章结尾我再谈谈做这件事情的意义.
接下来谈谈过滤条件
IPV4地址有非常多个,从0.0.0.0~255.255.255.255,共有4,294,967,296个
将近43亿个,当然,这里面的IP大部分是无效的,无法访问的,
我将不会处理包含以下任意条件的IP地址,因为无意义
1.五秒内没有响应的
2.状态码不是200的
3.状态码是200,但没有title标签的.
4.其它无法访问的异常.
即使加了这些条件,要走完这43亿服务器,也必然是一个漫长的过程,
好在是机器帮我来做这件事情,我只要开着程序,过一段时间看看就好.
理一理思路
要想实现这个看似简单的需求,其实也并不是那么容易的
.要有一个IP生成器.按顺序生成0.0.0.0到255.255.255.255的IP字符串
生成出来的IP还不能保存,即生即用,不然分分钟爆内存啦.
要有计数器,统计一共请求过多少IP,失败过多少次?成功过多少次?失败原因等等
要开启多线程,不能单线程去请求,不然这辈子都别想把这个程序跑完.
要考虑到程序因为意外原因被关掉以后,不要又从头开始,
例如第一个请求是0.0.0.0,第二个是0.0.0.1,当你请求到数千万时,中断了,不能又从0.0.0.0开始.
开始撸代码
首先,关于IP生成器的想法,我的想法是映射
即0.0.0.0映射为0,代表着它是第0个IP地址
0.0.0.1映射为1,代表着它是第1个IP地址
0.0.1.0映射为256,代表第256个IP地址,
妥妥的256进制嘛,
假如我传入一个0~4294967295之间的整数,
是不是意味着这里面的每一个整数都可以映射为一个IP地址呢,
下面我用python来实现这个函数,
def ipv4(n): if n >= 16777216:
ip_1 = int(n/16777216)
ip_1s = n%16777216
ip_2 = int(ip_1s/65536)
ip_2s = ip_1s%65536
ip_3 = int(ip_2s/256)
ip_3s = ip_2s%256
ip_4 = ip_3s
# print(ip_1,ip_2,ip_3,ip_4,sep=".")
return "{}.{}.{}.{}".format(ip_1,ip_2,ip_3,ip_4)
elif n<16777216 and n>=65536:
ip_1 = 0
ip_2 = int(n/65536)
ip_2s = n%65536
ip_3 = int(ip_2s/256)
ip_3s = ip_2s%256
ip_4 = ip_3s
# print(ip_1,ip_2,ip_3,ip_4,sep=".")
return "{}.{}.{}.{}".format(ip_1,ip_2,ip_3,ip_4)
elif n<65536 and n>=256:
ip_1 = 0
ip_2 = 0
ip_3 = int(n/256)
ip_3s = n%256
ip_4 = ip_3s
# print(ip_1,ip_2,ip_3,ip_4,sep=".")
return "{}.{}.{}.{}".format(ip_1,ip_2,ip_3,ip_4)
else:
# print("0.0.0.{}".format(n))
return "0.0.0.{}".format(n)
随便输个数字测一下
>>>ipv4(2888889999)
172.48.246.143
>>>ipv4(256)
0.0.1.0
接下来,准备一个巨大的整数(42,9496,7295)
它代表着255.255.255.255.
没错,只是一个网关地址,它肯定无法被请求,但我还是决定从它开始,
每发送一个请求,这个数字就减去一,来个死循环
流程总体来说就是这样的:
1.取到count,这个值(42,9496,7295)当计数器
2.把这个值解析为IP.(255.255.255.255),
3.向这个IP地址发送请求
4.count-=1
循环以上操作.
第1次执行的时候,请求地址是255.255.255.255
第2次:255.255.255.254
第3次:255.255.255.253
第4次:255.255.255.252
…
下面是具体请求的代码
节选自Class的代码
代码写得比较糙,因为这只是个小demo,写着玩,敬请谅解,
取到的数据直接保存成txt了,后面有空再优化.
def getdata(self,ip): try:
r = requests.get(url=ip, headers=self.headers ,timeout=self.timeout)
r_code = r.status_code
r_text = r.content.decode("utf8")
title = re.findall("<title>(.*?)</title>", r_text) if r_code!=200:
self.bad_status_count+=1
return
if len(title)==0:
self.not_title_count+=1
return
if title[0]=="":
self.not_title_count+=1
return
c_ip = ip.replace("http://","") with open("f://hello_world/"+c_ip+title[0]+".txt","w",encoding="utf8")as f:
pass except:
self.time_out_count+=1
return
全部代码:
我开了1000个线程.
没有做MT4教程线程锁之类的东西,测试了一下不影响,就没做了
数据以光有名字没内容的txt文件存在f盘hello world文件夹里,
如果有copy代码运行的,可以自己改路径
比较糙,有空再优化
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# author: kcc time:2019/11/16 import requests,re,random,threading,time,os class SpiderWorld(): def __init__(self): self.headers = {
"User-Agent":"User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36"
,"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3"
} self.timeout = 5 self.ip_count = 4294967295
#2642648575
#4294967295
self.time_out_count = 0 self.bad_status_count = 0 self.not_title_count = 0 def getdata(self,ip):
#发送请求
try:
r = requests.get(url=ip, headers=self.headers ,timeout=self.timeout)
r_code = r.status_code
r_text = r.content.decode("utf8")
title = re.findall("<title>(.*?)</title>", r_text) if r_code!=200:
self.bad_status_count+=1
return
if len(title)==0:
self.not_title_count+=1
return
if title[0]=="":
self.not_title_count+=1
return
c_ip = ip.replace("http://","") with open("f://hello_world/"+c_ip+title[0]+".txt","w",encoding="utf8")as f:
pass except:
self.time_out_count+=1
return def ipv4(self,n):
#把n解析为IP地址字符串
if n >= 16777216:
ip_1 = int(n/16777216)
ip_1s = n%16777216
ip_2 = int(ip_1s/65536)
ip_2s = ip_1s%65536
ip_3 = int(ip_2s/256)
ip_3s = ip_2s%256
ip_4 = ip_3s
# print(ip_1,ip_2,ip_3,ip_4,sep=".")
return "{}.{}.{}.{}".format(ip_1,ip_2,ip_3,ip_4)
elif n<16777216 and n>=65536:
ip_1 = 0
ip_2 = int(n/65536)
ip_2s = n%65536
ip_3 = int(ip_2s/256)
ip_3s = ip_2s%256
ip_4 = ip_3s
# print(ip_1,ip_2,ip_3,ip_4,sep=".")
return "{}.{}.{}.{}".format(ip_1,ip_2,ip_3,ip_4)
elif n<65536 and n>=256:
ip_1 = 0
ip_2 = 0
ip_3 = int(n/256)
ip_3s = n%256
ip_4 = ip_3s
# print(ip_1,ip_2,ip_3,ip_4,sep=".")
return "{}.{}.{}.{}".format(ip_1,ip_2,ip_3,ip_4)
else:
# print("0.0.0.{}".format(n))
return "0.0.0.{}".format(n) def main(self):
#主函数循环
while True: req_ip = "http://"+self.ipv4(self.ip_count)
self.ip_count-=1
self.getdata(req_ip) if self.ip_count<100:return def state(self):
#每隔十秒输出一下日志
while True:
with open("a.txt","w",encoding="utf8")as f:
f.write("当前轮询IP地址{}".format(self.ipv4(self.ip_count))+"\n")
f.write("当前剩余IP地址数{}".format(self.ip_count)+"\n")
f.write("超时数量{}".format(self.time_out_count)+"\n")
f.write("错误状态码数{}".format(self.bad_status_count)+"\n")
f.write("无效标题数{}".format(self.not_title_count)+"\n") time.sleep(10) if __name__ == "__main__":
#开启程序1000线程
a = SpiderWorld()
for i in range(1000):
t = threading.Thread(target=a.main)
t.start() #开启一个输出日志的线程
a = threading.Thread(target=a.state)
a.start()
一个比较独特的"HelloWorld"的更多相关文章
- (一)IDEA工具开第一个springboot应用之helloworld
(一)IDEA工具开第一个springboot应用之helloworld 一.前置知识 1.maven相关知识 2.spring注解 3.RESTful API 二.idea开发第一个springbo ...
- scala 入门Eclipse环境搭建及第一个入门经典程序HelloWorld
scala 入门Eclipse环境搭建及第一个入门经典程序HelloWorld 学习了: http://blog.csdn.net/wangmuming/article/details/3407911 ...
- 创建第一个Android应用程序 HelloWorld
按照博客的进程,今天应该进行程序编写啦,下面让我们开写一个简单的HelloWorld程序. 提示:这里对于如何使用Eclipse创建一个Android程序就不多讲啦,不会的同学可以去查阅相关文档. 程 ...
- 用 Smali 手写一个可运行的 HelloWorld!!!
一.前言 Android 的 App 实际上并不是运行在 Java 虚拟机中,而是运行在 Dalvik 虚拟机中.Dalvik 虚拟机对 Java 虚拟机做了一些额外的优化,让它更适用于移动设备.而 ...
- 第一个spring简单的helloworld
spring 是一个开源的框架 也是轻量级框架 1.导入jar包 spring的版本 4.0 目录: spring-framework-4.0.0.RELEASE-libs 下的jar spring ...
- 第一个Django项目:HelloWorld
OS:Windows家庭中文版, Python:3.6.3,Django:2.0.3 在前一篇文章中,Django已经顺利安装到了Python中,下面,开发第一个Python项目吧! 1.django ...
- 第一个duilib程序 - 实现HelloWorld详解
duilib是一个windows下的皮肤库,用win32写的... 先看个效果图吧: 要使用duilib库,必须先把库导入,代码如下: View Row Code 1 #include "x ...
- 【Java】手动编写第一个Java程序,HelloWorld!
第一个Java程序HelloWorld! 环境前提:确保你已经配置好了JDK8的环境变量,和本体安装 打开文本编辑器,这里我使用的是EditPlus 编写代码: public class Hello{ ...
- 第一个Struts2程序之HelloWorld
1.Struts2 简介 Struts 2是Struts的下一代产品,是在 struts 1和WebWork的技术基础上进行了合并的全新的Struts 2框架.其全新的Struts 2的体系结构与St ...
随机推荐
- cocos2D-X c++ call java
{ //https://blog.csdn.net/yuechuzhao/article/details/9283847 }
- 大碗宽面Beta迭代阶段博客目录
大碗宽面Beta迭代阶段博客目录 Githhub:https://github.com/rz-2000/Course-Evaluation 一.Scrum Meeting 1. [第十周会议记录]ht ...
- AcWing 234. 放弃测试 (01分数规划)打卡
题目:https://www.acwing.com/problem/content/236/ 题意:给你一个方程,可以有k个不选,要求最优 思路:看了一下这个方程就知道是01分数规划的模板题,它可以选 ...
- Git Git管理码云项目
Git 一.下载安装 1. 要使用git 先安转git 请到官网下载最新git https://git-scm.com/downloads 2. 一路默认安装,安装完成右键查看下是否有Git. 二 ...
- 自己封装 vue 组件 和 插件
vue 组件 一.组件的创建,两种方法.(本质上是1.2两种,vue文件,只是创建了一个 组件选项对象,仅是一个js对象)1.定义组件:Vue.component('button-counter', ...
- [CSP-S模拟测试63]题解
A.Median 这题的数据生成方式并没有什么规律,所以可以认为是随机数据. 维护一个桶,表示当前K长区间里的值域情况. 并且用变量记录中位数值域上的左侧有多少个数,当区间调整时一并调整桶和这个变量即 ...
- HTML5 开发技能图谱skill-map
# HTML5 开发技能图谱![HTML5 脑图](https://github.com/TeamStuQ/skill-map/blob/master/data/designbyStuQ/png-HT ...
- PHP面试 AJAX基础内容
AJAX基础内容 Ajax的基本工作原理 Ajax基础概念:通过在后台与服务器进行少量数据交换,Ajax可以使用网页实现异步更新 Ajax工作原理:XMLHttpRequest是Ajax的基础 ...
- client-go获取k8s集群内部连接,实现deployment的增删改查
一开始写了一个client-java版本的,但是java放在k8s集群上跑需要装jvm而且java的包比较大,client-go版本更适合主机端,下面是整个实现 说明:k8s官方维护的客户端库只有go ...
- 9.Jmeter自定义Sample(自定义测试内容)完成测试
问题:在某些场景下我们会发现Jmeter里面提供的各种Sample不能满足自己的需求,应为这个世界上的压力测试的逻辑本来就是千变万化的,所以这个时候我们如果自己实现一套测试逻辑(当Jmeter的基本e ...