混迹博客园那么久,人也很懒。思考了一下还是把这篇文章记录下来。原创https://www.cnblogs.com/y112102/p/10788564.html。
这里说的是只基于google插件
30分钟
准备知识:javascript, sql(新建一个表就可以了),一个接口webapi(入库数据)。
传统的做法:
1:后台发送一个请求(request),获取输出(response) 然后对输出的结果分析。筛选符合自己业务的数据 (还是不理解的查看 http://www.cnblogs.com/youuuu/archive/2011/06/17/2083714.html)。
2:【难度】数据筛选,后台模拟请求 可能采集的页面涉及到token,登入身份信息....当然我也不会说他不好。一个字麻烦。 系数大。
主角登场:先易后难。
场景:
1:建立好数据库,简单除暴 没啥好说的。
2:一个api接口能插入数据 就可以(接受参数,插入数据库)简单粗暴 没什么逻辑。
3:主角 google插件
1:一个manifest.json文件
2:1个html页面
3:一个js文件
manifest.json:
{ // 清单文件的版本, \"manifest_version\": 2, // 插件的名称 \"name\": \"xxx采集\", // 插件的版本 \"version\": \"1.0\", // 插件描述 \"description\": \"色卡xxx内部使用\", // 作者 \"author\": \"sxei\", // 图标,一般偷懒全部用一个尺寸的也没问题 \"icons\": { \"48\": \"img/icon.png\", \"128\": \"img/icon.png\" }, // 浏览器右上角图标设置,browser_action、page_action、app必须三选一 \"browser_action\": { \"default_icon\": \"img/icon.png\", \"default_popup\": \"popup.html\" }, // 需要直接注入页面的JS \"content_scripts\": [ { //匹配的网站 \"matches\": [ \"https://www.qtccolor.com/Product/FHIP110N.aspx\", \"https://www.qtccolor.com/Color/*\" ], // 多个JS按顺序注入 \"js\": [ \"js/jquery-1.10.2.min.js\", \"js/content-script.js\" ] } ], // 权限申请 (这个很重要 如何没有它 我们的请求是无法跨域的) 有啥就写啥 权限最大化 \"permissions\": [ \"contextMenus\", \"tabs\", \"notifications\", \"webRequest\", // web请求 \"webRequestBlocking\", \"storage\", \"http://*/*\", \"https://*/*\" ] }
2:html页面和 manifest.json 【browser_action】里面的名称保持一致就好popup.html
html内容:根据业务需求(我一般弄一个链接打开要采集的页面 和一些说明信息)原因:某一些网站有很多域名 同一个业务地址栏不同。干脆指定
如图:
<!DOCTYPE html> <html> <head> <title>【xxx】</title> <meta charset=\"utf-8\"/> <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" /> <style type=\"text/css\" > body { padding-bottom: 20px; font-family: \"Helvetica Neue\",Helvetica,Arial,sans-serif; font-size: 14px; line-height: 1.42857143; color: #333; background-color: #fff; margin: 0; width: 200px; text-align: center; } @-webkit-keyframes shake{ 0%{ opacity: 1; } 50%{ opacity: 0.5; } 100%{ opacity: 1; } } @keyframes shake{ 0%{ opacity: 1; } 50%{ opacity: 0.5; } 100%{ opacity: 1; } } .shake{ -webkit-animation: shake 2s infinite; animation: shake 2s infinite; color:red; } </style> </head> <body> <h4>【x入口】</h4> <a href=\"#\" id=\"openCtripWindow\">色卡(不要点击其他页签)</a> <h5 class=\"shake\">采集失败请联系电脑部</h5> <h5 class=\"shake\">提示:x内部使用</h5> <script type=\"text/javascript\" src=\"js/jquery-1.10.2.min.js\"></script> <script type=\"text/javascript\" src=\"js/popup.js\"></script> </body> </html>
js:(为了方便省事 用的jquery)我都写上注释了。写在 manifest.json 配置 注入的 content-script.js文件 里面
(function() { var tempVriable = { //接口 apiUrl: \"http://localhost:62930/api/Ctrip/InsetSeKa\", nowUrl: window.location.href, mainPage: \"xx\", //采集的页面 caiJiePage: \"https://www.xxx.com/Color/\" }; var systemMethod = { //ajax 没什么好的说的 Ajax: function(obj) { var objs = $.extend({ dataType: \"json\", data: obj.data, error: function(xmlHttpRequest, textStatus, errorThrown) { debugger; console.log(XMLHttpRequest + \"-----\" + textStatus + \"---\" + errorThrown); }, success: obj.success, url: obj.url, type: \"get\", beforeSend: function(request) { } }, obj); $.ajax(objs); }, //采集页面入口 模拟点击打不不同的链接, 不同的链接页面 setData: function () { var tempElement = $(\".productColors ul\").find(\".show-color-image\"); for (var i = 0; i < tempElement.length; i++) { let thisInfo = $(tempElement[i]); //循环中延迟 防止打开频繁 (function (i) { setTimeout(function () { //模拟操作 不同的业务这里的逻辑可能不一样 thisInfo.trigger(\"click\"); }, i * 1000); })(i); } }, //成功后关闭窗口 closePage: function() { window.opener = null; window.open(\"\", \"_self\", \"\"); window.close(); }, Init: function () { //注册成功 控制台打印日志 setTimeout(() => { console.clear(); if (tempVriable.nowUrl.indexOf(tempVriable.mainPage) > -1) { console.group(\'xxx\'); console.log(\'%c xxx 页面启动成功-内部使用\', \'color:red;\'); console.groupEnd(); } if (tempVriable.nowUrl.indexOf(tempVriable.caiJiePage) > -1) { console.group(\'xxx潘通\'); console.log(\'%c xxxx Color页面启动成功-内部使用\', \'color:red;\'); console.groupEnd(); } }, 200); //入口页面 setTimeout(() => { if (tempVriable.nowUrl.indexOf(tempVriable.mainPage) > -1) { systemMethod.setData(); } }, 2000); //采集页面 数据入库 发送请求(根据自己的需求) setTimeout(() => { if (tempVriable.nowUrl.indexOf(tempVriable.caiJiePage) > -1) { //就和我们平常写js一样 需要哪些数据 获取到哪些节点 let tempName = $(\".SimpleColorBlock h1\")[0].childNodes; let TPX = tempName[0].textContent; let colorName = tempName[2].textContent; let RGB = $(\".cmyk\"), tableDom = $(\".block-detail table td\"); var R = RGB[0].innerText, G = RGB[1].innerText, B = RGB[2].innerText, Hex = tableDom[6].innerText; var data = { TPX: TPX, colorName: colorName, R: R, G: G, B: B, Hex: Hex }; systemMethod.Ajax({ data: data, url: tempVriable.apiUrl, success: function (json) { if (json != undefined && json.Result == 0) { //成功后关闭页面 systemMethod.closePage(); } else { console.error(\'\'); console.group(\'采集失败\'); //记录错误信息 后台也打印记录日志 console.log(`%c 当然url${this.url}\', \'color:red;`); console.groupEnd(); } } }); } }, 2000); }, registeEevent: function() { } }; systemMethod.Init(); })();
结果:
附加到google插件,然后打开自己的页面吧 去见证这个奇迹
花了40分钟大功告成
总结:建好数据库,一个接口(这些对我们来说都是5分钟的事情)。
1个:manifest.json 文件 格式按规定写。依葫芦画瓢 不要问为什么 google的规矩
js文件 想怎么写就怎么写 是不是很简单。30分钟你看可以吗?
3:细节 后台打印 记录日志 前台打印记录日志, 可能某一些采集的页面 在实现模拟人工操作 可能会复杂一点 。这个只能多花时间了。
4:可能某一些反爬虫的 页面 有很多限制。比如说访问太频繁 ,页面故意制造一线逻辑 数据获取麻烦 比如说 (自己体验的携程的机票数据) 可能是自己水平有限 携程的反爬虫 做的还是可以 。
5:你的爬虫来源的对方的成功的 。最高的反爬虫就是放对方一码 都是码农 何必为难自己。
6:缺点 需要打开浏览器 毕竟他的名字是叫google插件
补充知识:google插件的 详细补充 api对你来说 使用都不是事情
https://github.com/sxei/chrome-plugin-demo