Spaghetti扫描器源码分析之爬虫模块

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/bnxf00000/article/details/78173512

      上一篇大致分析了Spaghetti的指纹识别部分,这篇来大致分析下它的爬虫部分。

      先来看下extractor目录下的urlextract.py:

 
 
class UrlExtract:
	@staticmethod
	def run(content):
		try:
			urls = re.findall(r'href=[\'"]?([^\'" >]+)|Allow: (\/.*)|Disallow: (\/.*)|<loc>(.+?)</loc>',content)
			return urls
		except Exception,e:
			pass

      这个文件定义的类主要是解析response返回中的url连接和固有文件robots.txt、sitemap.xml中的指定路径。

      forms.py中的源码主要集中在对表单的处理。表单处理用到了BeautifulSoup。

 
 
		try:
			params = zip(*[iter(params)]*2)
			data = urllib.unquote(urllib.urlencode(params))
			if method == []:
				method = ['get']
			method = method[0]
			if method.upper() == "GET":
				return data
		except Exception,e:
			pass

      上面的代码中那个zip和iter组合使用的技巧值得知晓,可以参照这里。后面的urlencode相当于对dict进行编码成url那种key=value&key=value的形式。其实只要是由两个元素组成元组队列也可以编码成功。

      下面,来分析爬虫的功能实现文件crawler.py。看下函数run的代码:

 
 
	def run(self):
		links_list = []
		try:
			for path in ('','robots.txt','sitemap.xml','spaghetti'):
				url = self.ucheck.path(self.url,path)
				resp = self.request.send(url,cookies=self.cookie)
				links = self.extract.run(resp.content)
				if links == None: link=[]
				forms = self.forms.run(resp.content,self.url)
				if forms == None: forms=[]
				links_list += links
				links_list += forms
			return self.get(self.parse(links_list))
		except Exception,e:
			pass

      这个函数主要是对制定的url,这个url就是目标地址,然后尝试找根目录下的robots.txt和sitemap.xml文件,形成一个需要爬取的url地址列表。

      看下get函数:

 
 
	def get(self,lista1):
		lista = []
		for i in lista1:
			if re.search('=',i,re.I):
				lista.append(i)
		return lista

      这个函数是寻找有等号的url,这个难道是为了后续XSS、SQL等的测试么?寻找有等号的url,相当于寻找key=value这样的url,也就是找有输入点的地方。

      看下parse函数,这里分几块来看:

 
 
		for link in links:
			for i in link:
				if i == '':
					pass
				else:
					if i not in flinks:
						tlinks.append(i)
		blacklist = ['.png', '.jpg', '.jpeg', '.mp3', '.mp4', '.avi', '.gif', '.svg','.pdf','.js','.zip','.css','.doc','mailto']
		for link in tlinks:
			for bl in blacklist:
				if bl in link:
					pblacklist.append(link)
		for link in tlinks:
			for bl in pblacklist:
				if bl == link:
					index = tlinks.index(bl)
					del tlinks[index]

      这一块主要是过滤掉一些图片、视频、css、js等资源链接。我咋觉得这块写的不好,作者的思路是先找到所以符合黑名单的链接,存到pblacklist里面,然后双循环遍历tlinks和pblacklist,剔除掉tlinks里面符合pblacklist的链接。可是在前面筛选pblacklist的时候,就可以直接剔除掉不符合要求的链接,没有必要再遍历一次。要是我来写的话,直接过滤掉包含黑名单的链接,开一个列表存符合要求的链接即可。

      继续看:

 
 
		for link in tlinks:
			if link.startswith('./'):
				link = link.split('.')[1]
			if link.startswith('http://')or link.startswith('https://'):
				if link not in dlinks:
					dlinks.append(link)
			elif link.startswith('www.'):
				link = 'http://'+link
				if link not in dlinks:
					dlinks.append(link)
			elif link.startswith('/'):
				link = self.ucheck.path(self.url,link)
				if link not in dlinks:
					dlinks.append(link)
			else:
				link = self.ucheck.path(self.url,link)
				if link not in dlinks:
					dlinks.append(link)
		for link in dlinks:
			if not link.startswith('http'):
				pass
			elif self.parser.host() not in link:
				pass
			elif link.startswith('http://http://') or link.startswith('https://http://'):
				link = 'http'+link.split('http')[2]
				complete.append(link)
			else:
				complete.append(link)
		for i in complete:
			i = urllib.unquote(i)
			i = i.replace('&amp;','&')
			if i not in deflinks:
				deflinks.append(i)
		return deflinks

      这一块就是拼接url了,让其成为一个符合标准的url链接。之前得到的url很多是相对地址或者是非目标主机的url,在这里都会被过滤掉。

      thread_run函数:

 
 
	def thread_run(self):
		links = self.run()
		links_list = []
		if '--crawler' in sys.argv:
			self.output.info('Starting deep crawler for %s'%self.parser.host())
			try:
				for link in links:
					resp = self.request.send(link,cookies=self.cookie)
					links_extract = self.extract.run(resp.content)
					if links_extract == None: links_extract=[]
					forms_extract = self.forms.run(resp.content,self.url)
					if forms_extract == None: forms_extract=[]
					links_list += links_extract
					links_list += forms_extract
				links_list = self.get(self.parse(links_list))
				links_list = links_list+links
				return links_list
			except Exception,e:
				pass
		return links

      可以看到就是组合上面几个函数,然后得到最终符合要求的链接。

      整体看,这个爬虫没有处理Ajax技术相关的动态页面。从源码上看,这个爬虫就爬取了第一层的链接。然后url去重也木有实现。

      大概就是这些了。

猜你喜欢

转载自blog.csdn.net/bnxf00000/article/details/78173512