爬一爬!
仅仅记录一下一个java狂热者在python中的爬路经历。
谈谈自己对Java和Python在网络编程方面的感受: 曾经的我在java中写过不少爬虫,代码量非常的大(毕竟静态语言非得事先声明),而且post过程及其复杂,对cookie的操作也显得特别混乱(但是java的代码结构还是依然的清晰,有条有理。这也是动态语言不能超越的)。最近看了python中的网络编程,感叹其简洁性,曾经HttpUrlConnection或者HttpClient复杂的connect过程在python中仅一行代码urlopen。这真的是让我措手不及。废话少说....
我使用的是Python3.5,之前用2.7写过一次,使用的是url lib,urllib2,cStringIO。但是将源代码转换到python3.5之后,异常纷飞。
所以这里简要说明一下版本间的模块的对应关系:
python2.7 | python3.5 |
urllib | url lib.parse |
urllib2 | url lib.request |
cStringIO | io |
PIL.Image | Image |
思路:
1.先去xxx教务网站抓包,看一下我们网络请求所需要的数据。(chrome自带工具台)
2. 网站需要验证码
3.我们在第一次进入登陆页面的时候会返回一个set-cookie值
4.在登陆的时候需要post查询的学号以及密码
5.登录成功之后,每次访问其他数据都需要带上之前的cookie
整体的思路就是这样,接下来就来实现一下
import urllib.request as urllib2
import urllib.parse as urllib
import PIL.Image as Image
import io as cStringIO
import re
以上是在3.0中的导入过程,并且将对应关系写在上面。(其实是我太懒了,不打算重写一遍py3.5的代码,于是选择在使用新模块的时候沿用之前的名字)
studentId = input('请输入查询学号:')
password = input('请输入你的密码:')
req_index = urllib2.Request('http://jwc.xxx.edu.cn/bkjw/')
res_index = urllib2.urlopen(req_index)
img_cookie = res_index.headers['Set-Cookie'].split(';')[0]
#print(img_cookie)
首先呢输入学号和密码等个人信息,并且模拟登陆页面,获得浏览器的set-cookie值img_cookie
第二步,请求验证码图片,同时带上获得到的cookie字段img_cookie。在获取到图片的bytes流之后,使用io模块转为文件并使用Image模块显示。
(注意这里标注为**的一行,在2.x中使用的是cStringIO.StringIO,而在3.x中使用的是io.BytesIO),最后调用show方法显示。
req_getimg = urllib2.Request('http://jwc.xxx.edu.cn/bkjw/captchaImage')
req_getimg.add_header('Cookie',img_cookie)
res_getimg = urllib2.urlopen(req_getimg)
img_output = res_getimg.read()
**file = cStringIO.BytesIO(img_output)
img = Image.open(file)
img.show()
根据之前的个人信息及验证码信息组装表单
x = input('请输入验证码: ')
mydata = {'usercode':studentId,'password':password,'code':x}
发出post请求,请求登陆
req_in = urllib2.Request(url='http://jwc.xxx.edu.cn/bkjw/login',data=urllib.urlencode(mydata).encode('utf8'))
req_in.add_header('Cookie',img_cookie)
res_in = urllib2.urlopen(req_in)
req_cet = urllib2.Request(url='http://jwc.xxx.edu.cn/bkjw/sljcjcx/sljcjcxInit')
req_cet.add_header('Cookie',img_cookie)
res_cet = urllib2.urlopen(req_cet)
html_cet = res_cet.read().decode('utf-8')
mycet = html_cet.split('</br>')
studentName = mycet[0].split("<td width=\"202\">")[1].split("</td>")[0]
studentXueY = mycet[0].split("<th>学 院:</th>")[1].split("<td colspan=\"3\">")[1].split("</td>")[0]
mycet[0] = mycet[0].split("<td colspan=\"4\">")[1]
print ('=======================================CET score====================================')
print ('学号:%s'%studentId)
print ('姓名:%s'%studentName)
print ('学院:%s'%studentXueY)
print ('\n')
for i in range(3):
print(mycet[i].strip())
最终效果图:
**注释**
由于涉及到一些隐私,就不去透露具体的学校和网址了。在校学生感兴趣的可以试一试,抓好包其他问题不在话下。(毕竟京东的我也爬过,完全没问题。学校教务网页的水平就摆在那里,很少有反爬机制。)
今年6级木有报上,写篇博客为明年的6级开个好头...