本人习惯使用pyhton2进行编程,因此beautifulsoup也是使用python2版本的,但据说python2明年就要停止支持了,忧伤得很。。。0x01 题目要求如图所示,在页面源码当中找到5个flag,然后拼接起来,还给了flagA的示例。flagA:打开站点是一个ctf-wiki的demo站点,了解这个站的人应该都知道它的体量,所以手动一个个找是不现实的,需要用到爬虫了(题目名称也暗示了)。0x02 解题思路我考虑使用广度优先搜索(BFS)实现一个网站爬虫,不了解广度搜索的童鞋可以自行百度。具体实现方法如下:建立待请求链接visiting_urls和已请求链接visited_urls的2个列表(也可看做队列)从visiting_urls取出一条链接,使用requrests.get请求页面源码在源码中正则匹配flag字段beautifulsoup获取页面中所有的a标签,符合要求的加入visiting_urlsvisiting_urls不为空,则执行[2]当中需要考虑2个问题:去重问题:当爬取链接时,难免会遇到存在不同位置的url指向同一个页面,爬取时不需要再请求相同页面,因此要对爬取到的url进行去重。方法如下:维护visiting_urls visited_urls列表,比对爬取url与已爬取过的url是否重复;根据mkdocs网站url特点,包含"../“的是回溯链接,此类链接不需要再次请求。正则匹配问题:这个方面没有多想,写个能使用的正则匹配规则就行,在本题中需要2种正则匹配:匹配flag:flag[ABCDE],我的目的是匹配到flag的标志,而不是把flag整个都匹配出来,因为我不清楚flag当中有没有其他奇怪字符,防止出现漏匹配的情况;匹配url:[\w/]+index.html,目的是匹配路径为字母数字(不包含”..")且末尾是"index.html"的url。到此,整个任务就完成了。0x03 完整脚本#coding=utf-8import requests,refrom bs4 import BeautifulSoups = requests.session()s.keep_alive=Falseflagre = re.compile(‘flag[ABCDE]’)urlre = re.compile(’[\w/]+index.html’)base_url = ‘http://23.236.125.55:1000/ctf-wiki/‘flagA_url = ‘http://23.236.125.55:1000/ctf-wiki/assembly/mips/readme/index.html’visiting_urls = [‘http://23.236.125.55:1000/ctf-wiki/index.html’]visited_urls = []def find_flag(url,html): flist = flagre.findall(html) if len(flist) > 0: print flist,urldef BFS(): url = visiting_urls[0] del(visiting_urls[0]) visited_urls.append(url) r = s.get(url) #r.encoding = ‘utf-8’ find_flag(url,r.text) soup = BeautifulSoup(r.text,’lxml’) for a in soup.find_all(‘a’): link = a[‘href’] if urlre.findall(link) and “..” not in link: new_url = base_url + link if new_url not in visited_urls and new_url not in visiting_urls: visiting_urls.append(new_url)if name == ‘main’: while len(visiting_urls) > 0: BFS()上面思路已经提到了,该脚本只能提取到包含flag标志的页面,而不是flag本身,因此还需要手动访问这些页面去寻找flag(手动狗头),如果还想直接显示flag,那就需要优化一下正则匹配了。提示一点,在获取到页面源码后,使用r.encoding = ‘utf-8’转码会导致EOFError,具体原因不详,本想能够匹配中文页面,结果画蛇添足搞了半天以为匹配没成功。提示两点,requests.session()的好处,相较于直接requests.get(),可以防止建立过多的HTTP连接,导致新连接无法建立的问题。参考页面:https://segmentfault.com/q/10…执行效果如下:最后拼接一下,完事了。