网络上大部分关于python爬虫的介绍以及代码讲解,都用的是python2.7或以下版本,用python3.x版本的甚少。

  在python3.3.2版本中,没有urllib2这个库,也没有cookiejar这个库。对应的库分别是http.cookiejar以及urllib这俩。

  关于url以及python2.7爬虫写法的介绍,可以参考[Python]网络爬虫(一):抓取网页的含义和URL基本构成这系列的文章。我这里主要介绍的是python3.3.2的urllib2的实现。

  

  首先,下面是一个简单的抓取网页信息程序,主要是介绍下urllib的使用。

# 简单的抓取HOJ主页的数据
import urllib.request response = urllib.request.urlopen('http://acm.hit.edu.cn')
html = response.read()
print(html) # 注意,由于网页抓取下来的是bytes格式的数据,所以写入文件时需要以二进制的方式写入
fout = open('txt.txt','wb')
fout.write(html)
fout.close() fout = open('html.html','wb') # 写入到文件html.html
fout.write(html)
fout.close()

  运行结果应该是txt.txt,html.html两个文件。我们可以打开看看txt.txt、html.html看看,发现txt.txt的数据跟浏览器查看的网页源代码一致。如果用浏览器打开html.html,会发现这个跟我们实际上考看到的网页基本一样。

  


  

模拟HOJ登陆并抓取已经AC的代码

  

  我们需要进行登陆,需要设置一个cookie处理器,它负责从服务器下载cookie到本地,并且在发送请求时带上本地的cookie。

    # 设置一个cookie处理器,它负责从服务器下载cookie到本地,并且在发送请求时带上本地的cookie
cj = http.cookiejar.LWPCookieJar()
cookie_support = urllib.request.HTTPCookieProcessor(cj)
opener = urllib.request.build_opener(cookie_support, urllib.request.HTTPHandler)
urllib.request.install_opener(opener)

  

  登陆时需要对HOJ服务器发送数据请求,对于发送data表单数据,我们怎么查看需要发送的数据?在HTTP中,这个经常使用熟知的POST请求发送。

  我们可以先查看网页源代码,看到

  

  看到三个name,所以发送的求情数据中需要包含这三个,

    # 构造Post数据,从抓大的包里分析得出的或者通过查看网页源代码可以得到
data = {
'user' : user, # 你的用户名
'password' : password, # 你的密码,密码可能是明文传输也可能是密文,如果是密文需要调用相应的加密算法加密
'submit' : 'Login' # 特有数据,不同网站可能不同
}

  

  另外,一般的HTML表单,data需要编码成标准形式。然后做为data参数传到Request对象。所以我们需要对data进行编码。

data = urllib.parse.urlencode(data).encode('utf-8')

  

  发送请求,得到服务器给我们的响应,完成登录功能。header最好加上,不然由于内部信息默认显示为机器代理,可能被服务器403 Forbidden拒绝访问。

    # 发送请求,得到服务器给我们的响应
response = urllib.request.Request(url, data,header)
# 通过urllib提供的request方法来向指定Url发送我们构造的数据,并完成登录过程
urllib.request.urlopen(response)

  

  登录函数如下:

def login(): # 登陆函数
print('请输入你的账号')
user = input()
print('请输入你的密码')
password = input() # 设置一个cookie处理器,它负责从服务器下载cookie到本地,并且在发送请求时带上本地的cookie
cj = http.cookiejar.LWPCookieJar()
cookie_support = urllib.request.HTTPCookieProcessor(cj)
opener = urllib.request.build_opener(cookie_support, urllib.request.HTTPHandler)
urllib.request.install_opener(opener) url = 'http://acm.hit.edu.cn/hoj/system/login' # 登陆的界面 # 这个最好加上,不然由于内部信息默认显示为机器代理,可能被服务器403 Forbidden拒绝访问
header={'User-Agent':'Magic Browser'} # 构造Post数据,从抓大的包里分析得出的或者通过查看网页源代码可以得到
data = {
'user' : user, # 你的用户名
'password' : password, # 你的密码,密码可能是明文传输也可能是密文,如果是密文需要调用相应的加密算法加密
'submit' : 'Login' # 特有数据,不同网站可能不同
} data = urllib.parse.urlencode(data).encode('utf-8') # 发送请求,得到服务器给我们的响应
response = urllib.request.Request(url, data,header)
# 通过urllib提供的request方法来向指定Url发送我们构造的数据,并完成登录过程
urllib.request.urlopen(response) return

  

  登录进去后,我们需要对已经AC的代码进行抓取。抓取的链接为:

  http://acm.hit.edu.cn/hoj/problem/solution/?problem=题目编号

    url = 'http://acm.hit.edu.cn/hoj/problem/solution/?problem='+str(i)
