域名遍历搜索python实现
来源:互联网 发布:ubuntu 安装sqlserver 编辑:程序博客网 时间:2024/05/17 06:33
前记——
其实我的第一篇博客就是写如何获取给定网址的信息,也有那家公司的面试题。
最近一个星期想把那个面试题中的程序研究透彻..
毕竟既然有可以参考的大公司的大神的代码,肯底要学习一番嘛,(师夷长技以制夷..不对,额反正就大概是这个意思啦)
正文——
程序的功能很简单,就遍历可能的域名组合,每个地址都访问一次,获取它的标题。
功能是很简单,但是网址数一旦多就变得很麻烦。
实现的方式是采用生产者——消费者模式。定义两个类,一个用于产生网址,另外一个用于判断网址。
具体使用到的技术:
1:产生地址是采用yield生成器,以便后续的程序改进。
2:判断地址的步骤分为五步。1:开启判断地址的多进程(默认为6个)
2:每个进程开启一定数目的协程(默认50个)
3:在进程安全的队列中取出网址,并初始化dns模块,以dns模块首先判断网址是否可以解析。
4:再使用urllib模块的urlopen方法判断访问网址的状态码。
5:采用urllib2模块获取网页的正文。
6:使用beautifulsoup处理html文本,获取标题。
简单的大致流程就是这样。
以下是代码:
# coding=utf-8import dnsimport syssys.setrecursionlimit(10000)import stringimport urllibimport urllib2import multiprocessingfrom multiprocessing import Queuefrom multiprocessing import RLockimport geventfrom gevent import monkeyimport MySQLdbimport dns.resolverfrom bs4 import BeautifulSoup# 一定不能让猴子补丁覆盖掉线程thread类,不然程序不会运行。参考 http://xiaorui.cc/2016/04/27/%e6%ba%90%e7%a0%81%e5%88%86%e6%9e%90%e4%b9%8bgevent-monkey-patch_all%e5%ae%9e%e7%8e%b0%e5%8e%9f%e7%90%86/monkey.patch_all(thread=False)#socket.setdefaulttimeout(8)domainqueue = Queue()Message = Queue()Mesdict = {}usefulIp = Queue()uselessIP = Queue()class subsearch(object): def __init__(self): self.set = set() net = self._creatdomain() for i in range(100000): a = net.next() self.set.add('www.' + a + '.com') for i in self.set: domainqueue.put_nowait(i) def _creatdomain(self): ergodicword = ['', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'] for word in string.lowercase: ergodicword.append(word) # 生成26个英文字母并添加进去 for i in ergodicword: for j in ergodicword: for k in ergodicword: for l in ergodicword: for m in ergodicword: yield i + j + k + l + mclass subvisit(object): def __init__(self, DNSSERVER, headers): self.dnsserver = DNSSERVER self.run() self.headers = headers def start(self, i): self.id = i self.work() def work(self): resolver1 = dns.resolver.Resolver() resolver1.lifetime = resolver1.timeout = 5.0 resolver1.nameservers = [self.dnsserver] A = '' while not domainqueue.empty(): try: url = domainqueue.get() except BaseException: break try: A = resolver1.query(url) except dns.resolver.NXDOMAIN as xxx_todo_changeme: dns.resolver.Timeout = xxx_todo_changeme continue except dns.exception.DNSException: continue if A: headers['Host'] = url try: codenum = urllib.urlopen('http://' + url).getcode() if codenum == 200 or codenum == 304: pass else: continue req = urllib2.Request('http://' + url, headers=headers) res = urllib2.urlopen( req, timeout=10) # urllib2的get方法访问url response = res.read() # 获取正文 res.close() del res soup = BeautifulSoup(response) title = soup.title except Exception as e: #title = "Not Found" continue if title: title = str(title)[7:-8] lock.acquire() print str(url).ljust(13),str(A[0].address).ljust(15),title lock.release() #Message.put_nowait((url, A[0].address,title)) # usefulIp.put_nowait(url) def run(self): try: threads = [gevent.spawn(self.start, i) for i in range(50)] gevent.joinall(threads) except KeyboardInterrupt as e: passif __name__ == '__main__': lock = RLock() DnsServer = ['114.114.114.114', '114.114.115.115', '223.5.5.5', '223.6.6.6', '112.124.47.27', '114.215.126.16'] headers = { 'Host': '', 'User-Agent': 'Mozilla / 5.0(X11;Ubuntu;Linuxx86_64;rv:55.0) Gecko / 20100101Firefox / 55.0', 'Accept': 'text / html, application / xhtml + xml, application / xml;q = 0.9, * / *;q = 0.8', 'Accept-Language': 'zh - CN, zh;q = 0.8, en - US;q = 0.5, en;q = 0.3', 'Accept-Encoding': 'gzip, deflate, br', 'Connection': 'keep - alive', } b = subsearch() pool = multiprocessing.Pool(processes=6) result = [] for i in xrange(6): result.append(pool.apply_async(subvisit, args=(DnsServer[i], headers))) pool.close() pool.join()
可以改进的部分:
1:把成功获取的数据存入到数据库,或者写入文件。需要注意的是获取到的标题有可能是韩文、日文、阿拉伯文等等,主要文本处理。
2:采用optparse模块。不要使用ide编写(特别是pycharm)太占用内存了(分分钟内存80以上)
3:有些网址可以访问,可是没有标题。在这里我的处理是把它剔除,但其实beautifulsoup的处理能力很强,我只略懂皮毛,或许可以获取网页的小标题代替主标题。
4:dns模块的处理可以更优化。在这里我是每一个进程采用一个dns解析器,但其实这样风险挺大,一旦一个解析器出现问题,整个进程所有协程都讲停工。
5:程序有时会卡在urllib2.read()上面,这个问题烦扰我两天还是解决不了。(网上的解决方案是采用超时的办法,但其实好像..没什么用..),我觉得这个问题的出现有两种可能,一是在访问的时候确实没有超时,只是在read()下载文档的时候速度过慢,导致程序都在等待,而不会抛出异常;二就是read()的时候由于协程也都在工作,在处理gerrnlet.lock()程序内部出现阻塞或死锁(虽然是协程,好像源码也有lock(),但就算如此为什么不抛出异常?..)
下面是程序运行的截图:
还是要打码的...
网站遍历的速度会与网速有挺大的关系。(可惜校园网比较渣,每次测试的速度都有较大程度的不同)
半个小时检索出2000个有标题的网址(按照测试的经验,大概判断的域名与可使用的域名比例是15比1,即半小时判断30000个,速度还是比较慢)
我会尝试不同的协程数目以及优化代码尝试改进。
在这里很感谢大公司的代码,对我来说是宝贵的学习资料。
阅读全文
0 0
- 域名遍历搜索python实现
- web信息搜索之域名遍历篇
- Python实现遍历url
- python学习笔记之os.walk()实现遍历文件搜索字符串
- Python 实现IP动态绑定pubyun 域名
- 使用python实现IP反查域名
- python实现文件比较,匹配域名
- Python实现深度遍历和广度遍历
- python 树的遍历实现
- Python实现文件递归遍历
- python实现二叉树遍历
- 用python实现本地文件搜索
- Python实现文件内容搜索
- 二叉搜索树 python实现
- 【图的实现】“广度优先搜索遍历”以及“深度优先搜索遍历”必会
- 用Python遍历文件并搜索文件内容
- Python遍历目录和搜索文件中的关键字
- 【Python排序搜索基本算法】之二叉树的遍历
- 第9周 指针练习:MyMax
- 二路归并排序
- Codeforces Round #433 D
- 如何自建网站(2)
- .net分布式压力测试工具(Beetle.DT)
- 域名遍历搜索python实现
- 比较全面的druid配置信息
- [转]Cassnadra3.X 特性概述
- chown -R 用户名:组名 ./ 及 chown用法介绍
- 判断文件是否为图片
- 网络安全学习笔记
- JAVA-Struts2防止表单重复提交
- MYSQL性能优化
- 【备忘】2017最新传智播客黑马java 32期基础就业班视频教程