python 爬虫(1):爬取 DDCTF-2018 参赛选手

简介

这几天闲来无事,突然想着学习一下 python 爬虫,也可以用来练习一下 python。刚好这两天报名参加了 DDCTF-2018 比赛,在比赛官网的挑战者页面可以看到参赛者,不如就爬取一下所有的参赛者信息吧。

平时用 python 不多,这也是我第一次写 python 爬虫,难免有不足的地方,以后继续进步。本文使用了 urlib2 + Beautiful soup,同时使用 xlsxwriter 将获取到的参赛者信息保存 excel 表格中,希望对一些 python 爬虫入门的朋友有一点帮助。

分析

打开官网的挑战者页面,如下:

挑战者页面

可见每个参赛者都列出了昵称、大学以及年级三项信息,这个表格的源代码如下:

<table class="table table-striped table-bordered">
                <thead>
                    <tr>
                        <td><b>昵称</b></td>
                        <td class="d-none d-md-table-cell d-lg-table-cell"><b>大学</b></td>
                        <td class="d-none d-md-table-cell d-lg-table-cell"><b>年级</b></td>
                    </tr>
                </thead>
                <tbody>

                    <tr>
                        <td>

                            <a href="/team/84">HONKONE</a>

                        </td>
                        <td class="d-none d-md-table-cell d-lg-table-cell">


                                <span>
                                    电子科技大学成都学院
                                </span>


                        </td>
                        <td class="d-none d-md-table-cell d-lg-table-cell">
                            <span>大四</span>
                        </td>
                    </tr>

                    ...
                    ...                 

                    <tr>
                        <td>

                            <a href="/team/152">十九岁</a>

                        </td>
                        <td class="d-none d-md-table-cell d-lg-table-cell">


                                <span>
                                    宿州学院
                                </span>


                        </td>
                        <td class="d-none d-md-table-cell d-lg-table-cell">
                            <span>大一</span>
                        </td>
                    </tr>

                </tbody>
</table>

因此利用 Beautiful soup 获取到表格的每一个 <tr></tr> 标签,再获取其所有 Navigable String 即可。

但是这样仅仅获取到一个页面的参赛者信息,剩余的其它页面的参赛者信息怎么获取呢?观察页面 url 后发现,不同的参赛者页面的 url 的构造都是 http://ddctf.didichuxing.com/teams/ + page,page 的值为 1, 2, 3 …

同样分析发现,当页面表格仅仅有一行时,即一个 <tr></tr> 标签时,说明该页面没有参赛者,也即是已经爬取完所有参赛者了。由此可以终止爬取。

代码

# -*- coding: UTF-8 -*-

import urllib2
from bs4 import BeautifulSoup
import xlsxwriter
import os
import sys
reload(sys)
sys.setdefaultencoding('utf-8')


URL_BASE = 'http://ddctf.didichuxing.com/teams/'
ALL_CHALLENGER = []     # 存放所有选手信息


def save_to_xlsx():
    workbook = xlsxwriter.Workbook('DDCTF-2018-challengers.xlsx')
    worksheet = workbook.add_worksheet('first_sheet')

    title_format = workbook.add_format({'bold':True, 'font_size':18, 'bg_color':'cccccc'})
    worksheet.write_row('A1', ['昵称', '大学', '年级'], title_format)
    worksheet.set_column('A:A', 30)     # 设置A列列宽为 30
    worksheet.set_column('B:B', 20)
    worksheet.set_column('C:C', 40)

    row = 1
    for challenger in ALL_CHALLENGER:
        worksheet.write_row(row, 0, challenger)
        row += 1
    workbook.close()

    print '所有选手信息已保存至 ' + os.getcwd() + '\DDCTF-2018-challengers.xlsx'


def get_info(all_challengers):
    global ALL_CHALLENGER
    for challenger in all_challengers:
        if challenger.find('a'):    # 存在选手姓名
            strs = list(challenger.stripped_strings)
            if len(strs) == 3:
                ALL_CHALLENGER.append([strs[0], strs[2], strs[1].strip()])
            elif len(strs) == 2:    # 院校可以刻意构造为空,此时要特殊处理
                ALL_CHALLENGER.append([strs[0], strs[1], ''])


def spider(url):
    req = urllib2.Request(url)
    try:
        response = urllib2.urlopen(req)
    except urllib2.URLError, e:
        if hasattr(e, 'reason'):            # 页面加载错误,同样应该已经爬取完所有参赛者信息
            print '加载页面 ' + url + ' 失败,失败原因:' + e.reason
            return False
    soup = BeautifulSoup(response.read().decode('utf-8'), "html.parser")

    all_challengers = soup.find_all('tr')
    if len(all_challengers) <= 1:           # 页面没有任何参赛者,说明已经爬取完所有参赛者信息
        print '页面 ' + url + ' 无选手信息'
        return False
    get_info(all_challengers)

    print '成功抓取页面 ' + url + ' !'
    return True


if __name__=="__main__":
    page = 1
    while 1:
        if not spider(URL_BASE + str(page)):
            break
        page += 1

    save_to_xlsx()
    print '终止爬取,退出程序...'

爬取结果

运行结果

成果展示

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值