Python クローラー経由で ctftime の ctf ゲーム時間を取得します (詳細 + ソース コード)

結果を見る


ソースコードは一番下にありますが、本当に Python クローラーを学びたい人や、私のアイデアを理解したい人は、私の詳細な解釈を辛抱強く読んでいただければ幸いです。そうしないと、これらのコードはこれから始めよとしているゲームに属さないことになります。
ここに画像の説明を挿入

ここに画像の説明を挿入

生産工程

クロールのアイデア

まず、ctftime
ここに画像の説明を挿入
で囲まれた場所にアクセスすると、開催中の ctf コンペティションと今後の ctf コンペティションの情報が表示され、
ホームページには該当するコンペティションの URL は表示されず、コンペティション名とコンペティション時間だけが表示されていることがわかります
ここに画像の説明を挿入
。詳細を知るための Web サイト
ここに画像の説明を挿入
Web ページには欲しい情報がすべてあり、詳細な Web サイトをそれぞれ巡回することで情報を入手できます。
ついに見つけた法則、各詳細ウェブサイトは以下の方法で構成されています

https://ctftime.org/event/XXXX

そして、xxx​​x はホームページ上で閲覧できるので
ここに画像の説明を挿入
、私の考えは明確です。まずホームページ上で対応する 4 桁の番号までクロールし、次に新しい URL をつなぎ合わせ、その新しい URL をクロールして情報を取得します。

進行中のゲーム

ここに画像の説明を挿入
選んでいるときに気づきました

<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%')

ここに画像の説明を挿入
最初に 4 桁の情報を取得できたことがわかりますが、さらに位置を絞り込む必要があります。4
ここに画像の説明を挿入
桁の情報が 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)

ここに画像の説明を挿入
最小のタグが抽出され、冗長なコンテンツが除外されます。すべて冗長であるため、置換によって直接フィルタリングできます。

                    today_a_str = str(today_a)
                    today_url = re.sub('<a href="/event/|" style="color: #000000">|<img alt="Jeopardy" border="0" rel="tooltip" src="/static/images/ct/1.png" title="Jeopardy"/></a>|\n', '', today_a_str)

ここに画像の説明を挿入

今後のゲーム

ここに画像の説明を挿入
私たちが選択するとき

<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')

ここに画像の説明を挿入
4 桁の情報はラベルの下にあり、それをさらに読んでいきます。

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

ここに画像の説明を挿入
冗長なコンテンツをフィルタリングします。ここでは均一ではないため、以前は最初の 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('<a href="/event/', '', come4)

ここに画像の説明を挿入
ここに画像の説明を挿入

詳細な Web サイトをクロールする

まず URL を結合します

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

ここに画像の説明を挿入
次に、競合の詳細 Web サイトを分析します。

ゲーム名 ゲーム
の名前は難しいものではなく、単なる短答式の読み取りフィルターです

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('<h2>|<i class="icon-play-circle" id="progress" rel="tooltip"></i></h2>|</h2>', '',str(name)) # 比赛名称
        return final_name
    except:
        print("比赛名称获取失败")

ここに画像の説明を挿入
ゲーム時間
ここでの難点は、取得される情報が一様ではなく、直接フィルタリングできないことですが、違いは 4 桁の数値なので、同時に 4 桁の数値を関数にインポートできます。
ここに画像の説明を挿入
ここに画像の説明を挿入

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('<p>|<a href="/event/|.ics|" id="calendar" rel="tooltip">|<img class="svg_icon" id="icon_calendar" src="/static/img/icon_cal.svg"/>|</a>|</p>|\xa0|\n', '', time_str)
        final_time = re.sub(num, '', final_time) # 比赛时间
        return final_time
    except:
        print("比赛时间获取失败")

ここに画像の説明を挿入
コンテスト サイト
ここでの 1 つのポイントは、フィルタリング後に 2 つの同一のサイトが存在することです。

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('<a href="|" rel="nofollow">|</a>|\n', '', str(url))

ここに画像の説明を挿入
ここでは半分を取得する方法を使用できます。半分を取得する長さは 2 つのリンク文字の長さの半分です。

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

ここに画像の説明を挿入

完全なコード

'''
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('<a href="/event/|" style="color: #000000">|<img alt="Jeopardy" border="0" rel="tooltip" src="/static/images/ct/1.png" title="Jeopardy"/></a>|\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('<a href="/event/', '', 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('<h2>|<i class="icon-play-circle" id="progress" rel="tooltip"></i></h2>|</h2>', '',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('<p>|<a href="/event/|.ics|" id="calendar" rel="tooltip">|<img class="svg_icon" id="icon_calendar" src="/static/img/icon_cal.svg"/>|</a>|</p>|\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('<a href="|" rel="nofollow">|</a>|\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) # 即将举行的比赛

おすすめ

転載: blog.csdn.net/weixin_46706771/article/details/119973505