上一次我们拿学校的URP做了个小小的demo。。。。

其实我们还可以把每个学生的证件照爬下来做成一个证件照校花校草评比

另外也可以写一个物理实验自动选课。。。

但是出于多种原因,,还是绕开这些敏感话题。。

今天,我们来扒一下cf的题面! PS:本代码不是我原创

1. 必要的分析

1.1 页面的获取

一般情况CF的每一个 contest 是这样的:

对应的URL是:http://codeforces.com/contest/xxx

还有一个Complete problemset页面,它是这样的:

对应的URL是:http://codeforces.com/contest/xxx/problems

可以发现,每一个contest除了xxx不一样外,其他都一样。

这样,我们就可以通过修改xxx的内容,来决定爬取哪一场比赛的题面了。

1.2 src保存问题

要保存整个网站,除了html的文本内容外,还需要将页面中对应的其他资源一起保存下来。

这里,我们分两步来做

  • 第一步,将html页面的头部以及对应的资源事先保存下来,因为这些头部都是一样的
  • 第二步,每访问一个contest,就下载其中相应的资源文件,并保存到相应的目录。

1.3 一些扩展

保存为html并不是很方便查看,我们可以使用wkhtmltopdf将html转化为pdf。

脚本如下:

  1. if [ -d ./pdf ]; then
  2. :
  3. else
  4. mkdir -p pdf
  5. fi
  6. cd html
  7. for h in *.html;
  8. do
  9. wkhtmltopdf -q "$h" "../pdf/`echo "$h"|sed "s/\.html/\.pdf/"`"
  10. done

