上一次任务:
cms版本识别提取模块
从phpmyadmin的若干版本源码包中,找出一个路径(包括文件名),该路径大多数源码包中都包含,并且md5值不一样,寻找的文件类型为css或js
程序输出:
{
"url": "/test/test.css",
"data": {
"xxxversion": "32位md5",
"yyyversion": "32位md5"
}
}
phpmyadmin查看了一下,共更新了几百个版本。
手动下载不现实,在Linux系统中使用wget -i filename.txt 可实现。
那么就需要将所有版本的下载链接保存到filename.txt文件中。
1、使用爬虫进行链接的获取
由于phpmyadmin软件源代码在每个网页中只有10个版本需要点击Next跳转到下一页,那么就需要找到该网页中的下一页的链接,即递归爬取。可以使用Beautiful Soup, 是一个处理Python HTML/XML的模块,功能相当强劲。
Beautiful Soup是一个库,最主要的功能是从网页抓取数据。
下载及安装:https://blog.csdn.net/a_flying_bird/article/details/51088485
代码实现:
import re
from urllib.request import urlopen, urlretrieve
from bs4 import BeautifulSoup
zip_net_list=[]
# 下载HTML
def getHtml(url):
page = urlopen(url)
html = page.read()
return html
# 从html中解析URL
def get(html):
reg = r'href="(.*?\.zip)"'
netre = re.compile(reg)
htmld = html.decode('utf-8')
netlist = netre.findall(htmld)
return netlist
def find_file(url):
# url = 'https://github.com/phpmyadmin/phpmyadmin/tags?after=RELEASE_4_6_6'
html = getHtml(url)
netlist = get(html)
for neturl in netlist:
neturl1,neturl2=neturl.strip().split('/a')
neturl3,neturl4=neturl2.strip().split('/',1)
neturl5,neturl6=neturl4.strip().split('.z')
print('https://codeload.github.com'+neturl1+'/'+'zip/'+neturl5)
zip_net_list.append('https://codeload.github.com'+neturl1+'/'+'zip/'+neturl5)
return False
def crawl(url):
html = urlopen(url)
# print('--------------------------------')
find_file(url)
html = urlopen(url)
soup = BeautifulSoup(html, 'html.parser')
zzr = soup.find_all('div', class_="pagination")
list_net = []
for item in zzr:
list_tmp = item.find_all('a')
for a in list_tmp:
list_net.append(a.get('href'))
# print(list_net)
len_ = len(list)
if len(list_net)==1:
if len_>2 and list_net[0]==list[len_-2]:
return list
list.append(list_net[0])
crawl(list_net[0])
if len(list_net)==2:
# else:
list.append(list_net[1])
crawl(list_net[1])
url='https://github.com/phpmyadmin/phpmyadmin/tags'
list=[]
list.append(url)
crawl(url)
save_zip_net=open('phpmyadmin_net.txt','w')
for i in range(len(zip_net_list)):
save_zip_net.write('%s\n'%zip_net_list[i])
2、批量下载
wget -i phpmyadmin_net.txt
3、批量解压到相应的目录
ls * | xargs -n1 unzip -d 解压目录
到解压目录查看当前文件夹数量:
ls |wc -l
共有446个版本
4、计算MD5
find ./ -regextype posix-extended -regex ".*\.(css|js)" -exec md5sum {} \;>phpmyadmin_md5.txt
5、理解
任务要求:找出一个路径(包括文件名),该路径大多数源码包中都包含
上次理解错误以为要求所有版本中都含有相同路径的文件(即446个版本中都有相同路径的相同文件),其实在代码中加一个版本数量的遍历,起初是446表示446都含有相同路径的文件,如果没有,就减1,找445个版本中有相同路径的文件。。。,直到X个版本中找到了为止。接下来就要考虑该X版本中有多少个数量为X相同路径的文件,取出其中某个相同路径的MD5不同的数量最多的那个,可能不止一个。
6、代码整理
#对数据分割重组
import re
import os
import sys
#--------------创建all_file_merge.txt----V/P:MD5-----------
#所有版本内容合并: V/P:md5
all_file_to_list=[]
######*********######### 可修改
file_num_ = 446
# file_num = 15
filepath='phpmyadmin_md5.txt' ######*********######### 可修改
# filepath='new_file.txt'
file=open(filepath,'r')
count__=0
# print('初始长度:\n',len(file.readlines()))
for line in file.readlines():
key,value=line.strip().split('./')
all_file_to_list.append(value+':'+key) #value:versionpath key:md5
count__+=1
# print(count__)
# print(all_file_to_list) #all_file_merge.txt
#------------创建path_md5.txt---P:MD5------------
list_path_md5_list=[]
for li in all_file_to_list:
value, key=li.strip().split(':')
value=value[::-1]
match=re.match('.*/',value)
value=match.group()[::-1]
# dict[value]=key
list_path_md5_list.append(value+':'+key)
# print(list_path_md5_list) #path_md5.txt
#
# print('初始列表总长度:\n',len(list_path_md5_list))
#--------------创建version_md5.txt-V:MD5---------------
list_version_md5=[]
for li in all_file_to_list:
(key, value)=li.strip().split(':')
version,path=key.strip().split('/',1)
list_version_md5.append(version+':'+value)
# print(list_version_md5)
# print('success!')
#--------------------------------第2步:
#文件排序
# file=open('txt2/path_md5.txt','r') ######*********#########
#对path_md5排序:结果写入path_md5_sort.txt文件中
list_path_md5=[]
# for i in range(len(list_path_md5_dict)):
# for key,value in list_path_md5_dict[i].items():
# list_path_md5.append(key+':'+value)
for i in range(len(list_path_md5_list)):
list_path_md5.append(list_path_md5_list[i])
# for line in file.readlines():
# print(len(list))
list_path_md5.sort()#返回值是None,其表示是在原对象上进行的操作。返回排序后结果意味着创建了一个副本。
list_path_md5_sort=list_path_md5
# print(len(list_path_md5_sort))
# print('路径排序:\n',list_path_md5_sort)
#----------------------------------第三步:
#小心:在同一个文件中不能写读同一个文件,否则读会出错
#找到所有版本中共同的文件 路径相同
list_path=[]
for i in range(len(list_path_md5_sort)):
parh,md5=list_path_md5_sort[i].strip().split(':')
list_path.append(parh)
# print('路径总数:\n',len(list_path))#
# print('路径列表:\n',list_path)
# save_list_path=open('save_same_list_path.txt','w')
# for li in list_path:
# save_list_path.write('%s\n'%li)
#记录列表中相同路径的第一个序号:与源文件少1,是因为列表从0开始遍历而源文件是从1开始计数
list_path_record_num=[]
file_num=0
for num_p in range(446,0,-1):
# print(len(path_list))
for i in range(len(list_path)):
# print(i)
count = i + num_p - 1 # [i count]范围判断
if count<len(list_path) and list_path[i]==list_path[count] :
list_path_record_num.append(i)
# print(path_list[i])
# print(len(list_path_record_num))
if(len(list_path_record_num)!=0):
# print('所有版本中不存在与版本数量相同路径下的文件!')
# sys.exit()
file_num=num_p
break
# print('list_path_record_num:',list_path_record_num)
#
#-------------------第4步找出相同路径的文件的位置
# import find_16_samepath_file_3
# import all_file_to_merge_1
# find_file_=open(r'txt2/path_md5_sort.txt','r')
list_all_samefile_path=[]
num=0 # 列表中的序号
i=0 #第i位置
count=0 #计数,记到所有文件的数量时,归0
for j in list_path_md5_sort:
if num<len(list_path_record_num) and \
i>=list_path_record_num[num] and \
i<=list_path_record_num[num]+file_num-1:##############
list_all_samefile_path.append(j)
count+=1
# print(line)
if(count==file_num):#计数到16时,count归0,并且列表指向下一个元素#########修改
num+=1
count=0
i+=1
# print('获得文件数量:',len(list_path_record_num))
# print('存储的序号:\n',list_path_record_num)
#
# print('列表元素个数:',len(list_all_samefile_path))
#
#
# print('相同路径下的MD5:\n',list_all_samefile_path)
#
#
#
#-----------第5步从相同路径下的文件中找到不同的MD5
list_samepath_different_md5=[]
num=0
for i in range(len(list_all_samefile_path)):
# for j in range(16)
if i+1<len(list_all_samefile_path) and list_all_samefile_path[i]==list_all_samefile_path[i+1]:
continue
else:
list_samepath_different_md5.append(list_all_samefile_path[i])
# print('不相同路径下的MD5:\n',list_samepath_different_md5)
# find_different_md5=open('txt/find_different_md5.txt','w')
# for i in range(len(md5_list)):
# find_different_md5.write('%s'%md5_list[i])
# #------------------------------第6步:相同路径下的不同的MD5
#
#
# # file=open('txt/find_different_md5.txt','r')
#
list_samepath_path=[]
#读取文本中的内容将路径保存在list中方便后面统计相同路径的数目
for i in range(len(list_samepath_different_md5)):
path,md5_=list_samepath_different_md5[i].strip().split(':')
list_samepath_path.append(path)
# for line in file.readlines():
# key,value=line.strip().split(':')
# list.append(key)
# print(len(list_samepath_path))
# print('相同路径:',list_samepath_path)
count_=1 #记录相同路径数
count_different_md5_num=0
tmp=list_samepath_path[0]
list_different_md5_count=[]
dict={} #保存路径--不同数量
#用list_num记录列表中相同路径下的MD5不同的数量,并且将路径+数量保存到zid中
for i in range(1,len(list_samepath_path)):
if(list_samepath_path[i]==tmp):
count_+=1
else:
list_different_md5_count.append(count_)
dict[tmp]=count_
tmp=list_samepath_path[i]
count_=1
list_different_md5_count.append(count_)
dict[tmp] = count_
# print('输出不同MD5:',list_different_md5_count)#输出不同MD5
#
# print('输出不同MD5的总数:',len(list_different_md5_count))#输出不同MD5的总数
# print(dict)
# for (key,value) in dict.items():
# print(key,value)
# count_different_md5_num+=1
# print(count_different_md5_num)
# 找到列表中的最大值,并判断最大值个数
if len(list_different_md5_count)==1:
max_different_md5_count=list_different_md5_count[0]
else:
max_different_md5_count=max(list_different_md5_count)
# print('列表中的最大值',max_different_md5_count)
# count_max=0
# for i in range(len(list_num)):
# if(list_num[i]==max(list_num)):
# count_max+=1
# 找到最大的数(MD5不同),将对应的路径及MD5以key,value形式保存在字典中
dict_result={}
for path,num in dict.items():
if(num==max(list_different_md5_count)):
dict_result[path]=num
# print("fined the result:")
#输出满足要求的路径及对应的不同的MD5的数量
# for path,num in dict_result.items():
# print(path,num)
# dict_to_list=list(dict_result)
#将记录的路径保存在列表中
list_find_final_path=[]
for path,num in dict_result.items():
list_find_final_path.append(path)
# print(list_path)
## 找到满足要求的不同路径的数量
need_file_num=len(list_find_final_path)
# print(need_file_num)
#---------------第7步找到相同路径下不同的MD5
find_next_num=0
max_different_md5_count_=0
list_find_final_samepath_different_md5=[]
# 从所有的相同路径不同MD5文件中遍历
for i in range(len(list_samepath_different_md5)):
# print(line)
path,md5__=list_samepath_different_md5[i].strip().split(':')
# print(key)
#相同路径下含有最多不同的MD5的内容
if find_next_num<len(list_find_final_path) and (path==list_find_final_path[find_next_num]):
list_find_final_samepath_different_md5.append(list_samepath_different_md5[i])
max_different_md5_count+=1
#当计数到同文件下不同MD5的最大数量时,num++即遍历列表中的下一个保存路径
if max_different_md5_count_==max_different_md5_count:
find_next_num+=1
# print(list_find_final_samepath_different_md5)
# # 将找到的内容保存起来
# P_M=open('find_final_path_md5.txt','w')
# for i in range(len(list_find_final_samepath_different_md5)):
# P_M.write('%s\n'%list_find_final_samepath_different_md5[i].strip())
#-----------------------第8步 找到相同路径下不同的MD5
list_result=[]
# 用MD5来找对应的版本,然后将version+path+md5保存到列表中
for i in range(len(list_version_md5)):
version,md51=list_version_md5[i].strip().split(':')
for j in range(len(list_find_final_samepath_different_md5)):
path,md5_1=list_find_final_samepath_different_md5[j].strip().split(':')
if md51==md5_1:
list_result.append(version+list_find_final_samepath_different_md5[j])
# 将version+path+文本中md5写入
final_result=open('find_final_version_path_md5.txt','w')
for i in range(len(list_result)):
final_result.write('%s\n'%list_result[i].strip())
# print(len(list_result))
# print(list_result)
#
#-----------------第9步格式化输出
# import samepath_file_different_md5_6
# file=open('txt/final_result.txt','r')
#
# #list中保存了16*samepath_file_different_md5_6.need_file_num个文件
# list=[]
# for line in file.readlines():
# list.append(line)
# print(len(list))
print('\n打印出结果:')
list_result.sort()
for i in range(len(list_result)):
print(list_result[i].strip())
save_final_output=open('final_output.txt','w')
num=0
print('output_result:')
#一般性,可能含有多个相同的最大的MD5数量
# 遍历有可能多个MD5的不同数量即符合要求多于1个其数量为samepath_file_different_md5_6.need_file_num
for i in range(need_file_num):
key,value=list_result[num].strip().split(':')#分割version_path:MD5,初始标志
print('{')
save_final_output.write('{\n')
print(' url:',path)
save_final_output.write(' url:%s\n'%path)
print(' {\n data:\n {')
save_final_output.write(' {\n data:\n {\n')
for j in range(num+1,(i+1)*file_num):#
key1,value1=list_result[j].strip().split(':')
if(value==value1):#与前一个MD5对比,相同跳过
continue
else:
version,mad5=key.strip().split('/',1)#MD5不同,记录初始位置的V_M
print(' ',version,':',value)
save_final_output.write(' %s:%s\n'%(version,value))
key,value=key1,value1 #更新比较的值
num = num+file_num
key2,value2=list_result[num-1].strip().split(':')#最后一个
version_, mad5_= key2.strip().split('/', 1)
print(' ',version_, ':', value)
save_final_output.write(' %s:%s\n' % (version_, value))
print(' }')
save_final_output.write(' }\n')
print(' }')
save_final_output.write(' }\n')
# print(samepath_file_different_md5_6.max_list_num)
# #特殊性:只有一个最大的MD5数量
# key,value=list[0].strip().split(':')
# print('{')
# # vp,md5=key.strip().split(':')
# v,p=key.strip().split('/',1)
# print('url:',p)
# print('{\n data:\n {')
# for j in range(1,len(list)):
# key1,value1=list[j].strip().split(':')
# if(value==value1):
# continue
# else:
# version,mad5_=key.strip().split('/',1)
# print(' ',version,':',value)
# key,value=key1,value1
#
# key1,value1=list[len(list)-1].strip().split(':')
# version, mad5= key1.strip().split('/', 1)
# print(' ',version, ':', value)
# print(' }')
print('}')
save_final_output.write('}\n')
修改code:
#对数据分割重组
import re
import os
import sys
#--------------创建all_file_merge.txt----V/P:MD5-----------
#所有版本内容合并: V/P:md5
all_file_to_list=[]
######*********######### 可修改
file_num_ = 446
filepath='phpmyadmin_md5.txt' ######*********######### 可修改
file=open(filepath,'r')
count__=0
for line in file.readlines():
key,value=line.strip().split('./')
all_file_to_list.append(value+':'+key) #value:versionpath key:md5
count__+=1
#------------创建path_md5.txt---P:MD5------------
list_path_md5_list=[]
for li in all_file_to_list:
value, key=li.strip().split(':')
value=value[::-1]
match=re.match('.*/',value)
value=match.group()[::-1]
# dict[value]=key
list_path_md5_list.append(value+':'+key)
#--------------创建version_md5.txt-V:MD5---------------
list_version_md5=[]
for li in all_file_to_list:
(key, value)=li.strip().split(':')
version,path=key.strip().split('/',1)
list_version_md5.append(version+':'+value)
#--------------------------------第2步:
list_path_md5=[]
for i in range(len(list_path_md5_list)):
list_path_md5.append(list_path_md5_list[i])
list_path_md5.sort()#返回值是None,其表示是在原对象上进行的操作。返回排序后结果意味着创建了一个副本。
list_path_md5_sort=list_path_md5
#----------------------------------第三步:
list_path=[]
for i in range(len(list_path_md5_sort)):
parh,md5=list_path_md5_sort[i].strip().split(':')
list_path.append(parh)
#记录列表中相同路径的第一个序号:与源文件少1,是因为列表从0开始遍历而源文件是从1开始计数
list_path_record_num=[]
file_num=0
for num_p in range(446,0,-1):
# print(len(path_list))
for i in range(len(list_path)):
# print(i)
count = i + num_p - 1 # [i count]范围判断
if count<len(list_path) and list_path[i]==list_path[count] :
list_path_record_num.append(i)
if(len(list_path_record_num)!=0):
# print('所有版本中不存在与版本数量相同路径下的文件!')
# sys.exit()
file_num=num_p
break
#-------------------第4步找出相同路径的文件的位置
list_all_samefile_path=[]
num=0 # 列表中的序号
i=0 #第i位置
count=0 #计数,记到所有文件的数量时,归0
for j in list_path_md5_sort:
if num<len(list_path_record_num) and \
i>=list_path_record_num[num] and \
i<=list_path_record_num[num]+file_num-1:##############
list_all_samefile_path.append(j)
count+=1
# print(line)
if(count==file_num):#计数到16时,count归0,并且列表指向下一个元素#########修改
num+=1
count=0
i+=1
#-----------第5步从相同路径下的文件中找到不同的MD5
list_samepath_different_md5=[]
num=0
for i in range(len(list_all_samefile_path)):
# for j in range(16)
if i+1<len(list_all_samefile_path) and list_all_samefile_path[i]==list_all_samefile_path[i+1]:
continue
else:
list_samepath_different_md5.append(list_all_samefile_path[i])
#
list_samepath_path=[]
#读取文本中的内容将路径保存在list中方便后面统计相同路径的数目
for i in range(len(list_samepath_different_md5)):
path,md5_=list_samepath_different_md5[i].strip().split(':')
list_samepath_path.append(path)
count_=1 #记录相同路径数
count_different_md5_num=0
tmp=list_samepath_path[0]
list_different_md5_count=[]
dict={} #保存路径--不同数量
#用list_num记录列表中相同路径下的MD5不同的数量,并且将路径+数量保存到zid中
for i in range(1,len(list_samepath_path)):
if(list_samepath_path[i]==tmp):
count_+=1
else:
list_different_md5_count.append(count_)
dict[tmp]=count_
tmp=list_samepath_path[i]
count_=1
list_different_md5_count.append(count_)
dict[tmp] = count_
# 找到列表中的最大值,并判断最大值个数
if len(list_different_md5_count)==1:
max_different_md5_count=list_different_md5_count[0]
else:
max_different_md5_count=max(list_different_md5_count)
# 找到最大的数(MD5不同),将对应的路径及MD5以key,value形式保存在字典中
dict_result={}
for path,num in dict.items():
if(num==max(list_different_md5_count)):
dict_result[path]=num
#将记录的路径保存在列表中
list_find_final_path=[]
for path,num in dict_result.items():
list_find_final_path.append(path)
# print(list_path)
## 找到满足要求的不同路径的数量
need_file_num=len(list_find_final_path)
# print(need_file_num)
#---------------第7步找到相同路径下不同的MD5
find_next_num=0
max_different_md5_count_=0
list_find_final_samepath_different_md5=[]
# 从所有的相同路径不同MD5文件中遍历
for i in range(len(list_samepath_different_md5)):
# print(line)
path,md5__=list_samepath_different_md5[i].strip().split(':')
# print(key)
#相同路径下含有最多不同的MD5的内容
if find_next_num<len(list_find_final_path) and (path==list_find_final_path[find_next_num]):
list_find_final_samepath_different_md5.append(list_samepath_different_md5[i])
max_different_md5_count+=1
#当计数到同文件下不同MD5的最大数量时,num++即遍历列表中的下一个保存路径
if max_different_md5_count_==max_different_md5_count:
find_next_num+=1
#-----------------------第8步 找到相同路径下不同的MD5
list_result=[]
# 用MD5来找对应的版本,然后将version+path+md5保存到列表中
for i in range(len(list_version_md5)):
version,md51=list_version_md5[i].strip().split(':')
for j in range(len(list_find_final_samepath_different_md5)):
path,md5_1=list_find_final_samepath_different_md5[j].strip().split(':')
if md51==md5_1:
list_result.append(version+list_find_final_samepath_different_md5[j])
# 将version+path+文本中md5写入
final_result=open('find_final_version_path_md5_1.txt','w')
for i in range(len(list_result)):
final_result.write('%s\n'%list_result[i].strip())
#
#-----------------第9步格式化输出
print('\n打印出结果:')
list_result.sort()
for i in range(len(list_result)):
print(list_result[i].strip())
save_final_output=open('final_output_1.txt','w')
num=0
print('output_result:')
#一般性,可能含有多个相同的最大的MD5数量
# 遍历有可能多个MD5的不同数量即符合要求多于1个其数量为samepath_file_different_md5_6.need_file_num
for i in range(need_file_num):
key,value=list_result[num].strip().split(':')#分割version_path:MD5,初始标志
print('{')
save_final_output.write('{\n')
print(' url:',path)
save_final_output.write(' url:%s\n'%path)
print(' {\n data:\n {')
save_final_output.write(' {\n data:\n {\n')
for j in range(num+1,(i+1)*file_num):#
key1,value1=list_result[j].strip().split(':')
# if(value==value1):#与前一个MD5对比,相同跳过
# continue
# else:
version,mad5=key.strip().split('/',1)#MD5不同,记录初始位置的V_M
print(' ',version,':',value)
save_final_output.write(' %s:%s\n'%(version,value))
key,value=key1,value1 #更新比较的值
num = num+file_num
key2,value2=list_result[num-1].strip().split(':')#最后一个
version_, mad5_= key2.strip().split('/', 1)
print(' ',version_, ':', value)
save_final_output.write(' %s:%s\n' % (version_, value))
print(' }')
save_final_output.write(' }\n')
print(' }')
save_final_output.write(' }\n')
print('}')
save_final_output.write('}\n')