30分钟学会爬虫 实战演习
混迹博客园那么久,人也很懒。思考了一下还是把这篇文章记录下来。原创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.x.com/Producttxxxx", "https://www.x.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">xx(不要点击其他页签)</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文件 里面
1 (function() { 2 var tempVriable = { 3 apiUrl: "http://localhost:62930/api/Ctrip/InsetSeKa", 4 nowUrl: window.location.href, 5 mainPage: "xxxxx", 6 caiJiePage: "https://www.xxx.com/Color/", 7 }; 8 9 var systemMethod = { 10 Ajax: function(obj) { 11 var objs = $.extend({ 12 dataType: "json", 13 data: obj.data, 14 error: function(xmlHttpRequest, textStatus, errorThrown) { 15 console.group("system.js文件 ajax入口"); 16 console.error(`url:${this.url}`); 17 console.error(`错误原因(默认显示150字):${xmlHttpRequest.responseText}`); 18 console.groupEnd(); 19 console.count("ajax error 错误次数"); 20 }, 21 success: obj.success, 22 url: obj.url, 23 //timeout: 6000, //超时时间设置,单位毫秒 24 type: "get", 25 beforeSend: function(request) { 26 //request.setRequestHeader("Authorization", variableObj.keys); 27 }, 28 //当请求完成之后调用这个函数 29 complete: function (xmlHttpRequest, status) { 30 if (status === 'timeout') { 31 console.error("请求时间超时6秒 问题频繁出现请联系管理员"); 32 // console.trace(); 33 } 34 if (typeof (this.globalAjax) == "undefined") { 35 36 } 37 } 38 }, obj); 39 $.ajax(objs); 40 }, 41 //主页面 42 mainPage: function () { 43 if (tempVriable.nowUrl.indexOf(tempVriable.mainPage) == -1) return; 44 var tempElement = $(".productColors ul").find(".show-color-image"); 45 //注意for循环定义用的let 闭包 注意不要太频繁 控制频率 46 for (let j = 0; j < 10; j++) { 47 setTimeout(function () { 48 let thisInfo = $(tempElement[j]); 49 thisInfo.trigger("click"); 50 }, j * 1000); 51 } 52 }, 53 //采集页面 54 sendCaiJiePage: function() { 55 if (tempVriable.nowUrl.indexOf(tempVriable.caiJiePage) > -1) { 56 let tempName = $(".SimpleColorBlock h1")[0].childNodes, 57 RGB = $(".cmyk"), 58 tableDom = $(".block-detail table td"); 59 //采集的数据 60 var data = { 61 TPX: tempName[0].textContent, 62 colorName: tempName[2].textContent, 63 R: RGB[0].innerText, 64 G: RGB[1].innerText, 65 B: RGB[2].innerText, 66 Hex: tableDom[6].innerText 67 }; 68 //发送请求 69 systemMethod.Ajax({ 70 data: data, 71 url: tempVriable.apiUrl, 72 success: function (json) { 73 if (json != undefined && json.Result == 0) { 74 systemMethod.closePage(); 75 } else { 76 console.error(`api 500${json}`); 77 } 78 } 79 }); 80 } 81 }, 82 //窗口关闭 释放资源 83 closePage: ()=>{ 84 window.opener = null; 85 window.open("", "_self", ""); 86 window.close(); 87 }, 88 //初始化入口 89 Init: function () { 90 //打印控制台日志 91 setTimeout(() => { 92 console.clear(); 93 if (tempVriable.nowUrl.indexOf(tempVriable.mainPage) > -1) { 94 console.log('%c 页面启动成功-内部使用', 'color:red;'); 95 } 96 if (tempVriable.nowUrl.indexOf(tempVriable.caiJiePage) > -1) { 97 console.group('页面启动成功-内部使用'); 98 console.log('%c 页面启动成功-内部使用', 'color:red;'); 99 console.groupEnd(); 100 } 101 }, 200); 102 103 //入口页面 防止第3方页面未加载完 延迟 104 setTimeout(() => { 105 systemMethod.setData(); 106 }, 2000); 107 108 //采集页面 防止第3方页面未加载完成延迟 109 setTimeout(() => { 110 systemMethod.sendCaiJiePage(); 111 }, 2000); 112 }, 113 registeEevent: function() { 114 115 } 116 }; 117 systemMethod.Init(); 118 })();
结果:
附加到google插件,然后打开自己的页面吧 去见证这个奇迹
花了40分钟大功告成
总结:建好数据库,一个接口(这些对我们来说都是5分钟的事情)。
1个:manifest.json 文件 格式按规定写。依葫芦画瓢 不要问为什么 google的规矩
js文件 想怎么写就怎么写 是不是很简单。30分钟你看可以吗?
3:细节 后台打印 记录日志 前台打印记录日志, 可能某一些采集的页面 在实现模拟人工操作 可能会复杂一点 。这个只能多花时间了。
4:可能某一些反爬虫的 页面 有很多限制。比如说访问太频繁 ,页面故意制造一线逻辑 数据获取麻烦 比如说 (自己体验的携程的机票数据) 可能是自己水平有限 携程的反爬虫 做的还是可以 。
5:你的爬虫来源的对方的成功的 。最高的反爬虫就是放对方一码 都是码农 何必为难自己。
6:缺点 需要打开浏览器 毕竟他的名字是叫google插件
补充知识:如果你想跟详细的了解 google插件 https://github.com/sxei/chrome-plugin-demo
如果对你有帮助 帮忙推荐一下。如果你有什么问题也可以留言。