通过python爬虫获取ctftime的ctf比赛时间(详解+源码)

查看结果

源码在最下面,但如果真正想要学习python爬虫或者想要了解我的思路的人,我希望可以耐心看完我的详细解读,不然这些代码永远不属于你
正在进行的比赛
通过python爬虫获取ctftime的ctf比赛时间(详解+源码)_第1张图片
即将开始的比赛
通过python爬虫获取ctftime的ctf比赛时间(详解+源码)_第2张图片

制作过程

爬取思路

首先我们访问ctftime
通过python爬虫获取ctftime的ctf比赛时间(详解+源码)_第3张图片
圈出的地方就是正在进行的ctf的比赛和即将进行的ctf比赛的信息
查看可以看到这个主页并没有给出相关比赛网址,只有比赛名称和比赛时间
通过python爬虫获取ctftime的ctf比赛时间(详解+源码)_第4张图片
访问一个网站看看
通过python爬虫获取ctftime的ctf比赛时间(详解+源码)_第5张图片
发现详细网页中有所有我们想要的信息,我们可以通过爬取每一个详细网站来获取信息。
最后找到了规律,每一个详细网站都是由下面的方式组成的

https://ctftime.org/event/XXXX

而xxxx则可以在首页中查看到
通过python爬虫获取ctftime的ctf比赛时间(详解+源码)_第6张图片
那么我的思路就清晰了,先在首页爬取到相应的四位数字,然后拼凑成新的url,并对新的url进行爬取,从而获得信息。

正在进行的比赛

通过python爬虫获取ctftime的ctf比赛时间(详解+源码)_第7张图片
我发现当我选中

<table width="100%">

时,我们的目标信息就都会被选中,那么我们就从这里下手

 headers = {
            'User-Agent': "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36"
        }
        r = requests.get(url, headers=headers)
        bs_url = BeautifulSoup(r.text, 'html.parser')
        ctf_today = bs_url.find_all('table', width='100%')

通过python爬虫获取ctftime的ctf比赛时间(详解+源码)_第8张图片
可以看到我们初步获取了四位数字信息,但是还需要我们进一步缩小定位
通过python爬虫获取ctftime的ctf比赛时间(详解+源码)_第9张图片
可以看到四位数字信息在td>a标签下,我们进行进一步读取

        for today1 in ctf_today:
            today_td = today1.find_all('td')
            for today2 in today_td:
                today_a = today2.find('a')
                if today_a:
                    print(today_a)

通过python爬虫获取ctftime的ctf比赛时间(详解+源码)_第10张图片
已经提取到最小标签,然后我们过滤掉多余的内容,由于都是重复的赘余,所以我们可以直接用替换的方式过滤

                    today_a_str = str(today_a)
                    today_url = re.sub('|Jeopardy|\n', '', today_a_str)

通过python爬虫获取ctftime的ctf比赛时间(详解+源码)_第11张图片

即将进行的比赛

通过python爬虫获取ctftime的ctf比赛时间(详解+源码)_第12张图片
当我们选中

<table class="table table-striped upcoming-events">

时,我们的目标信息就都会被选中

        url_event = "https://ctftime.org/event/"
        # ctf = {} # 写入字典用
        headers = {
            'User-Agent': "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36"
        }
        r = requests.get(url, headers=headers)
        bs_url = BeautifulSoup(r.text, 'html.parser')
        ctf_come = bs_url.find_all('table', class_='table table-striped upcoming-events')

通过python爬虫获取ctftime的ctf比赛时间(详解+源码)_第13张图片
四位数字信息在a标签下,我们进行进一步读取

        for come1 in ctf_come:
            come_tr = come1.find_all('a')
            for come2 in come_tr:
                print(come2)