response = urllib.request.urlopen(url)
html = response.read()

  我们可以把html输出看看具体内容是什么。  

  通过查看网页代码,发现提交的代码都是在<span></span>标签中。

  

  因此我们可以对这部分数据进行处理,处理过程中我们可以用到python的正则表达式进行搜索。并且对于特殊的编码如&lt;需要进行解码。

  当然,我们需要注意保存的文件到底是java还是c++。

 

  最后,详细的代码如下:

  

import urllib
import http.cookiejar
#import time hashTable = { # 网页特殊编码转化
'<':'<',
'>': '>',
'{':'{',
'}':'}',
'(':'(',
')':')',
' ':' ',
'&':'&',
'[':'[',
']':']',
'"':'"'
} def login(): # 登陆函数
print('请输入你的账号')
user = input()
print('请输入你的密码')
password = input() # 设置一个cookie处理器,它负责从服务器下载cookie到本地,并且在发送请求时带上本地的cookie
cj = http.cookiejar.LWPCookieJar()
cookie_support = urllib.request.HTTPCookieProcessor(cj)
opener = urllib.request.build_opener(cookie_support, urllib.request.HTTPHandler)
urllib.request.install_opener(opener) url = 'http://acm.hit.edu.cn/hoj/system/login' # 登陆的界面 # 这个最好加上,不然由于内部信息默认显示为机器代理,可能被服务器403 Forbidden拒绝访问
header={'User-Agent':'Magic Browser'} # 构造Post数据,从抓大的包里分析得出的或者通过查看网页源代码可以得到
data = {
'user' : user, # 你的用户名
'password' : password, # 你的密码,密码可能是明文传输也可能是密文,如果是密文需要调用相应的加密算法加密
'submit' : 'Login' # 特有数据,不同网站可能不同
} data = urllib.parse.urlencode(data).encode('utf-8') # 发送请求,得到服务器给我们的响应
response = urllib.request.Request(url, data,header)
# 通过urllib提供的request方法来向指定Url发送我们构造的数据,并完成登录过程
urllib.request.urlopen(response) return def solve(html,i):
txt = html.decode('gbk','ignore') start = txt.find('<span')
if start==-1: # 没有span,表示此题没AC
return
p = '.java'
if txt.find('import')==-1:
p = '.cpp' fout = open('txt_'+str(i)+p,'w')
while True:
end = txt.find('<span',start+5)
if end==-1:
end = txt.find('</span>',start) x = txt.find('>',start)+1
w = '' ok = True
while x<end:
if txt[x]=='<':
ok = False
elif txt[x]=='>':
ok = True
if not ok or txt[x]=='>':
x += 1
continue if txt[x]=='&': # 进行特殊的解码
t4 = txt[x:x+4]
t5 = txt[x:x+5]
t6 = txt[x:x+6]
if t4 in hashTable:
w += hashTable[t4]
x += 4
elif t5 in hashTable:
w += hashTable[t5]
x += 5
elif t6 in hashTable:
w += hashTable[t6]
x += 6
else:
w += txt[x]
x += 1
else:
w += txt[x]
x += 1
fout.write(w)
if end==start:
break
start = end fout.close()
return def run(): # 抓取所有AC代码
for i in range(1001,3169):
url = 'http://acm.hit.edu.cn/hoj/problem/solution/?problem='+str(i)
response = urllib.request.urlopen(url)
html = response.read()
solve(html,i)
#time.sleep(0.5) # 时间间隔为0.5s发送一次抓取请求,减轻hoj服务器压力
return login()
run()

  

我所有的HOJ AC代码,在http://pan.baidu.com/s/1gdsX9DL

  


提交AC代码:

  这个其实跟登陆并抓取AC代码原理基本一样。

  

    # 构造Post数据,从网页数据分析得出
data = {
'Proid' : num,
'Language' : language,
'Source' : txt # 可以通过查看网页源代码看出
}

  另外,我们需要用到listdir()函数,以此来获得当前目录下所有的文件。

  这里我们需要设置time.sleep(3) ,间隔三秒递交一次代码,减轻服务器压力,以免使得HOJ服务器崩了。

  总的代码如下:

