这两天需要把有道单词本中的单词导出到本地,有道本身也提供了这样的功能,但十分单一,只能导出单词拼写,音标,中文语义,不方便学习和记忆单词。所以用ruby写了这个爬虫,其中整个过程中最主要要解决的有三个问题:

  1. URL重定向
  2. 模拟登录有道词典
  3. HTTP访问中cookie的管理

http重定向

我们打开有到词典的首页,会在搜索框下面发现一个”我的单词本“的链接,点开它,但单词本的页面并没有显示出来,现在你看到的一定是登录界面。对呀,每个人的单词本都是不一样的,没有身份验证怎么能行呢。就在刚刚的这个过程中发生了URL的重定向。我们可以做如下测验:

main_uri=URI("http://dict.youdao.com")
main_page=Net::HTTP.get_response(main_uri)
main_html=Nokogiri::HTML(main_page.body)
words_str=nil
main_html.search("a").each do |tag|words_str=tag.attribute("href") if tag.content=="单词本"
end
words_uri=URI(words_str)
puts Net::HTTP.get(words_uri)

则会看到打印到控制台的消息是:

The URL has moved <a href="http://account.youdao.com/login?service=dict&back_url=http://dict.youdao.com/wordbook/wordlist%3Fkeyfrom%3Dnull">here</a>

这正是我们呢在浏览器中可以看到的东西,当我们还没登录是,点击单词本的链接就会先弹出来一个登录界面,然后在我们输入登录信息之后就又会返回到单词本的页面,这期间发生了两次URL的重定向。
在发生重定向后,返回的HTTP头中location字段会显示更新后的URL,rubydoc中有详细的处理过程,在本例中可以如下写:

def fetch(uri)page=Net::HTTP.get_response(uri)case pagewhen Net::HTTPSuccess then pagewhen Net::HTTPRedirection thenlocation=page['location']fetch(URI(location))end
end

所以以后为了避免重定向的问题,就用fetch方法代替GET方法了,至此我们解决了第一个问题。


模拟登录

模拟登录的处理比重定向麻烦了许多,分析登录界面,用户的登录信息是嵌入到一个表单当中的,除了用户名和密码,按钮和复选框以外,其他都是hidden属性,所以不可见,所以在提交的时候这些hidden字段按照name=>value的样子提交了就行,只是加入自己的信息就可以。在整个html文件中找到表单就需要Nokogiri这个包了。表单也填好了,那就把信息提交到服务器端吧,net/http中有一个post_form方法,把所有的表单按照Hash的形式传入方法,就可以提交到指定的URL了。恩,这个问题就也可以解决了。等等,URL?哪个URL?提交到哪里?是第一步重定向的那个URL么?那看一下正真的浏览器是怎么做的吧

没错,你看到的请求网址才是正真的提交表单的URL。
具体实现的代码可以写成:

words_page=fetch(words_uri)
words_uri=words_page.uri
words_page=Nokogiri::HTML(words_page.body)
params={}
words_page.xpath("//form//input").each do |t|params[t.attribute("name").to_s]=t.attribute("value").to_s if t.attribute("name")!=nil
end
params["username"]="××××"
params["password"]="××××"
form_action=URI "https://logindict.youdao.com/login/acc/login"
words_page=Net::HTTP.post_form(form_action,params)

迫不及待的运行,期待着一个新的页面跳入眼帘,但是如果不意外,当你打印word_page.body的时候一定还会是一个重定向的页面,而且又定向到了之前的登录页面。这一切现象都表明我们的登录失败了。因为我已经做过了,所以我会建议你关掉浏览器的javascript支持,看能不能模拟到我们的登录过程。如果这样做,就算是你的浏览器都不能成功登录,只有一遍又一遍的重定向页面,登录了好几遍,眼前还是那个熟悉的登录页面。你一定已经知道是怎么回事了。没错,就是javascrip,它只是隐藏在了我们的浏览器和远程的服务器中间了,说不定我们提交的数据是已经被它动过手脚的呢。
查看登录页面的源代码:

function validate(disableSubmit){var form = document.f;var name = form.username.value.trim();var password = form.password.value;if((name.length < 1 || name == _hint)|| (password.length < 1)|| password.length > 16) {//alert("请输入正确的网易邮箱用户名 ")showWarning1(true);return false;}form.password.value = hex_md5(form.password.value);var savelogin = yd_get_elem("savelogin");if (savelogin.checked){form.cf.value = 7;}if(disableSubmit) {form.submit.disabled = true;}return true;
}

这是验证用户登录数据的一个javascript程序,顺便还给我们的密码加了密。哦,这下明白了,我们也应该提交加密后的密码,就像javascript做的那样。还要注意的是保存登录这个复选框的影响表单中的cf字段,要格外小心。这下登录成功了吧,打印word_page.body也不会重定向到登录页面了,而是正确的转到了你的单词本,不管怎么说,离成功又尽了一步呢。


管理cookie

HTTP协议是不会记忆状态的,所以如果这个时候我们用GET方法获取你的单词本的html文件,又会重定向回该死的登录页面。所以在登录成功后一定要管理好服务器给我们的钥匙–cookiecookie在服务器的返回的http报文中的set-cookie字段指定,用来记录特定的状态。

cookies=words_page.header['set-cookie']
new_uri=URI.parse(words_page['location'])
http=Net::HTTP.new(new_uri.host,new_uri.port)
res=http.get(new_uri.path,{'cookie'=>cookies})
res=Nokogiri::HTML(res.body)

现在打印res.body是不是我们需要的单词本的页面就下载下来了,接下来做的就是从页面中提取我们感兴趣的数据,用好nokogiri这个包就行了。未完,请移步打造个性化有道单词本(二)

应用ruby打造个性化的有道单词本 (一)相关推荐

  1. 《Ruby程序员修炼之道》(第2版)目录—导读

    版权 Ruby程序员修炼之道(第2版) • 著 [美] David A. Black 译 钟凤鸣 陈雪静 责任编辑 杨海玲 • 人民邮电出版社出版发行 北京市丰台区成寿寺路11号 邮编 100164 ...

  2. 【星球问答精选】我想打造个性化的高效工作流,不会编程怎么办?

    题图:Photo by Christin Hume on Unsplash 知识星球上,星友 Kevin 提问(为保护隐私,有删节): 王老师您好,我是您的超级忠实读者以及新晋工具爱好者.由于新晋,所 ...

  3. 《Ruby程序员修炼之道》(第2版)—第1章1.2节剖析Ruby的安装

    本节书摘来自异步社区<Ruby程序员修炼之道>一书中的第1章,第1.2节剖析Ruby的安装,作者[美]David A. Black(戴维 A. 布莱克),更多章节内容可以访问云栖社区&qu ...

  4. 《Ruby程序员修炼之道》(第2版)—第1章1.4节易用的Ruby工具和应用程序

    本节书摘来自异步社区<Ruby程序员修炼之道>一书中的第1章,第1.4节易用的Ruby工具和应用程序,作者[美]David A. Black(戴维 A. 布莱克),更多章节内容可以访问云栖 ...

  5. 《Ruby程序员修炼之道》(第2版)—第1章1.1节进入Ruby的世界

    本节书摘来自异步社区<Ruby程序员修炼之道>一书中的第1章,第1.1节进入Ruby的世界,作者[美]David A. Black(戴维 A. 布莱克),更多章节内容可以访问云栖社区&qu ...

  6. 安卓直播详细教程(三)-----ijkplayer打造个性化控制界面

    ##前言 为什么要写这篇文章呢? Firsr:直接集成ijkplayer的控制界面太丑了 Second:无法满足我们的需求 我们来看下直接集成的ijkplayer控制界面: 是不是没法用,那么我们现在 ...

  7. Oracle营销云与微信集成,打造个性化体验

    Oracle营销云与微信集成,打造个性化体验 为了让市场营销人员在全球成长最快速的社交媒体平台之一微信(WeChat)上迅速有效地针对目标客户进行互动和关系维护,甲骨文今日宣布,将Oracle营销云( ...

  8. 后疫情时代,VR云游打造个性化云服务

    后疫情时代,线上经济引导着市场转型升级,"云对接"."云洽谈"."云购物"等模式已然成为我们社会发展的主要趋势.近年来,各地也都在积极的推进 ...

  9. 黑人电动牙刷研发新品打造个性化刷牙体验

    黑人牙刷自2017年进军电动牙刷市场,便受到消费者的广泛青睐.其首款电动牙刷"黑人声波深洁ET1电动牙刷"开启了科技助力口腔健康的新纪元.此后,黑人品牌再接再厉,经过研发部门精心设 ...

  10. 两个系统交互方式有几种_创新性OriginOS系统,打造个性化交互方式,很给力

    vivo近日最大的事件就是全新系统#OriginOS#的发布了,该系统与传统安卓系统完全不同,是一款全面升级的创新性系统!其带来的华容网格.原子组件.行为壁纸.变形器以及交互池等功能特性都进行了全方位 ...

最新文章

  1. 2018-2019-1 20165318 20165322 20165326 实验四 外设驱动程序设计
  2. 推荐两个插件DPack, Resharper
  3. UA MATH567 高维统计专题3 含L1-norm的凸优化4 Nesterov方法与Accelerate Proximal Gradient
  4. 谁是卧底的Android应用 (原型源码)
  5. 响应式设计的真正挑战:RSS
  6. oracle自动把SID给改了,Oracle SID修改方式的详解
  7. 数据结构与算法(一)——排序
  8. STM32F103:二.(2)串口控制LED
  9. 韩国Hana银行将建立试点验证CBDC技术
  10. 宽字节与多字节之间的转换
  11. Franka Emika机械臂快速入门教程
  12. 幽暗镰刀:隐私安全下的收割者们
  13. windows server2019安装SQLServer
  14. python线程池学习
  15. 快乐大本营html5小游戏,快乐大本营小游戏规则-新年小游戏.doc
  16. 解决VIVADO ZYNQ编译提示PS引脚约束警告
  17. lotus-miner 元数据备份
  18. GrabCut算法、物体显著性检测
  19. latex 表格引用出错 出现?? You have referenced something which has not yet been labelled
  20. CISP——关于网络安全法(分享笔记)

热门文章

  1. 深度对话“百度超级链” | 链上存证,司法效率助推器
  2. wpa_supplicant wps手册的翻译
  3. RedHat Linux各版本汇总
  4. 配置绿色版的editplus
  5. EditPlus 3.7 中文版已经发布
  6. Axure RP 9下载安装
  7. 中国省份-市级城市数组
  8. 小米浏览器保存的html文件怎么打开方式,怎么将小米手机浏览器中的网页设置为书签...
  9. android rtmp 播放器下载,android rtmp player 除了播放一般的视频格式 - 下载 - 搜珍网...
  10. Eucalyptus