Chinaunix首页 | 论坛 | 博客
  • 博客访问: 495214
  • 博文数量: 58
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 707
  • 用 户 组: 普通用户
  • 注册时间: 2019-10-09 17:06
文章分类
文章存档

2020年(4)

2019年(54)

我的朋友

分类: Python/Ruby

2019-11-20 16:50:42

为什么说是特殊的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来实现这个函数,

点击(此处)折叠或打开

  1. def ipv4(n):
  2.         
  3.         if n >= 16777216:
  4.             ip_1 = int(n/16777216)
  5.             ip_1s = n%16777216
  6.             ip_2 = int(ip_1s/65536)
  7.             ip_2s = ip_1s%65536
  8.             ip_3 = int(ip_2s/256)
  9.             ip_3s = ip_2s%256
  10.             ip_4 = ip_3s
  11.             # print(ip_1,ip_2,ip_3,ip_4,sep=".")
  12.             return "{}.{}.{}.{}".format(ip_1,ip_2,ip_3,ip_4)
  13.         elif n<16777216 and n>=65536:
  14.             ip_1 = 0
  15.             ip_2 = int(n/65536)
  16.             ip_2s = n%65536
  17.             ip_3 = int(ip_2s/256)
  18.             ip_3s = ip_2s%256
  19.             ip_4 = ip_3s
  20.             # print(ip_1,ip_2,ip_3,ip_4,sep=".")
  21.             return "{}.{}.{}.{}".format(ip_1,ip_2,ip_3,ip_4)
  22.         elif n<65536 and n>=256:
  23.             ip_1 = 0
  24.             ip_2 = 0
  25.             ip_3 = int(n/256)
  26.             ip_3s = n%256
  27.             ip_4 = ip_3s
  28.             # print(ip_1,ip_2,ip_3,ip_4,sep=".")
  29.             return "{}.{}.{}.{}".format(ip_1,ip_2,ip_3,ip_4)
  30.         else:
  31.             # print("0.0.0.{}".format(n))
  32.             return "0.0.0.{}".format(n)


随便输个数字测一下

点击(此处)折叠或打开

  1. >>>ipv4(2888889999)
  2. 172.48.246.143
  3. >>>ipv4(256)
  4. 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了,后面有空再优化.

点击(此处)折叠或打开

  1. def getdata(self,ip):
  2.         
  3.         try:
  4.             r = requests.get(url=ip, headers=self.headers ,timeout=self.timeout)
  5.             r_code = r.status_code
  6.             r_text = r.content.decode("utf8")
  7.             title = re.findall("(.*?)", r_text)

  8.             if r_code!=200:
  9.                 self.bad_status_count+=1
  10.                 return
  11.             if len(title)==0:
  12.                 self.not_title_count+=1
  13.                 return
  14.             if title[0]=="":
  15.                 self.not_title_count+=1
  16.                 return
  17.             c_ip = ip.replace("http://","")

  18.             with open("f://hello_world/"+c_ip+title[0]+".txt","w",encoding="utf8")as f:
  19.                 pass

  20.         except:
  21.             self.time_out_count+=1
  22.             return

全部代码:

我开了1000个线程.
没有做线程锁之类的东西,测试了一下不影响,就没做了
数据以光有名字没内容的txt文件存在f盘hello world文件夹里,
如果有copy代码运行的,可以自己改路径
比较糙,有空再优化

