专栏首页数据小魔方左手用R右手Python系列——模拟登陆教务系统

左手用R右手Python系列——模拟登陆教务系统

最近在练习R语言与Python的网络数据抓取内容,遇到了烦人的验证码问题,走了很多弯路,最终总算解决了。

在分享这篇文章之前,只想感慨一声,虽然Python拥有更为完善的爬虫生态和多如牛毛的爬虫分享课程,但是貌似这些大部分内容,使用R语言中的RCurl+httr都可以做到,但是可惜的利用R语言学习爬虫的爱好者与Pythoner相比,实在是太少了,R语言的高阶爬虫教程凤毛麟角,只能一点一点儿在stackflow上面搜罗整理。

希望我的这一篇案例能给大家带来一点儿可借鉴的思路。

R

library("RCurl")
library("XML")
library("dplyr")
library("ggplot2")
library("ggimage")

使用爬虫登录教务系统,最大的困难是验证码识别。通常来讲,你首次访问教务处的登录页,会激活验证码请求,输入验证码和账号密码,点击登录按钮则激活一个提交数据的POST请求。前后是在同一个进程中处理的,所以你不用担心前后cookie不一致的问题。

可是如果是使用爬虫来登录,你需要使用cookie管理功能,自动记忆登录时的cookie,让两个请求绑定在一个进程里,这样后续所有的请求都会自动复用第一次登录的cookie,你可以完成所有子网页的请求与遍历。

以下是教务处的登录和验证码请求地址:

login<-"http://202.199.165.193/loginAction.do"
Codein<-"http://202.199.165.193/validateCodeAction.do"
#构造报头:
header = c(    
      "Accept"="text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
      "Connection"="keep-alive",
      "User-Agent"="Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36",
      "Content-Type"="application/x-www-form-urlencoded"
       )
#构造账号、密码、验证码(留空)构成的表单体
payload<-c(zjh="*******",mm="*****",v_yzm="")

使用cookie管理器:

#设置错误记录
d <- debugGatherer()
#构造curl句柄收集登录信息,开启cookiefile管理器:
chandle <- getCurlHandle(debugfunction=d$update,followlocation=TRUE,cookiefile="",verbose = TRUE)
#使用POST请求先请求一次登录地址,将cookie保存下来:
postForm(login,httpheader=header,.params=payload,.encoding="GBK",curl=chandle,style="post")
#获取验证码并保存本地
getBinaryURL(Codein,httpheader=header,curl=chandle) %>% writeBin("vcode.jpg")
#使用ggplot2读取验证码:
ggplot()+geom_image(aes(x=1,y=1,image="vcode.jpg"),size=.1)+theme_void()
#指定验证码
payload[['v_yzm']]<-readline("请输入您的验证码:")
#使用完整的登录信息再次POST请求登录:
postForm(login,httpheader=header,.params=payload,.encoding="GBK",curl=chandle,style="post")
url=URLencode("http://202.199.165.193/gradeLnAllAction.do?type=ln&oper=qbinfo",reserved =FALSE)
#当登录成功之后,即可切换到别的子页面进行内容请求
mysocre<-postForm(url,httpheader=header,.params=payload,.encoding="GBK",curl=chandle,style="post") 
myresult<-mysocre %>% iconv("GBK","utf-8") %>% htmlParse(encoding="utf-8") 
#抽取学期信息
scorename<-myresult  %>% getNodeSet("//table//tr//td[@valign='middle']/b") %>% lapply(xmlValue,trim=T) %>% unlist()
#提取成绩表标头信息
namelabel<-myresult  %>% getNodeSet("//table[@class='titleTop2']//th") %>% lapply(xmlValue,trim=T) %>% unlist() %>% unique()
#提取课程成绩信息:
scoreclass<-myresult %>% getNodeSet("//table[@class='titleTop2']") 
classall<-data.frame()
for (i in 1:8){
classall<-rbind(classall,scoreclass %>% `[[`(i) %>% readHTMLTable() %>% .[3:(nrow(.)-1),])
 }
#提取所有学习成绩
names(classall)<-namelabel
#预览
head(classall)

接下来使用httr包进行演示:

library("httr") 
library("dplyr") 
library("jsonlite")
library("curl")
library("magrittr")
library("plyr")
library("rlist")
library("jpeg")
library("ggimage")
library("rvest")

POST登录教务系统:

#构造报头和登录信息
header = c( "Accept"="text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",    "Connection"="keep-alive",    "User-Agent"="Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36",    "Content-Type"="application/x-www-form-urlencoded")
payload<-c(zjh="*******",mm="********",v_yzm="")
#登录请求和验证码请求地址
login  <-"http://202.199.165.193/loginAction.do"
Codeurl<-"http://202.199.165.193/validateCodeAction.do"
h<-handle(login)
#第一次请求获取并保存cookie
POST(login,add_headers(.headers =header),body =payload,encode="form",verbose(),handle=h) 
#第二次请求获取验证码
image<-POST(Codeurl,add_headers(.headers =header),body=payload,encode="form",verbose(),handle=h)%>% content()
image %>% jpeg::writeJPEG(.,"vcode.jpg",quality=1)
#读取验证码
ggplot()+geom_image(aes(x=1,y=1,image="vcode.jpg"),size=.1)+theme_void()
#手动输入验证码,完善登录信息:
payload[['v_yzm']]<-readline("请输入您的验证码:")
#可以再请求一次,查看弹出信息,如果出现你的名字或者课程信息,那么恭喜你,登录成功了!
r <- POST(login,add_headers(.headers =header),body =payload,encode="form",verbose(),handle=h)
#登录成功之后,可以换一个子网页请求自己需要的信息
url<- URLencode("http://202.199.165.193/gradeLnAllAction.do?type=ln&oper=qbinfo",reserved =FALSE)
myresult<- POST(url,add_headers(.headers =header),body =payload,encode="form",verbose(),handle=h) 
#获取内容并解析内容,剩余的解析内容你可以使用rvest包或者使用XML包
mytable <-  myresult  %>%  content(as="parsed",type ="text/html",encoding ="GBK") %>% html_nodes(xpath="//table[@class='titleTop2']") %>% html_table(fill = TRUE)