我们还可以写一个用于清理的脚本:

  1. rm -f contest/*
  2. rm -f html/*
  3. rm -f problem/*
  4. rm -f src/*

那么最后,我们拥有如下文件:

  • cachesheader.html是我们之间保存的一些共用文件
  • clear.shhtml2pdf.sh是我们写的脚本
  • crawl_html.py是我们的爬虫

2. 代码

  1. #coding=utf-8
  2. # 导入需要用到的模块
  3. import urllib2
  4. import re
  5. import os
  6. import sys
  7. import threading
  8. import HTMLParser
  9. # 抓取网页内容
  10. def get_html(url):
  11. t=5
  12. while t>0:
  13. try:
  14. return urllib2.urlopen(url).read()
  15. except:
  16. t-=1
  17. print "open url failed:%s"%url
  18. # 编译正则表达式
  19. def allre(reg):
  20. return re.compile(reg,re.DOTALL)
  21. # 下载页面资源
  22. def down_src(html,title):
  23. src=allre(r'src="(.*?)"').findall(html)
  24. id = 1
  25. for s in src:
  26. nsrc='src/'+title + str(id)
  27. nsrc = nsrc.replace('#','').replace('.','').replace(' ','')
  28. nsrc = nsrc + '.png'
  29. open(workdir+nsrc,"w").write(get_html(s))
  30. html=html.replace(s,'../'+nsrc)
  31. return html
  32. # 获取contest内容
  33. def get_contest(c):
  34. html=get_html("http://codeforces.com/contest/%d/problems"%c)
  35. p=allre('class="caption">(.*?)</div>').findall(html)
  36. if len(p)==0:
  37. return None
  38. title=HTMLParser.HTMLParser().unescape(p[0]) # 获取标题
  39. html_path = workdir + 'html/[%d]%s.html'%(c,title.replace('/','_'))
  40. flag = False
  41. if os.path.exists(html_path):
  42. flag = True
  43. else:
  44. html=allre('(<div style="text-align: center;.*)').findall(html)[0] # 获取比赛页面内容
  45. html=down_src(html,title) #下载页面所需要的src
  46. return (c,title,html_path,html,flag)
  47. # 存储contest内容
  48. def save_contest(contest):
  49. html_path=contest[2]
  50. html=contest[3]
  51. open(html_path,'w').write(header+html)
  52. # ---------------------------------------------------------------
  53. # 多线程类
  54. class crawl_contest(threading.Thread):
  55. def __init__(this):
  56. threading.Thread.__init__(this)
  57. def run(this):
  58. global begin
  59. while begin<=end:
  60. lock.acquire()
  61. curid=begin
  62. begin+=1
  63. lock.release()
  64. contest=get_contest(curid)
  65. lock.acquire()
  66. # 三种情况,1- 没有获取到页面 2 - 页面已经下载过了 3 - 正常爬取页面
  67. if contest==None:
  68. print "cannot crawl contest %d"%curid
  69. elif contest[4]:
  70. print "existed:[%d]%s"%(contest[0],contest[1])
  71. else:
  72. save_contest(contest)
  73. print "crawled:[%d]%s"%(contest[0],contest[1])
  74. lock.release()
  75. # ---------------------------------------------------------------
  76. # ---------------------------------------------------------------
  77. # 从控制台获取参数 python xx.py 200 300 20 xxxx ----- 5
  78. # 0 1 2 3 4
  79. # argv[1] -> begin
  80. # argv[2] -> end
  81. # argv[3] -> thread number
  82. # argv[4] -> workdir 默认为当前目录
  83. arglen=len(sys.argv)
  84. if arglen<4 or arglen>5:
  85. print "Usage:\n\t%s begin end threads [workdir]"%sys.argv[0]
  86. exit()
  87. if arglen==5:
  88. workdir=sys.argv[4]
  89. else:
  90. workdir="./"
  91. begin=int(sys.argv[1])
  92. end=int(sys.argv[2])
  93. threads=int(sys.argv[3])
  94. # 创建src与html目录
  95. for d in ['src','html']:
  96. d = workdir + d
  97. if not os.path.exists(d):
  98. print "makedirs:%s"%d
  99. os.makedirs(d)
  100. # ---------------------------------------------------------------
  101. # 初始化线程lock
  102. lock = threading.RLock()
  103. #读取html头
  104. header=open("header.html").read()
  105. # 开始工作
  106. print "crawl contest %d to %d\n%d threads used,save in %s"%(begin,end,threads,workdir)
  107. for i in range(threads):
  108. crawl_contest().start()

3. 实例

我们以下载编号为200-250的contest为例:

  1. python crawl_html.py 200 250 30

其中html保存的即为html页面,src保存的为图片等资源

我们随意打开一个页面,可以看到,效果不错。

我们再使用shell脚本,将html批量生成pdf:

  1. ./html2pdf.sh

可以看到,我们成功将html转化为pdf了。

python爬虫学习(5) —— 扒一下codeforces题面的更多相关文章

  1. python爬虫学习 —— 总目录

    开篇 作为一个C党,接触python之后学习了爬虫. 和AC算法题的快感类似,从网络上爬取各种数据也很有意思. 准备写一系列文章,整理一下学习历程,也给后来者提供一点便利. 我是目录 听说你叫爬虫 - ...

  2. python爬虫学习(1) —— 从urllib说起

    0. 前言 如果你从来没有接触过爬虫,刚开始的时候可能会有些许吃力 因为我不会从头到尾把所有知识点都说一遍,很多文章主要是记录我自己写的一些爬虫 所以建议先学习一下cuiqingcai大神的 Pyth ...

  3. Python爬虫学习:二、爬虫的初步尝试

    我使用的编辑器是IDLE,版本为Python2.7.11,Windows平台. 本文是博主原创随笔,转载时请注明出处Maple2cat|Python爬虫学习:二.爬虫的初步尝试 1.尝试抓取指定网页 ...

  4. Python爬虫学习:三、爬虫的基本操作流程

    本文是博主原创随笔,转载时请注明出处Maple2cat|Python爬虫学习:三.爬虫的基本操作与流程 一般我们使用Python爬虫都是希望实现一套完整的功能,如下: 1.爬虫目标数据.信息: 2.将 ...

  5. Python爬虫学习:四、headers和data的获取

    之前在学习爬虫时,偶尔会遇到一些问题是有些网站需要登录后才能爬取内容,有的网站会识别是否是由浏览器发出的请求. 一.headers的获取 就以博客园的首页为例:http://www.cnblogs.c ...

  6. 《Python爬虫学习系列教程》学习笔记

    http://cuiqingcai.com/1052.html 大家好哈,我呢最近在学习Python爬虫,感觉非常有意思,真的让生活可以方便很多.学习过程中我把一些学习的笔记总结下来,还记录了一些自己 ...

  7. python爬虫学习视频资料免费送,用起来非常666

    当我们浏览网页的时候,经常会看到像下面这些好看的图片,你是否想把这些图片保存下载下来. 我们最常规的做法就是通过鼠标右键,选择另存为.但有些图片点击鼠标右键的时候并没有另存为选项,或者你可以通过截图工 ...

  8. python爬虫学习笔记(一)——环境配置(windows系统)

    在进行python爬虫学习前,需要进行如下准备工作: python3+pip官方配置 1.Anaconda(推荐,包括python和相关库)   [推荐地址:清华镜像] https://mirrors ...

  9. [转]《Python爬虫学习系列教程》

    <Python爬虫学习系列教程>学习笔记 http://cuiqingcai.com/1052.html 大家好哈,我呢最近在学习Python爬虫,感觉非常有意思,真的让生活可以方便很多. ...

随机推荐

  1. JavaScript权威设计--jQuery,Ajax.animate,SVG(简要学习笔记二十)[完结篇]

    1.$和jquery在全局命名空间中定义的唯一两个变量.   2.jquery是工厂函数,不是构造函数.他返回一个新创建的对象.   3.jquery的四种调用方式:     <1>传递C ...

  2. ASP.NET MVC5+EF6+EasyUI 后台管理系统(27)-权限管理系统-分配用户给角色

    系列目录 分配用户给角色,跟分配角色给用户操作是基本一致的. 打开模块维护,展开SysRole模块添加一个操作码,并赋予权限 设置好之后将权限授权给管理员,在SysRole的index添加操作码与js ...

  3. 浏览器加载和渲染HTML的过程(标准定义的过程以及现代浏览器的优化)

    先看一下标准定义的浏览器渲染过程(网上找的): 浏览器打开网页的过程 用户第一次访问网址,浏览器向服务器发出请求,服务器返回html文件: 浏览器开始载入html代码,发现 head 标签内有一个 l ...

  4. JAVA/GUI程序之记事本

    自上半年JAVA课程结束后,再也没有看过JAVA了,最近不是很忙,又简单的看了看,本博客纯属记录学习过程,请大神们别笑,其中错误是难免的,毕竟是新手写的博客.下面就进入我们的正题吧,复习GUI时,就想 ...

  5. jquery时间日期三级联动

    <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default3.aspx.cs ...

  6. C# 系统托盘图标

    C# 系统托盘图标 WPF NotifyIcon 资料 网址: http://www.codeproject.com/Articles/36468/WPF-NotifyIcon http://www. ...

  7. [C1] 仿 Excel 实现(C1FlexGrid)

    一  分析阶段 根据 Excel 表格区域的划分,如下图,基本上以4行*3列的框架搭建: 第一行为列头区域     ==>  C1FlexGrid.ColumnHeaders 第二行为单元格区域 ...

  8. 是时候 UWP 了 !

    什么是 UWP? 很多程序员都有一个梦想:希望自己开发的软件能够轻而易举的在所有平台上运行,而不是把同样的需求,用不同的技术.工具重新开发才能够运行在所有平台上.这就是跨平台,很多软件从业者都在为这个 ...

  9. [python] xlrd

    0.xlrd introduce Library for developers to extract data from Microsoft Excel (tm) spreadsheet files ...

  10. SIMLock锁卡功能解析

    一.锁卡背景介绍 锁卡即SIMLock,当手机开机启动或者插入SIM卡时,手机modem侧预置在NV项中的配置信息会与SIM卡中的信息做比对,检测是否匹配.若匹配,则SIM卡可以正常使用.若不匹配,则 ...