python 爬虫(1):爬取 DDCTF-2018 参赛选手
程序员文章站
2022-05-12 13:54:49
...
简介
这几天闲来无事,突然想着学习一下 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 '终止爬取,退出程序...'
爬取结果
上一篇: 面试中的一道题
下一篇: 一道验证花括号匹配的编程题