点击(此处)折叠或打开

  1. #!/usr/bin/env python
  2. # -*- coding:utf-8 -*-
  3. # author: kcc time:2019/11/16

  4. import requests,re,random,threading,time,os

  5. class SpiderWorld():

  6.     def __init__(self):

  7.         self.headers = {
  8.             "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"
  9.             ,"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3"
  10.         }

  11.         self.timeout = 5

  12.         self.ip_count = 4294967295
  13.         #2642648575
  14.         #4294967295
  15.         self.time_out_count = 0

  16.         self.bad_status_count = 0

  17.         self.not_title_count = 0

  18.     def getdata(self,ip):
  19.         #发送请求
  20.         try:
  21.             r = requests.get(url=ip, headers=self.headers ,timeout=self.timeout)
  22.             r_code = r.status_code
  23.             r_text = r.content.decode("utf8")
  24.             title = re.findall("(.*?)", r_text)

  25.             if r_code!=200:
  26.                 self.bad_status_count+=1
  27.                 return
  28.             if len(title)==0:
  29.                 self.not_title_count+=1
  30.                 return
  31.             if title[0]=="":
  32.                 self.not_title_count+=1
  33.                 return
  34.             c_ip = ip.replace("http://","")

  35.             with open("f://hello_world/"+c_ip+title[0]+".txt","w",encoding="utf8")as f:
  36.                 pass

  37.         except:
  38.             self.time_out_count+=1
  39.             return

  40.     def ipv4(self,n):
  41.         #把n解析为IP地址字符串
  42.         if n >= 16777216:
  43.             ip_1 = int(n/16777216)
  44.             ip_1s = n%16777216
  45.             ip_2 = int(ip_1s/65536)
  46.             ip_2s = ip_1s%65536
  47.             ip_3 = int(ip_2s/256)
  48.             ip_3s = ip_2s%256
  49.             ip_4 = ip_3s
  50.             # print(ip_1,ip_2,ip_3,ip_4,sep=".")
  51.             return "{}.{}.{}.{}".format(ip_1,ip_2,ip_3,ip_4)
  52.         elif n<16777216 and n>=65536:
  53.             ip_1 = 0
  54.             ip_2 = int(n/65536)
  55.             ip_2s = n%65536
  56.             ip_3 = int(ip_2s/256)
  57.             ip_3s = ip_2s%256
  58.             ip_4 = ip_3s
  59.             # print(ip_1,ip_2,ip_3,ip_4,sep=".")
  60.             return "{}.{}.{}.{}".format(ip_1,ip_2,ip_3,ip_4)
  61.         elif n<65536 and n>=256:
  62.             ip_1 = 0
  63.             ip_2 = 0
  64.             ip_3 = int(n/256)
  65.             ip_3s = n%256
  66.             ip_4 = ip_3s
  67.             # print(ip_1,ip_2,ip_3,ip_4,sep=".")
  68.             return "{}.{}.{}.{}".format(ip_1,ip_2,ip_3,ip_4)
  69.         else:
  70.             # print("0.0.0.{}".format(n))
  71.             return "0.0.0.{}".format(n)

  72.     def main(self):
  73.         #主函数循环
  74.         while True:
  75.             
  76.             req_ip = "http://"+self.ipv4(self.ip_count)
  77.             self.ip_count-=1
  78.             self.getdata(req_ip)
  79.             
  80.             if self.ip_count<100:return

  81.     def state(self):
  82.         #每隔十秒输出一下日志
  83.         while True:
  84.             with open("a.txt","w",encoding="utf8")as f:
  85.                 f.write("当前轮询IP地址{}".format(self.ipv4(self.ip_count))+"\n")
  86.                 f.write("当前剩余IP地址数{}".format(self.ip_count)+"\n")
  87.                 f.write("超时数量{}".format(self.time_out_count)+"\n")
  88.                 f.write("错误状态码数{}".format(self.bad_status_count)+"\n")
  89.                 f.write("无效标题数{}".format(self.not_title_count)+"\n")

  90.             time.sleep(10)
  91.             

  92. if __name__ == "__main__":
  93.     #开启程序1000线程
  94.     a = SpiderWorld()
  95.     for i in range(1000):
  96.         t = threading.Thread(target=a.main)
  97.         t.start()
  98.         
  99.     #开启一个输出日志的线程
  100.     a = threading.Thread(target=a.state)
  101.     a.start()




阅读(5187) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~
评论热议
请登录后评论。

登录 注册