通过python爬虫获取ctftime的ctf比赛时间(详解+源码)_第14张图片
过滤掉多余的内容,由于这里并不统一,我采用了读取前20位,然后在过滤掉开头的相同部分

        for come1 in ctf_come:
            come_tr = come1.find_all('a')
            for come2 in come_tr:
                come3 = str(come2)
                come4 = come3[0:20]
                come_url = re.sub(', '', come4)

通过python爬虫获取ctftime的ctf比赛时间(详解+源码)_第15张图片
通过python爬虫获取ctftime的ctf比赛时间(详解+源码)_第16张图片

爬取详细网站

首先拼接url

url_event = "https://ctftime.org/event/"
new_url = url_event + today_url

通过python爬虫获取ctftime的ctf比赛时间(详解+源码)_第17张图片
然后分析比赛详细网站

比赛名称
比赛名称没什么难度,就是简答的读取过滤

def get_name(url): # 获取比赛名称
    try:
        headers = {
            'User-Agent': "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36"
        }
        r = requests.get(url, headers=headers)
        bs_url = BeautifulSoup(r.text, 'html.parser')
        name = bs_url.find_all('h2')
        final_name = re.sub('

|

|'
, '',str(name)) # 比赛名称 return final_name except: print("比赛名称获取失败")

通过python爬虫获取ctftime的ctf比赛时间(详解+源码)_第18张图片
比赛时间
这里有一个难点就是获取的信息不统一,无法直接过滤,但是这个不同点就是那四位数字,所以我们可以同时在函数中导入四位数字
通过python爬虫获取ctftime的ctf比赛时间(详解+源码)_第19张图片
通过python爬虫获取ctftime的ctf比赛时间(详解+源码)_第20张图片

def get_time(url,num): # 获取比赛时间
    try:
        headers = {
            'User-Agent': "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36"
        }
        r = requests.get(url, headers=headers)
        bs_url = BeautifulSoup(r.text, 'html.parser')
        times = bs_url.find('div', class_='span10')
        time = times.find('p')
        time_str = str(time)
        final_time = re.sub('

||||

|\xa0|\n'
, '', time_str) final_time = re.sub(num, '', final_time) # 比赛时间 return final_time except: print("比赛时间获取失败")

通过python爬虫获取ctftime的ctf比赛时间(详解+源码)_第21张图片
比赛网站
这里有一个点就是在过滤后会有两个相同的网站

headers = {
            'User-Agent': "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36"
        }
        r = requests.get(url, headers=headers)
        bs_url = BeautifulSoup(r.text, 'html.parser')
        url = bs_url.find('a', rel='nofollow')
        final_url = re.sub('||\n', '', str(url))

通过python爬虫获取ctftime的ctf比赛时间(详解+源码)_第22张图片
这里我们可以用取半的方法,取半的长度就是两个链接字符长度和的一半

final_url = final_url[0:int(len(final_url) / 2)]

通过python爬虫获取ctftime的ctf比赛时间(详解+源码)_第23张图片

完整代码

'''
author:C1yas0
time:2021-8-28
'''
import requests
import re
from bs4 import BeautifulSoup

def get_ctftime_running(url):
    url_event = "https://ctftime.org/event/"
    # ctf = {} # 写入字典用
    try:
        headers = {
            'User-Agent': "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36"
        }
        r = requests.get(url, headers=headers)
        bs_url = BeautifulSoup(r.text, 'html.parser')
        ctf_today = bs_url.find_all('table', width='100%')
        for today1 in ctf_today:
            today_td = today1.find_all('td')
            for today2 in today_td:
                today_a = today2.find('a')
                if today_a:
                    # list = [] # 写入字典用
                    today_a_str = str(today_a)
                    today_url = re.sub('|Jeopardy|\n', '', today_a_str)
                    new_url = url_event + today_url
                    # list.append([get_time(new_url, today_url), get_url(new_url)]) # 写入字典用
                    # ctf[get_name(new_url)] = list # 写入字典用
                    print(get_name(new_url)+" "+get_time(new_url, today_url)+" " + get_url(new_url))
        # print(ctf) # 写入字典用
    except:
        print("请求失败")

def get_ctftime_upcoming(url):
    try:
        url_event = "https://ctftime.org/event/"
        # ctf = {} # 写入字典用
        headers = {
            'User-Agent': "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36"
        }
        r = requests.get(url, headers=headers)
        bs_url = BeautifulSoup(r.text, 'html.parser')
        ctf_come = bs_url.find_all('table', class_='table table-striped upcoming-events')
        for come1 in ctf_come:
            come_tr = come1.find_all('a')
            for come2 in come_tr:
                # list = [] # 写入字典用
                come3 = str(come2)
                come4 = come3[0:20]
                come_url = re.sub(', '', come4)
                new_url = url_event + come_url
                # list.append([get_time(new_url, come_url), get_url(new_url)]) # 写入字典用
                # ctf[get_name(new_url)] = list # 写入字典用
                print(get_name(new_url)+" "+get_time(new_url, come_url)+" "+get_url(new_url))
        # print(ctf) # 写入字典用
    except:
        print("请求失败")

def get_name(url): # 获取比赛名称
    try:
        headers = {
            'User-Agent': "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36"
        }
        r = requests.get(url, headers=headers)
        bs_url = BeautifulSoup(r.text, 'html.parser')
        name = bs_url.find_all('h2')
        final_name = re.sub('

|

|'
, '',str(name)) # 比赛名称 return final_name except: print("比赛名称获取失败") def get_time(url,num): # 获取比赛时间 try: headers = { 'User-Agent': "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36" } r = requests.get(url, headers=headers) bs_url = BeautifulSoup(r.text, 'html.parser') times = bs_url.find('div', class_='span10') time = times.find('p') time_str = str(time) final_time = re.sub('

||||

|\xa0|\n', '', time_str) final_time = re.sub(num, '', final_time) # 比赛时间 return final_time except: print("比赛时间获取失败") def get_url(url): # 获取比赛网址 try: headers = { 'User-Agent': "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36" } r = requests.get(url, headers=headers) bs_url = BeautifulSoup(r.text, 'html.parser') url = bs_url.find('a', rel='nofollow') final_url = re.sub('||\n', '', str(url)) final_url = final_url[0:int(len(final_url) / 2)] # 比赛网址 return final_url except: print("比赛时间获取失败") if __name__ == '__main__': url = "https://ctftime.org" # get_ctftime_running(url) # 正在举行的比赛 # get_ctftime_upcoming(url) # 即将举行的比赛

你可能感兴趣的:(python,爬虫,pycharm)