Python:

import http.cookiejar
from urllib.request import build_opener, HTTPCookieProcessor, Request  
from urllib.parse import urlencode  
from PIL import Image
import matplotlib.pyplot as plt
import re
import sys
import importlib
importlib.reload(sys)

开启cookies管理:

cookie = http.cookiejar.CookieJar()  
opener=build_opener(HTTPCookieProcessor(cookie))  
#构造个人登录信息:
values = {'zjh':'*******','mm':'*****','v_yzm':''}
postdata = urlencode(values).encode(encoding='UTF-8')
header = {    
     'User-Agent':'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36',
     'Referer':'http://202.199.165.193/loginAction.do'
      }
#第一次请求网页得到cookie:
login = "http://202.199.165.193/loginAction.do"
request = Request(login,postdata,headers=header)
response = opener.open(request)
print (response.getcode())
#200
for item in cookie:
    print ('Name = '+item.name)
    print ('Value = '+item.value)

获取验证码并保存 :

yzm = opener.open("http://202.199.165.193/validateCodeAction.do")
yzm_data = yzm.read()
yzm_pic  = open('yzm.jpg','wb')
yzm_pic.write(yzm_data)
yzm_pic.close()

读取用户验证码

img=Image.open('yzm.jpg')
plt.figure("code",figsize=(1.2,2.4))
plt.axis('off')
plt.imshow(img)
plt.show()
values['v_yzm'] = input('请输入验证码:')
login = "http://202.199.165.193/loginAction.do"
postdata = urlencode(values).encode(encoding='UTF-8')
#带验证码模拟登陆
request  = Request(login,postdata,header)
response = opener.open(request)
print (response.read().decode('gbk'))

请求需要的内容信息:

url="http://202.199.165.193/gradeLnAllAction.do"
values = {"type":"ln","oper":"qbinfo","lnxndm":"2014-2015学年第二学期(两学期)"}
data = urlencode(values)
geturl = url + "?" + data
response = opener.open(geturl)
print(response.read().decode('gbk'))


本文参考文献:
https://cran.r-project.org/web/packages/RCurl/
RCurl.pdfhttp://blog.csdn.net/sinat_26917383/article/details/51123164
https://cran.r-project.org/web/packages/httr/
httr.pdf
https://docs.python.org/2/library/urllib.html
往期案例数据请移步本人GitHub:
https://github.com/ljtyduyu/DataWarehouse/tree/master/File

本文分享自微信公众号 - 数据小魔方(datamofang),作者:杜雨

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2017-10-18

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • PPT图文混排三大常用技能

    今天跟大家聊一聊多图型PPT最常用的三大排版技巧 ——半透明遮罩、色块衬底、渐变过渡 图文混排技巧 ▽ 虽然PPT在图文排版方面与专业的修图软件PS比起来 要有...

    数据小磨坊
  • 左手用R右手Python系列——动态网页抓取与selenium驱动浏览器

    关于基础的网络数据抓取相关内容,本公众号已经做过很多次分享,特别是R语言的爬虫框架(RCurl+XML/httr+rvest[xml2+selectr])已经形...

    数据小磨坊
  • think-cell chart系列12——气泡图

    今天要跟大家分享的是气泡图! 因为think-cell chart中气泡图与散点图的数据组织结构非常相似(几乎就是一样的,气泡图要比散点图多一列size数据(散...

    数据小磨坊
  • 【玩转腾讯云】万物皆可Serverless之Kaggle+SCF端到端验证码识别从训练到部署

    近些年来人工智能迅速发展,尤其是在深度学习神经网络这一块生态尤为繁荣,各种算法和模型层出不穷。

    乂乂又又
  • 裸金属服务器kvm虚拟化安装win10

    和普通的 VPS 相比,裸金属服务器属于物理服务器,我的数据和其他用户数据做到了物理隔离,同时服务器本身是支持二次虚拟化的。

    宋天伦
  • 洛谷P1134 阶乘问题

    题目描述 也许你早就知道阶乘的含义,N阶乘是由1到N相乘而产生,如: 12! = 1 x 2 x 3 x 4 x 5 x 6 x 7 x 8 x 9 x 10 ...

    attack
  • 想拿腾讯Offer?这80道算法高频面试题别漏了

    我自从2015年担任算法组leader,作为面试官面试了不少同学。前前后后面试了超过200名同学,其中有不少入职的同学后来发展都不错,也坚定了自己对于选人标准的...

    Python编程与实战
  • SVN安装---本机安装---SVN仓库(2)

    wust小吴
  • Date对象和Math对象

        1.  var  date=new Date()    //无参数的情况下返回值为当前时间

    用户3159471
  • 腾讯云客户服务热线重磅升级 ——95716:新起点,心服务

    近日,腾讯云推出了全新的客户服务热线95716,目前已通过百度认证、小程序、官网控制台、官网联系我们等入口上线,将持续为用户提供高品质的服务。

    腾讯云技术服务团队

扫码关注云+社区

领取腾讯云代金券