作为一个安全测试人员,面对一个大型网站的时候,手工测试很有可能测试不全,这时候就非常需要一个通用型的网站扫描器。当然能直接扫出漏洞的工具也有很多,但这样你只能算是一个工具使用者,对于安全测试你还远远不够。这时候应该怎么做呢?对于那些大量且重复性工作,尽量能用工具实现就用工具实现,然后打包成自己的工具包。如今天的这个url爬取工具。当我们把整站url都爬取出来之后,可以对url进行分析分类,然后有针对性的进行手工测试。
注:此方法只能爬取网页链接性的url,不能爬取js动态生成的url
#python3.5
#urlScan.py
#Author:FrankHacker
import requests
import re
def url_is_correct():
'''
使用requests.get方法判断url是否正确,并返回url
:return:
'''
try:
url = input("Please input the target test url:")
#url = "http://10.70.18.47:8080" 这是我内网环境的测试地址
requests.get(url)
return url
except:
print('please input the correct url!!!')
#exit(-1) #如果url是固定写入的,那么必须添加此句,否则会一直循环
return url_is_correct()
url = url_is_correct() #将验证为正确的url地址赋值给url
def url_protocol(url):
'''
获取输入的url地址的协议,是http、https等
'''
print('该站使用的协议是:' + re.findall(r'.*(?=://)',url)[0])
return re.findall(r'.*(?=://)',url)[0]
urlprotocol = url_protocol(url)
def same_url(url):
'''
处理用户输入的url,并为后续判断是否为一个站点的url做准备,爬取的时候不能爬到其它站,那么爬取将无止境
:return: sameurl
'''
#将完整的url中的http://删除
url = url.replace(urlprotocol + '://','')
#判断删除http://之后的url有没有www,如果没有就加上‘www.’,但不存储,
#只是为了同化所有将要处理的url,都有了‘www.’之后,
#就可以找以‘www.’开始的到第一个‘/’结束中的所有字符串作为该站的主域名
if re.findall(r'^www',url) == []:
sameurl = 'www.' + url
if sameurl.find('/') != -1:
sameurl = re.findall(r'(?<=www.).*?(?=/)', sameurl)[0]
else:
sameurl = sameurl + '/'
sameurl = re.findall(r'(?<=www.).*?(?=/)', sameurl)[0]
else:
if url.find('/') != -1:
sameurl = re.findall(r'(?<=www.).*?(?=/)', url)[0]
else:
sameurl = url + '/'
sameurl = re.findall(r'(?<=www.).*?(?=/)', sameurl)[0]
print('同站域名地址:' + sameurl)
return sameurl
domain_url = same_url(url)
'''
处理url的类,对已访问过的和未访问过的进行记录,待后续使用
'''
class linkQuence:
def __init__(self):
self.visited = [] #已访问过的url初始化列表
self.unvisited = [] #未访问过的url初始化列表
def getVisitedUrl(self): #获取已访问过的url
return self.visited
def getUnvisitedUrl(self): #获取未访问过的url
return self.unvisited
def addVisitedUrl(self,url): #添加已访问过的url
return self.visited.append(url)
def addUnvisitedUrl(self,url): #添加未访问过的url
if url != '' and url not in self.visited and url not in self.unvisited:
return self.unvisited.insert(0,url)
def removeVisited(self,url):
return self.visited.remove(url)
def popUnvisitedUrl(self): #从未访问过的url中取出一个url
try: #pop动作会报错终止操作,所以需要使用try进行异常处理
return self.unvisited.pop()
except:
return None
def unvisitedUrlEmpty(self): #判断未访问过列表是不是为空
return len(self.unvisited) == 0
class Spider():
'''
真正的爬取程序
'''
def __init__(self,url):
self.linkQuence = linkQuence() #引入linkQuence类
self.linkQuence.addUnvisitedUrl(url) #并将需要爬取的url添加进linkQuence对列中
self.current_deepth = 1 #设置爬取的深度
'''
这里需要注意:
爬取分为:***先深度后广度***和***先广度和后深度***
1、如果是先深度后广度,那么给定一个url,然后从其页面中的任意一个可用链接进行深度爬取,很可能无限至循环下去
(在处理不当的时候,但一般情况下大家都会处理的很好,无非是判断哪些url是已经爬取过的,哪些是新爬取到的url)
2、如果是先广度后深度,就是将一个url页面中的所有链接进行爬取,然后分类处理过滤
(在这种处理不当的时候也会出现无限循环的可能,但一般情况下大家都会处理的很好,无非是判断哪些url是已经爬取过的,哪些是新爬取到的url)
'''
def getPageLinks(self,url):
'''
获取页面中的所有链接
'''
pageSource = requests.get(url).text
pageLinks = re.findall(r'(?<=href=").*?(?=")|(?<=href=').*?(?=')',pageSource)
#self.page_links = self.page_links + pageLinks
#print(self.page_links)
for l in pageLinks:
print(url + '该页面的源码链接有:' + l)
#for l in self.page_links:
# print(url + '该页面的源码链接有:' + l)
#return self.page_links
return pageLinks
def processUrl(self,url):
'''
判断正确的链接及处理相对路径为正确的完整url
:return:
'''
true_url = []
for l in self.getPageLinks(url):
if re.findall(r'/',l):
if re.findall(r':',l):
true_url.append(l)
else:
true_url.append(urlprotocol + '://' + domain_url + l)
#print(trueUrl)
for l in true_url:
print(url + '该url页面源码中,有效url:' + l)
return true_url
def sameTargetUrl(self,url):
'''
判断是否为同一站点链接,防止爬出站外,然后导致无限尝试爬取
'''
same_target_url = []
for l in self.processUrl(url):
if re.findall(domain_url,l):
same_target_url.append(l)
#print(self.same_target_url)
for l in same_target_url:
print(url + '该url页面源码中属于同一域的url有:' + l)
return same_target_url
def unrepectUrl(self,url):
'''
删除重复url
'''
unrepect_url = []
for l in self.sameTargetUrl(url):
if l not in unrepect_url:
unrepect_url.append(l)
for l in unrepect_url:
print(url + '该url下不重复的url有——:' + l)
#print(self.unrepect_url)
return unrepect_url
def crawler(self,crawl_deepth=1):
'''
正式的爬取,并依据深度进行爬取层级控制
'''
while self.current_deepth <= crawl_deepth:
while not self.linkQuence.unvisitedUrlEmpty():
visitedUrl = self.linkQuence.popUnvisitedUrl()
#print(visitedUrl)
if visitedUrl is None or visitedUrl == '':
continue
#self.getPageLinks(visitedUrl)
links = self.unrepectUrl(visitedUrl)
self.linkQuence.addVisitedUrl(visitedUrl)
for link in links:
self.linkQuence.addUnvisitedUrl(link)
self.current_deepth += 1
print(self.linkQuence.visited)
return self.linkQuence.visited
if __name__ == '__main__':
spider = Spider(url)
spider.crawler(2)
神龙|纯净稳定代理IP免费测试>>>>>>>>天启|企业级代理IP免费测试>>>>>>>>IPIPGO|全球住宅代理IP免费测试