@Belinda
2017-12-05T08:58:28.000000Z
字数 6132
阅读 1352
爬虫项目原理:通过用户账号信息授权登录或则用户扫码登录,在 box.exe 里模拟用户登录需要爬取的网站,例如京东网站。现爬取用户信息有两种方案,一、用选择器获取到需要的 dom 元素,通过text()获取节点用户信息。二、如果需要爬取的网站没有做反扒机制,我们可以通过直接 ajax 相应的接口,直接拿到 json 格式的数据
首先你需要注册阿里 code 的账号,将账号告知付老板开通拉取代码的权限,开通权限之后你需要克隆3个项目的代码,分别是:
//boxit.visitors 后面跟的属性要和你在数据库里添加的 kinds 字段一致boxit.visitors.jd = (function () {// 在这里写爬虫逻辑// 当页面的 url 路径变化会触发这个函数function on_task_updated(task, updates) {}// 输入账户信息,点击登录按钮的一刻触发function prepare_input(task, updates, fname) {}// 输入账户信息,点击登录按钮的一刻触发function finish_input(task, updates) {}// 完成爬取任务,box.exe 关闭的时候触发function on_finish(task) {}return {url: 'https://passport.jd.com/uc/login?redirectURL=https%3A%2F%2Fhome.jd.com', // box.exe 初始化访问的界面,一般是登录界面on_task_updated: on_task_updated,prepare_input: prepare_input,finish_input: finish_input,on_finish: on_finish,init: {message: '登陆京东官网......',hints: [] //用户界面初始化展示组件内容}}})();
- external.toFile 用于将数据写入 本地文件,便于调试
- external.postUTF8 用于将数据写入到数据库内
- enhanced.logTo 用于写入日志
kind 为爬虫脚本爬取的类型,qr为布尔值,表示是否使用二维码登录,其他参数为用户个人信息,这个连接可以避免反复手动输入用户个人信息(姓名,身份证,手机号,短信验证码),你也可以访问 http://localhost:3000/client.html#kind=jd&agent=agent_bbt&qr=true 这个地址每次你在 boxvisitors 项目里更新了你的爬虫代码之后,你需要手动删除 boxbrowser 这个目录里的文件,否则调试的时候代码不会更新url : boxbrowser在执行该visitor脚本时直接访问的url,也就是数据源网站的初始页面的url,一般为登陆页。
cookie_path:类型为一个直接返回字符串的函数。该字符串相当于cookieId,用于区分cookie,相同cookieId的页面会共用cookie。在boxbrowser的根目录下有对应的cookies目录,该目录下可根据cookieId找到对应的cookie。
ua: 用于配置请求头中的user-agent字段,配置之后boxbrowser中发起的http请求中的user-agent字段都会为该值。
reusable: 布尔值。设置该visitor是否复用。是否复用的含义是,该visitor执行完一个任务之后,不会关闭boxbrowser,在新的相同类型的task进来之后会续用当前boxbrowser。一般在某个数据源的初始化流程比较长的时候设置为true,比如支付宝数据源会经过非常多的重定向才会到登录页并且加载比较多的静态资源,此时就可以将reusable设置为true。在复用的情况下,一般需要在每次任务执行完毕之后将boxbrowser跳转到某个初始页面。
singleton: 布尔值。限定当前boxbrowser是否只能运行当前这个visitor,设置为true时,当该visitor脚本被执行时,会直接杀死其他的visitor进程,并阻止其他的visitor加入,慎用。
init: 关于task对象的初始化设置,之后会合并到原始的task对象中。一般会在该对象中设置初始的提示语和用户界面显示的初始控件。
hints: task中的hints字段为要显示在用户界面上的控件。一般在visitor代码中的开头部分会将可能要用到的控件列表全部列出来赋到一个变量上,要用到的时候直接在该变量上取即可。比如
boxit.visitors.alipay=(function() {var hints = {// ...'username': { name: 'username' , label: '账号' , placeholder: '邮箱/手机号/淘宝会员名' }, 'password': { name: 'password' , label: '密码' }, 'smscode' : { name: 'smscode' , label: '短信验证码'}, 'captcha' : { name: 'captcha' , label: '验证码' }, 'qrimage' : { name: 'qrimage' , label: '' }, 'login' : { name: 'action' , label: '登陆' }, 'next' : { name: 'action' , label: '继续'}, 'progress': { name: 'action' , label: '查看进度'}};// ...})()
boxbrowser会在任务的不同阶段,调用配置对象中声明的对应的函数,并传入task参数,和updates参数,task参数包含完整的任务信息,updates参数包含task参数与上一个阶段中有差异的字段。阶段函数(prepare_input阶段除外)需要返回一个result也就是该阶段的执行结果,随后这个result会被合并到task中。
on_task_updated: 在boxbrowser的url变化的时候会调用该阶段函数,并传入task和updates参数,一般在该阶段中根据url和task对象做任务的分发。
prepare_input: 当前一个阶段执行完毕而且需要与用户产生交互的行为才能继续进行爬取工作的时候,就需要将返回的result中的event字段定义为WAIT_INPUT,并且设置对应的要在用户界面上显示的控件(hints字段),在hints字段中相应的也要设置action控件,来让用户使用来结束输入。在用户输入完毕后就会进入该阶段,该阶段会根据定义的hints中的交互控件依次循环调用,进入该阶段后task对象上的inputs属性会被赋值为key(控件名,也就是hints对象中的name字段)value(用户输入的结果,隐私字段会被加密需要调用external.decrypt(val)进行解密)的形式。该阶段会比普通的阶段函数多接收一个参数fname,代表对应的控件名称,此时就可以根据控件名称和对应的值将用户输入赋值到boxbrowser相应的表单元素中,如果需要模拟用户的输入行为,则需要在该阶段中将boxbrowser中的焦点设置在相应的表单控件上,之后返回键盘的类型字符串(在databox-api文档上查找),之后box程序就会用相应的设备进行模拟键入操作。
finish_input: 在prepare_input的阶段函数全部执行完之后就会进入到该阶段函数。此时应该是用户的输入已经反馈到boxbrowser中了,在这个阶段应该进行登陆或者其他类似的操作。
on_close: 在上一个阶段中爬取工作已经完成并且task中step字段被设置为FINISH时会进入该阶段函数。如果需要做一些日志记录,或者该visitor是可复用的并且需要将url跳转到某个初始的url时,可在该阶段进行。
on_finish: on_close阶段函数执行完就会进入该阶段函数。一般会在该阶段中做一些收尾工作,比如整理数据、将数据从本地文件中读出来存到数据库中等。
可以在boxbrowser的根目录中的logs目录中查看日志,其中有一个boxit.log日志,在其中可以查看boxserver的一些日志,比如从服务端获取visitor脚本、任务的启动日期、任务超时日志等一些信息。
运行visitor脚本,在填写完client.html的各参数并运行后,boxserver会自动在url后面加上任务的id,比如
http://server.mdatabox.cn:3000/client.html#kind=weixin&agent=agent_fuyh&visitor=worker_fuyh&task=aMM7FAWi6YmjACqSy
后面的aMM7FAWi6YmjACqSy即为taskId。可根据taskId在logs目录查找相应的任务日志和一些其他信息,比如截取的二维码图片等。在boxbrowser的tasks目录中也可以根据taskId查找到最后一次保存的task的完整信息和updates(相较于上一次的task信息中的变更信息)。
task字段解析: 这里只介绍一些visitor脚本开发人员需要知道的字段,其他一些保留字段就不介绍了。
_id: 任务id。
kind: 任务类型,比如支付宝为alipay。
kid: 标记被爬取的用户的id,也可以理解为用户账号的概念,比如支付宝取支付宝账号,微信取微信账号。
created_at: 任务被创建的时间。
updated_at: 任务被更新的时间。
agent: 运行任务的agent账号。
visitor_id: 运行任务的visitor账号。
device: 运行任务的visitor的设备id。
visitor_ip: visitor的公网ip。
client_ip: 访问client.html的用户的公网ip。
visitor_local_ip: visitor的内网ip。
dport: 分发器(dispatcher)端口。
message: 显示在用户界面上的提示信息。
hints: 显示在用户界面上表单控件。
ip_proxies: box_browser的ip代理池,因为有时候账号异地登陆或者访问网站的boxbrowser的ip和用户扫二维码的设备的ip不同会有问题,所以会需要做ip代理。
client_location: 通过用户设备ip解析出的用户大概所在地区。
opts: 给开发者使用来暂存一些数据的对象,可以通过该对象在不同的阶段函数里面交换数据来实现相应的功能需求。并且在client.html后面附加的参数也会对应到opts对象中。
visitor_url: 当前阶段boxbrowser停留的url。
event: 当前task所触发的事件。
step: 当前task所处的阶段。
inputs: 上面介绍过了,就是用于存储用户输入的表单数据的对象。
errFound: 错误信息。
visitor 代码中可使用的全局对象因为visitor代码的执行环境就是boxbrowser,所以浏览器中的全局对象都可以使用,不过要注意ie版本的差别。还有一些常用的库被附加在了boxbrowser里,可以在boxbrowser的根目录中的scripts目录中查看(external库除外),主要有以下类库:
external: 一个十分重要的库,封装了许多和系统交互的api,可以在databox-api.html中查看其文档。
enhanced: 也是一个十分重要的库,封住了比较多的浏览器api和external的api。
jquery: 文档,一个dom操作库。
moment: 文档,对时间进行处理的类库。
underscore: 文档,也是个工具库,非常实用。
json: 针对低版本的ie使用的JSON库。
jsencrypt: 文档,用于加解密。