import urllib
import http.cookiejar
import time
from os import listdir def login():
print('请输入你的账号')
user = input()
print('请输入你的密码')
password = input() cj = http.cookiejar.LWPCookieJar()
cookie_support = urllib.request.HTTPCookieProcessor(cj)
opener = urllib.request.build_opener(cookie_support, urllib.request.HTTPHandler)
urllib.request.install_opener(opener) url = 'http://acm.hit.edu.cn/hoj/system/login' header = {'User-Agent' : 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:14.0) Gecko/20100101 Firefox/14.0.1',
'Referer' : '******'} # 构造Post数据,他也是从抓大的包里分析得出的。
data = {'op' : 'dmlogin',
'f' : 'st',
'user' : user, # 用户名
'password' : password, # 密码,密码可能是明文传输也可能是密文,如果是密文需要调用相应的加密算法加密
'submit' : 'Login' # 特有数据,不同网站可能不同
} data = urllib.parse.urlencode(data).encode('utf-8')
request = urllib.request.Request(url, data,header) # 通过urllib2提供的request方法来向指定Url发送我们构造的数据,并完成登录过程
urllib.request.urlopen(request) return def solve(file): # file:为文件名,格式是 txt_problemNumber.cpp或者 txt_problemNumber.java
ed = file.find('.')
language = file[ed+1:len(file)]
if language!='cpp' and language!='java':
return
if language=='cpp':
language = 'C++'
else:
language = 'Java'
st = file.find('_')
num = file[st+1:ed] url = 'http://acm.hit.edu.cn/hoj/problem/submit/?id='+num header = {'User-Agent' : 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:14.0) Gecko/20100101 Firefox/14.0.1',
'Referer' : '******'} fin = open(file,'rb')
txt = fin.read().decode('gbk','ignore')
fin.close() # 构造Post数据,从网页数据分析得出
data = {
'Proid' : num,
'Language' : language,
'Source' : txt # 可以通过查看网页源代码看出
} data = urllib.parse.urlencode(data).encode('utf-8') # 使用UTF-8编码方式进行编码
request = urllib.request.Request(url, data,header) # 添加消息头 # 通过urllib2提供的request方法来向指定Url发送我们构造的数据,并完成登录过程
urllib.request.urlopen(request) time.sleep(3) # 间隔三秒递交一次代码,减轻服务器压力 return def run():
allFile = listdir() # 获得当前目录下所有的文件
for file in allFile:
solve(file) return login()
run()

  

codeforces爬AC代码(有些网页格式不太一样,最后直接把那些题目忽略了,囧)(CF python代码尚未正确,有待改进。。。)

import urllib

user = 'yejinru' # 用户
page = 21 # 提交的页数 def solve(html,name):
txt = html.decode('utf-8','ignore') cpp = '.cpp'
start = txt.find('include')-1
if start==-2:
start = txt.find('public static void Main')
if start==-1:
cpp = '.py'
else:
cpp = '.java' end = txt.find('</pre>',start+100) fout = open('cf/'+name+cpp,'wb')
pro = txt[start:end] pro = pro.replace(u'<',u'<')
pro = pro.replace(u'>',u'>')
pro = pro.replace(u'"',u'"')
pro = pro.replace(u'&',u'&') fout.write(pro.encode('gbk','ignore'))
fout.close()
return def fun(html):
txt = html.decode('utf-8','ignore')
pre = 0
while True:
cur = txt.find('<span class=\'verdict-accepted\'>',pre)
if cur==-1:
return
pre = cur+100 p = txt.find( '"',txt.find('submissionId="',cur-50) )+1
pid = ''
while txt[p]!='"':
pid += txt[p]
p += 1 p = txt.find('data-problemId="',cur-300)
if p==-1:
return
p = txt.find('>',txt.find('<a href="/',p))+19
if p==18:
return
tid = '' while txt[p]>='0' and txt[p]<='9':
tid += txt[p]
p += 1
if len(tid)>3:
continue url = 'http://codeforces.com/contest/'+tid+'/submission/'+pid
print(url)
response = urllib.request.urlopen(url)
html = response.read() solve(html,tid+txt[p]) fout = open('cf/'+pid+'.html','wb')
fout.write(html)
fout.close() return def run():
add = '/page/'
first = 'http://codeforces.com/submissions/'+user for i in range(1,page+1): # 这是因为http://codeforces.com/submissions/yejinru这里只有21页
url = ''
if i==1:
url = first
else:
url = first+add+str(i)
response = urllib.request.urlopen(url)
html = response.read()
fun(html) return run()

  

python 3.3.2 爬虫记录的更多相关文章

  1. 第一次用python 写的简单爬虫 记录在自己的博客

    #python.py from bs4 import BeautifulSoup import urllib.request from MySqlite import MySqlite global ...

  2. Python初学者之网络爬虫(二)

    声明:本文内容和涉及到的代码仅限于个人学习,任何人不得作为商业用途.转载请附上此文章地址 本篇文章Python初学者之网络爬虫的继续,最新代码已提交到https://github.com/octans ...

  3. [Python学习] 简单网络爬虫抓取博客文章及思想介绍

            前面一直强调Python运用到网络爬虫方面很有效,这篇文章也是结合学习的Python视频知识及我研究生数据挖掘方向的知识.从而简介下Python是怎样爬去网络数据的,文章知识很easy ...

  4. 洗礼灵魂,修炼python(50)--爬虫篇—基础认识

    爬虫 1.什么是爬虫 爬虫就是昆虫一类的其中一个爬行物种,擅长爬行. 哈哈,开玩笑,在编程里,爬虫其实全名叫网络爬虫,网络爬虫,又被称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者 ...

  5. 使用Python + Selenium打造浏览器爬虫

    Selenium 是一款强大的基于浏览器的开源自动化测试工具,最初由 Jason Huggins 于 2004 年在 ThoughtWorks 发起,它提供了一套简单易用的 API,模拟浏览器的各种操 ...

  6. 孤荷凌寒自学python第八十天开始写Python的第一个爬虫10

    孤荷凌寒自学python第八十天开始写Python的第一个爬虫10 (完整学习过程屏幕记录视频地址在文末) 原计划今天应当可以解决读取所有页的目录并转而取出所有新闻的功能,不过由于学习时间不够,只是进 ...

  7. 孤荷凌寒自学python第七十九天开始写Python的第一个爬虫9并使用pydocx模块将结果写入word文档

    孤荷凌寒自学python第七十九天开始写Python的第一个爬虫9 (完整学习过程屏幕记录视频地址在文末) 今天在上一天的基础上继续完成对我的第一个代码程序的书写. 到今天终于完成了对docx模块针对 ...

  8. 孤荷凌寒自学python第七十八天开始写Python的第一个爬虫8

    孤荷凌寒自学python第七十八天开始写Python的第一个爬虫8 (完整学习过程屏幕记录视频地址在文末) 今天在上一天的基础上继续完成对我的第一个代码程序的书写. 到今天止基本完成了对docx模块针 ...

  9. 孤荷凌寒自学python第七十七天开始写Python的第一个爬虫7

    孤荷凌寒自学python第七十七天开始写Python的第一个爬虫7 (完整学习过程屏幕记录视频地址在文末) 今天在上一天的基础上继续完成对我的第一个代码程序的书写. 今天的学习仍然是在纯粹对docx模 ...

随机推荐

  1. Linux 下安装android

    主要参考了这篇文章 http://segmentfault.com/a/1190000003069062#articleHeader2 这里提到了“unable to run mksdcard sdk ...

  2. OC:属性的内部实现原理、dealloc内释放实例变量、便利构造器方法的实现原理、collection的内存管理

    代码: // // main.m #import <Foundation/Foundation.h> #import "Person.h" #import " ...

  3. C# —— IList, ArrayList与List的区别详解

    共同点:    IList, List , ArrayList 通俗一点来讲就是广义的数组,C#里面称之为集合.不同于一般的狭义的数组,它们可以存放任意类型的东西,在申明或者赋值的时候指定. 比如你写 ...

  4. C# 6与VB 12即将加入模式匹配

    又有一种源自于函数式编程语言中的概念加入了C#和VB的阵营,这就是被称为模式匹配(Pattern Matching)的特性.初看上去,模式匹配的作用类似于一段switch/select语句块,但它的功 ...

  5. The sound of silence引发的关于互联网以及教育的利弊思考

    “茫茫人海里,人群跟著人群,我们无时无刻不感到孤寂.停下来让我们好好沟通吧,否则人类的关系将日形恶化,沦为新世纪科技的牺牲品” ------- Simon 说实话,我第一次看<毕业生>应该 ...

  6. [Express] Level 1: First Step

    Installing Express Let's start building our new Express application by installing Express. Type the ...

  7. Android自定义长按事件

    Android系统自带了长按事件,setOnLongClickListener即可监听.但是有时候,你不希望用系统的长按事件,比如当希望长按的时间更长一点的时候.这时候就需要自己来定义这个长按事件了. ...

  8. [原创]SQL SERVER 2008R2安装

    配置系统环境说明 操作系统:Windows 7 操作系统版本:旗舰版 SP1 操作系统位数:x64 注:其它系统配置也基本相似,只是可能菜单的名字或者所处位置不一样,具体的配置如有不同,请自行搜索 安 ...

  9. oracle之报错:ORA-00054: 资源正忙,要求指定 NOWAIT_数据库的几种锁

    问题如下: SQL> conn scott/tiger@vm_databaseConnected to Oracle Database 11g Enterprise Edition Releas ...

  10. c#删除转义字符的方法,删除\0后所有字符串(菜鸟级别)

    string str = "78738\01212"; string str_2= Regex.Unescape(str); int index = str_2.IndexOf(& ...