├── .gitignore ├── 2plaintext ├── README.md └── formatFun.py ├── LICENSE ├── README.md ├── database ├── README.md └── database.sql ├── nodejs_query ├── README.md ├── annc_server.js ├── connection.js ├── controllers.js ├── func.js ├── log.js ├── package.json ├── public │ ├── images │ │ ├── doc.png │ │ ├── pdf.png │ │ └── txt.png │ ├── javascripts │ │ ├── bootstrap.min.js │ │ └── jquery.min.js │ └── stylesheets │ │ └── bootstrap.min.css ├── routes.js └── views │ └── index.html └── python_scraw ├── README.md ├── annc ├── README.md ├── annc │ ├── __init__.py │ ├── items.py │ ├── middlewares.py │ ├── pipelines.py │ ├── settings.py │ └── spiders │ │ ├── __init__.py │ │ └── anncSpider.py └── scrapy.cfg ├── cninfo_main.py └── config.cfg /.gitignore: -------------------------------------------------------------------------------- 1 | python_scraw/annc/annc/*.pyc 2 | python_scraw/annc/annc/spiders/*.pyc 3 | -------------------------------------------------------------------------------- /2plaintext/README.md: -------------------------------------------------------------------------------- 1 | ### 股票公告的文件类型中大部分是pdf,还有一些doc和docx的。这里提供了一些转为文本的方法。 2 | 3 | #### docx 4 | * 在python中安装:pip install python-docx,然后调用formatFun.py中的dx2t 5 | 6 | #### doc 7 | * 在linux下安装catdoc工具(catdoc只能在linux下用)。然后调用formatFun.py中的d2t 8 | 9 | #### pdf 10 | * 在python中安装 pip install pdfminer,然后调用formatFun.py中的p2t 11 | 12 | #### formatFun.py中的参数,文件在当前目录下就写文件名即可,如果不是,则用绝对路径指明文件名 13 | 14 | ### 转换效率不是很高。有兴趣的同学可以试一试Apache的Tika,解析的种类更丰富,但效率没测试过 -------------------------------------------------------------------------------- /2plaintext/formatFun.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import sys 3 | import time 4 | import os 5 | # 用于pdf文件的处理 6 | from pdfminer.pdfparser import PDFParser 7 | from pdfminer.pdfdocument import PDFDocument 8 | from pdfminer.pdfpage import PDFPage 9 | from pdfminer.pdfpage import PDFTextExtractionNotAllowed 10 | from pdfminer.pdfinterp import PDFResourceManager 11 | from pdfminer.pdfinterp import PDFPageInterpreter 12 | from pdfminer.pdfdevice import PDFDevice 13 | from pdfminer.layout import * 14 | from pdfminer.converter import PDFPageAggregator 15 | 16 | ###########################################把pdf转为txt################################################ 17 | def p2t(sourcefile, outfile): 18 | with open(sourcefile, 'rb') as fp: 19 | # 来创建一个pdf文档分析器 20 | parser = PDFParser(fp) 21 | #创建一个PDF文档对象存储文档结构 22 | try: 23 | document = PDFDocument(parser) 24 | except: 25 | print(sourcefile + ' :pdf未正确下载') 26 | # 检查文件是否允许文本提取 27 | else: 28 | if not document.is_extractable: 29 | print(sourcefile + ' :不允许提取文本') 30 | # 创建一个PDF资源管理器对象来存储共赏资源 31 | rsrcmgr=PDFResourceManager() 32 | # 设定参数进行分析 33 | laparams=LAParams() 34 | # 创建一个PDF设备对象 35 | # device=PDFDevice(rsrcmgr) 36 | device=PDFPageAggregator(rsrcmgr,laparams=laparams) 37 | # 创建一个PDF解释器对象 38 | interpreter=PDFPageInterpreter(rsrcmgr,device) 39 | # 处理每一页 40 | for page in PDFPage.create_pages(document): 41 | interpreter.process_page(page) 42 | # 接受该页面的LTPage对象 43 | layout=device.get_result() 44 | for x in layout: 45 | if(isinstance(x,LTTextBoxHorizontal)): 46 | with open(outfile, 'a') as f: 47 | f.write(x.get_text().encode('utf-8')+'\n') 48 | print(sourcefile + ' 已转为 ' + outfile) 49 | 50 | ##############################################把doc转为txt############################################## 51 | # 调用之前要确保你在linux 下装了catdoc 52 | def d2t(sourcefile, outfile): 53 | try: 54 | f =open(outfile, 'w+') 55 | content = os.popen("catdoc -s='utf-8' -d='utf-8' " + sourcefile).read() 56 | f.write(content) 57 | f.close() 58 | except: 59 | print(sourcefile + ' :doc文件转换失败') 60 | else: 61 | print(sourcefile + '已转为 ' + outfile) 62 | 63 | 64 | ############################################### 把docx转为txt############################################# 65 | def dx2t(sourcefile, outfile): 66 | import docx 67 | try: 68 | fullText = [] 69 | doc = docx.Document(sourcefile) 70 | f = open(outfile, 'w+') 71 | paras = doc.paragraphs 72 | for p in paras: 73 | fullText.append(p.text) 74 | f.write('\n'.join(fullText)) 75 | f.close() 76 | except: 77 | print(sourcefile + ' :doc文件转换失败') 78 | else: 79 | print(sourcefile + '已转为 ' + outfile) -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 focsu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # China_stock_announcement 2 | ## 简介 3 | * 该项目通过python脚本从巨潮网络的服务器获取中国股市公告(上市公司和监管机构),公告信息存入数据库,公告文件下载到本地 4 | * 还可支持文本抽取, 网页,API的查询和读取等功能 5 | * python实现公告爬取下载,nodejs搭建网络服务,提供api和网页展示 6 | 7 | ## 文件说明 8 | * database/: 存放数据库的sql文件,可以用shell命令执行,创建数据库和数据表 9 | * nodejs_query/: 存放node服务的代码 10 | * python_scraw/: 存放python爬虫的程序, cninfo_main.py可实现较为全面的功能,annc文件下是用scrapy框架写的爬虫,正在逐渐完善,以后会替代cninfo_main.py 11 | * 2plaintext/: 存放一个python小脚本,用于将pdf、doc、docx文件转为纯文本文件 12 | 13 | ## 使用 14 | * 准备好MySQL,Python等环境, 参考python_scraw/cninfo_main.py的头引入,下载一些python包 15 | * 进入 database/ 执行 mysql -u $USER -p$PASSWORD 2)throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher, but lower than version 3")}(jQuery),+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one("bsTransitionEnd",function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b(),a.support.transition&&(a.event.special.bsTransitionEnd={bindType:a.support.transition.end,delegateType:a.support.transition.end,handle:function(b){return a(b.target).is(this)?b.handleObj.handler.apply(this,arguments):void 0}})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var c=a(this),e=c.data("bs.alert");e||c.data("bs.alert",e=new d(this)),"string"==typeof b&&e[b].call(c)})}var c='[data-dismiss="alert"]',d=function(b){a(b).on("click",c,this.close)};d.VERSION="3.3.6",d.TRANSITION_DURATION=150,d.prototype.close=function(b){function c(){g.detach().trigger("closed.bs.alert").remove()}var e=a(this),f=e.attr("data-target");f||(f=e.attr("href"),f=f&&f.replace(/.*(?=#[^\s]*$)/,""));var g=a(f);b&&b.preventDefault(),g.length||(g=e.closest(".alert")),g.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(g.removeClass("in"),a.support.transition&&g.hasClass("fade")?g.one("bsTransitionEnd",c).emulateTransitionEnd(d.TRANSITION_DURATION):c())};var e=a.fn.alert;a.fn.alert=b,a.fn.alert.Constructor=d,a.fn.alert.noConflict=function(){return a.fn.alert=e,this},a(document).on("click.bs.alert.data-api",c,d.prototype.close)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof b&&b;e||d.data("bs.button",e=new c(this,f)),"toggle"==b?e.toggle():b&&e.setState(b)})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.isLoading=!1};c.VERSION="3.3.6",c.DEFAULTS={loadingText:"loading..."},c.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",null==f.resetText&&d.data("resetText",d[e]()),setTimeout(a.proxy(function(){d[e](null==f[b]?this.options[b]:f[b]),"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c))},this),0)},c.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")?(c.prop("checked")&&(a=!1),b.find(".active").removeClass("active"),this.$element.addClass("active")):"checkbox"==c.prop("type")&&(c.prop("checked")!==this.$element.hasClass("active")&&(a=!1),this.$element.toggleClass("active")),c.prop("checked",this.$element.hasClass("active")),a&&c.trigger("change")}else this.$element.attr("aria-pressed",!this.$element.hasClass("active")),this.$element.toggleClass("active")};var d=a.fn.button;a.fn.button=b,a.fn.button.Constructor=c,a.fn.button.noConflict=function(){return a.fn.button=d,this},a(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(c){var d=a(c.target);d.hasClass("btn")||(d=d.closest(".btn")),b.call(d,"toggle"),a(c.target).is('input[type="radio"]')||a(c.target).is('input[type="checkbox"]')||c.preventDefault()}).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',function(b){a(b.target).closest(".btn").toggleClass("focus",/^focus(in)?$/.test(b.type))})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b),g="string"==typeof b?b:f.slide;e||d.data("bs.carousel",e=new c(this,f)),"number"==typeof b?e.to(b):g?e[g]():f.interval&&e.pause().cycle()})}var c=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=null,this.sliding=null,this.interval=null,this.$active=null,this.$items=null,this.options.keyboard&&this.$element.on("keydown.bs.carousel",a.proxy(this.keydown,this)),"hover"==this.options.pause&&!("ontouchstart"in document.documentElement)&&this.$element.on("mouseenter.bs.carousel",a.proxy(this.pause,this)).on("mouseleave.bs.carousel",a.proxy(this.cycle,this))};c.VERSION="3.3.6",c.TRANSITION_DURATION=600,c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0,keyboard:!0},c.prototype.keydown=function(a){if(!/input|textarea/i.test(a.target.tagName)){switch(a.which){case 37:this.prev();break;case 39:this.next();break;default:return}a.preventDefault()}},c.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(a){return this.$items=a.parent().children(".item"),this.$items.index(a||this.$active)},c.prototype.getItemForDirection=function(a,b){var c=this.getItemIndex(b),d="prev"==a&&0===c||"next"==a&&c==this.$items.length-1;if(d&&!this.options.wrap)return b;var e="prev"==a?-1:1,f=(c+e)%this.$items.length;return this.$items.eq(f)},c.prototype.to=function(a){var b=this,c=this.getItemIndex(this.$active=this.$element.find(".item.active"));return a>this.$items.length-1||0>a?void 0:this.sliding?this.$element.one("slid.bs.carousel",function(){b.to(a)}):c==a?this.pause().cycle():this.slide(a>c?"next":"prev",this.$items.eq(a))},c.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},c.prototype.next=function(){return this.sliding?void 0:this.slide("next")},c.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},c.prototype.slide=function(b,d){var e=this.$element.find(".item.active"),f=d||this.getItemForDirection(b,e),g=this.interval,h="next"==b?"left":"right",i=this;if(f.hasClass("active"))return this.sliding=!1;var j=f[0],k=a.Event("slide.bs.carousel",{relatedTarget:j,direction:h});if(this.$element.trigger(k),!k.isDefaultPrevented()){if(this.sliding=!0,g&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var l=a(this.$indicators.children()[this.getItemIndex(f)]);l&&l.addClass("active")}var m=a.Event("slid.bs.carousel",{relatedTarget:j,direction:h});return a.support.transition&&this.$element.hasClass("slide")?(f.addClass(b),f[0].offsetWidth,e.addClass(h),f.addClass(h),e.one("bsTransitionEnd",function(){f.removeClass([b,h].join(" ")).addClass("active"),e.removeClass(["active",h].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger(m)},0)}).emulateTransitionEnd(c.TRANSITION_DURATION)):(e.removeClass("active"),f.addClass("active"),this.sliding=!1,this.$element.trigger(m)),g&&this.cycle(),this}};var d=a.fn.carousel;a.fn.carousel=b,a.fn.carousel.Constructor=c,a.fn.carousel.noConflict=function(){return a.fn.carousel=d,this};var e=function(c){var d,e=a(this),f=a(e.attr("data-target")||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""));if(f.hasClass("carousel")){var g=a.extend({},f.data(),e.data()),h=e.attr("data-slide-to");h&&(g.interval=!1),b.call(f,g),h&&f.data("bs.carousel").to(h),c.preventDefault()}};a(document).on("click.bs.carousel.data-api","[data-slide]",e).on("click.bs.carousel.data-api","[data-slide-to]",e),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var c=a(this);b.call(c,c.data())})})}(jQuery),+function(a){"use strict";function b(b){var c,d=b.attr("data-target")||(c=b.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"");return a(d)}function c(b){return this.each(function(){var c=a(this),e=c.data("bs.collapse"),f=a.extend({},d.DEFAULTS,c.data(),"object"==typeof b&&b);!e&&f.toggle&&/show|hide/.test(b)&&(f.toggle=!1),e||c.data("bs.collapse",e=new d(this,f)),"string"==typeof b&&e[b]()})}var d=function(b,c){this.$element=a(b),this.options=a.extend({},d.DEFAULTS,c),this.$trigger=a('[data-toggle="collapse"][href="#'+b.id+'"],[data-toggle="collapse"][data-target="#'+b.id+'"]'),this.transitioning=null,this.options.parent?this.$parent=this.getParent():this.addAriaAndCollapsedClass(this.$element,this.$trigger),this.options.toggle&&this.toggle()};d.VERSION="3.3.6",d.TRANSITION_DURATION=350,d.DEFAULTS={toggle:!0},d.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},d.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b,e=this.$parent&&this.$parent.children(".panel").children(".in, .collapsing");if(!(e&&e.length&&(b=e.data("bs.collapse"),b&&b.transitioning))){var f=a.Event("show.bs.collapse");if(this.$element.trigger(f),!f.isDefaultPrevented()){e&&e.length&&(c.call(e,"hide"),b||e.data("bs.collapse",null));var g=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[g](0).attr("aria-expanded",!0),this.$trigger.removeClass("collapsed").attr("aria-expanded",!0),this.transitioning=1;var h=function(){this.$element.removeClass("collapsing").addClass("collapse in")[g](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return h.call(this);var i=a.camelCase(["scroll",g].join("-"));this.$element.one("bsTransitionEnd",a.proxy(h,this)).emulateTransitionEnd(d.TRANSITION_DURATION)[g](this.$element[0][i])}}}},d.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse in").attr("aria-expanded",!1),this.$trigger.addClass("collapsed").attr("aria-expanded",!1),this.transitioning=1;var e=function(){this.transitioning=0,this.$element.removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse")};return a.support.transition?void this.$element[c](0).one("bsTransitionEnd",a.proxy(e,this)).emulateTransitionEnd(d.TRANSITION_DURATION):e.call(this)}}},d.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()},d.prototype.getParent=function(){return a(this.options.parent).find('[data-toggle="collapse"][data-parent="'+this.options.parent+'"]').each(a.proxy(function(c,d){var e=a(d);this.addAriaAndCollapsedClass(b(e),e)},this)).end()},d.prototype.addAriaAndCollapsedClass=function(a,b){var c=a.hasClass("in");a.attr("aria-expanded",c),b.toggleClass("collapsed",!c).attr("aria-expanded",c)};var e=a.fn.collapse;a.fn.collapse=c,a.fn.collapse.Constructor=d,a.fn.collapse.noConflict=function(){return a.fn.collapse=e,this},a(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(d){var e=a(this);e.attr("data-target")||d.preventDefault();var f=b(e),g=f.data("bs.collapse"),h=g?"toggle":e.data();c.call(f,h)})}(jQuery),+function(a){"use strict";function b(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}function c(c){c&&3===c.which||(a(e).remove(),a(f).each(function(){var d=a(this),e=b(d),f={relatedTarget:this};e.hasClass("open")&&(c&&"click"==c.type&&/input|textarea/i.test(c.target.tagName)&&a.contains(e[0],c.target)||(e.trigger(c=a.Event("hide.bs.dropdown",f)),c.isDefaultPrevented()||(d.attr("aria-expanded","false"),e.removeClass("open").trigger(a.Event("hidden.bs.dropdown",f)))))}))}function d(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new g(this)),"string"==typeof b&&d[b].call(c)})}var e=".dropdown-backdrop",f='[data-toggle="dropdown"]',g=function(b){a(b).on("click.bs.dropdown",this.toggle)};g.VERSION="3.3.6",g.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=b(e),g=f.hasClass("open");if(c(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a(document.createElement("div")).addClass("dropdown-backdrop").insertAfter(a(this)).on("click",c);var h={relatedTarget:this};if(f.trigger(d=a.Event("show.bs.dropdown",h)),d.isDefaultPrevented())return;e.trigger("focus").attr("aria-expanded","true"),f.toggleClass("open").trigger(a.Event("shown.bs.dropdown",h))}return!1}},g.prototype.keydown=function(c){if(/(38|40|27|32)/.test(c.which)&&!/input|textarea/i.test(c.target.tagName)){var d=a(this);if(c.preventDefault(),c.stopPropagation(),!d.is(".disabled, :disabled")){var e=b(d),g=e.hasClass("open");if(!g&&27!=c.which||g&&27==c.which)return 27==c.which&&e.find(f).trigger("focus"),d.trigger("click");var h=" li:not(.disabled):visible a",i=e.find(".dropdown-menu"+h);if(i.length){var j=i.index(c.target);38==c.which&&j>0&&j--,40==c.which&&jdocument.documentElement.clientHeight;this.$element.css({paddingLeft:!this.bodyIsOverflowing&&a?this.scrollbarWidth:"",paddingRight:this.bodyIsOverflowing&&!a?this.scrollbarWidth:""})},c.prototype.resetAdjustments=function(){this.$element.css({paddingLeft:"",paddingRight:""})},c.prototype.checkScrollbar=function(){var a=window.innerWidth;if(!a){var b=document.documentElement.getBoundingClientRect();a=b.right-Math.abs(b.left)}this.bodyIsOverflowing=document.body.clientWidth
',trigger:"hover focus",title:"",delay:0,html:!1,container:!1,viewport:{selector:"body",padding:0}},c.prototype.init=function(b,c,d){if(this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d),this.$viewport=this.options.viewport&&a(a.isFunction(this.options.viewport)?this.options.viewport.call(this,this.$element):this.options.viewport.selector||this.options.viewport),this.inState={click:!1,hover:!1,focus:!1},this.$element[0]instanceof document.constructor&&!this.options.selector)throw new Error("`selector` option must be specified when initializing "+this.type+" on the window.document object!");for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focusin",i="hover"==g?"mouseleave":"focusout";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},c.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},c.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusin"==b.type?"focus":"hover"]=!0),c.tip().hasClass("in")||"in"==c.hoverState?void(c.hoverState="in"):(clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?void(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show)):c.show())},c.prototype.isInStateTrue=function(){for(var a in this.inState)if(this.inState[a])return!0;return!1},c.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusout"==b.type?"focus":"hover"]=!1),c.isInStateTrue()?void 0:(clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?void(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide)):c.hide())},c.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(b);var d=a.contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(b.isDefaultPrevented()||!d)return;var e=this,f=this.tip(),g=this.getUID(this.type);this.setContent(),f.attr("id",g),this.$element.attr("aria-describedby",g),this.options.animation&&f.addClass("fade");var h="function"==typeof this.options.placement?this.options.placement.call(this,f[0],this.$element[0]):this.options.placement,i=/\s?auto?\s?/i,j=i.test(h);j&&(h=h.replace(i,"")||"top"),f.detach().css({top:0,left:0,display:"block"}).addClass(h).data("bs."+this.type,this),this.options.container?f.appendTo(this.options.container):f.insertAfter(this.$element),this.$element.trigger("inserted.bs."+this.type);var k=this.getPosition(),l=f[0].offsetWidth,m=f[0].offsetHeight;if(j){var n=h,o=this.getPosition(this.$viewport);h="bottom"==h&&k.bottom+m>o.bottom?"top":"top"==h&&k.top-mo.width?"left":"left"==h&&k.left-lg.top+g.height&&(e.top=g.top+g.height-i)}else{var j=b.left-f,k=b.left+f+c;jg.right&&(e.left=g.left+g.width-k)}return e},c.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||("function"==typeof c.title?c.title.call(b[0]):c.title)},c.prototype.getUID=function(a){do a+=~~(1e6*Math.random());while(document.getElementById(a));return a},c.prototype.tip=function(){if(!this.$tip&&(this.$tip=a(this.options.template),1!=this.$tip.length))throw new Error(this.type+" `template` option must consist of exactly 1 top-level element!");return this.$tip},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},c.prototype.enable=function(){this.enabled=!0},c.prototype.disable=function(){this.enabled=!1},c.prototype.toggleEnabled=function(){this.enabled=!this.enabled},c.prototype.toggle=function(b){var c=this;b&&(c=a(b.currentTarget).data("bs."+this.type),c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c))),b?(c.inState.click=!c.inState.click,c.isInStateTrue()?c.enter(c):c.leave(c)):c.tip().hasClass("in")?c.leave(c):c.enter(c)},c.prototype.destroy=function(){var a=this;clearTimeout(this.timeout),this.hide(function(){a.$element.off("."+a.type).removeData("bs."+a.type),a.$tip&&a.$tip.detach(),a.$tip=null,a.$arrow=null,a.$viewport=null})};var d=a.fn.tooltip;a.fn.tooltip=b,a.fn.tooltip.Constructor=c,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=d,this}}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof b&&b;(e||!/destroy|hide/.test(b))&&(e||d.data("bs.popover",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.init("popover",a,b)};if(!a.fn.tooltip)throw new Error("Popover requires tooltip.js");c.VERSION="3.3.6",c.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:''}),c.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),c.prototype.constructor=c,c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content").children().detach().end()[this.options.html?"string"==typeof c?"html":"append":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},c.prototype.hasContent=function(){return this.getTitle()||this.getContent()},c.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")};var d=a.fn.popover;a.fn.popover=b,a.fn.popover.Constructor=c,a.fn.popover.noConflict=function(){return a.fn.popover=d,this}}(jQuery),+function(a){"use strict";function b(c,d){this.$body=a(document.body),this.$scrollElement=a(a(c).is(document.body)?window:c),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||"")+" .nav li > a",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on("scroll.bs.scrollspy",a.proxy(this.process,this)),this.refresh(),this.process()}function c(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})}b.VERSION="3.3.6",b.DEFAULTS={offset:10},b.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},b.prototype.refresh=function(){var b=this,c="offset",d=0;this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight(),a.isWindow(this.$scrollElement[0])||(c="position",d=this.$scrollElement.scrollTop()),this.$body.find(this.selector).map(function(){var b=a(this),e=b.data("target")||b.attr("href"),f=/^#./.test(e)&&a(e);return f&&f.length&&f.is(":visible")&&[[f[c]().top+d,e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){b.offsets.push(this[0]),b.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.getScrollHeight(),d=this.options.offset+c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(this.scrollHeight!=c&&this.refresh(),b>=d)return g!=(a=f[f.length-1])&&this.activate(a);if(g&&b=e[a]&&(void 0===e[a+1]||b .dropdown-menu > .active").removeClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!1),b.addClass("active").find('[data-toggle="tab"]').attr("aria-expanded",!0),h?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu").length&&b.closest("li.dropdown").addClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!0),e&&e()}var g=d.find("> .active"),h=e&&a.support.transition&&(g.length&&g.hasClass("fade")||!!d.find("> .fade").length);g.length&&h?g.one("bsTransitionEnd",f).emulateTransitionEnd(c.TRANSITION_DURATION):f(),g.removeClass("in")};var d=a.fn.tab;a.fn.tab=b,a.fn.tab.Constructor=c,a.fn.tab.noConflict=function(){return a.fn.tab=d,this};var e=function(c){c.preventDefault(),b.call(a(this),"show")};a(document).on("click.bs.tab.data-api",'[data-toggle="tab"]',e).on("click.bs.tab.data-api",'[data-toggle="pill"]',e)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof b&&b;e||d.data("bs.affix",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.options=a.extend({},c.DEFAULTS,d),this.$target=a(this.options.target).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(b),this.affixed=null,this.unpin=null,this.pinnedOffset=null,this.checkPosition()};c.VERSION="3.3.6",c.RESET="affix affix-top affix-bottom",c.DEFAULTS={offset:0,target:window},c.prototype.getState=function(a,b,c,d){var e=this.$target.scrollTop(),f=this.$element.offset(),g=this.$target.height();if(null!=c&&"top"==this.affixed)return c>e?"top":!1;if("bottom"==this.affixed)return null!=c?e+this.unpin<=f.top?!1:"bottom":a-d>=e+g?!1:"bottom";var h=null==this.affixed,i=h?e:f.top,j=h?g:b;return null!=c&&c>=e?"top":null!=d&&i+j>=a-d?"bottom":!1},c.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(c.RESET).addClass("affix");var a=this.$target.scrollTop(),b=this.$element.offset();return this.pinnedOffset=b.top-a},c.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},c.prototype.checkPosition=function(){if(this.$element.is(":visible")){var b=this.$element.height(),d=this.options.offset,e=d.top,f=d.bottom,g=Math.max(a(document).height(),a(document.body).height());"object"!=typeof d&&(f=e=d),"function"==typeof e&&(e=d.top(this.$element)),"function"==typeof f&&(f=d.bottom(this.$element));var h=this.getState(g,b,e,f);if(this.affixed!=h){null!=this.unpin&&this.$element.css("top","");var i="affix"+(h?"-"+h:""),j=a.Event(i+".bs.affix");if(this.$element.trigger(j),j.isDefaultPrevented())return;this.affixed=h,this.unpin="bottom"==h?this.getPinnedOffset():null,this.$element.removeClass(c.RESET).addClass(i).trigger(i.replace("affix","affixed")+".bs.affix")}"bottom"==h&&this.$element.offset({top:g-b-f})}};var d=a.fn.affix;a.fn.affix=b,a.fn.affix.Constructor=c,a.fn.affix.noConflict=function(){return a.fn.affix=d,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var c=a(this),d=c.data();d.offset=d.offset||{},null!=d.offsetBottom&&(d.offset.bottom=d.offsetBottom),null!=d.offsetTop&&(d.offset.top=d.offsetTop),b.call(c,d)})})}(jQuery); -------------------------------------------------------------------------------- /nodejs_query/public/javascripts/jquery.min.js: -------------------------------------------------------------------------------- 1 | /*! jQuery v3.1.0 | (c) jQuery Foundation | jquery.org/license */ 2 | !function(a,b){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){"use strict";var c=[],d=a.document,e=Object.getPrototypeOf,f=c.slice,g=c.concat,h=c.push,i=c.indexOf,j={},k=j.toString,l=j.hasOwnProperty,m=l.toString,n=m.call(Object),o={};function p(a,b){b=b||d;var c=b.createElement("script");c.text=a,b.head.appendChild(c).parentNode.removeChild(c)}var q="3.1.0",r=function(a,b){return new r.fn.init(a,b)},s=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,t=/^-ms-/,u=/-([a-z])/g,v=function(a,b){return b.toUpperCase()};r.fn=r.prototype={jquery:q,constructor:r,length:0,toArray:function(){return f.call(this)},get:function(a){return null!=a?a<0?this[a+this.length]:this[a]:f.call(this)},pushStack:function(a){var b=r.merge(this.constructor(),a);return b.prevObject=this,b},each:function(a){return r.each(this,a)},map:function(a){return this.pushStack(r.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(f.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(a<0?b:0);return this.pushStack(c>=0&&c0&&b-1 in a)}var x=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ha(),z=ha(),A=ha(),B=function(a,b){return a===b&&(l=!0),0},C={}.hasOwnProperty,D=[],E=D.pop,F=D.push,G=D.push,H=D.slice,I=function(a,b){for(var c=0,d=a.length;c+~]|"+K+")"+K+"*"),S=new RegExp("="+K+"*([^\\]'\"]*?)"+K+"*\\]","g"),T=new RegExp(N),U=new RegExp("^"+L+"$"),V={ID:new RegExp("^#("+L+")"),CLASS:new RegExp("^\\.("+L+")"),TAG:new RegExp("^("+L+"|[*])"),ATTR:new RegExp("^"+M),PSEUDO:new RegExp("^"+N),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+K+"*(even|odd|(([+-]|)(\\d*)n|)"+K+"*(?:([+-]|)"+K+"*(\\d+)|))"+K+"*\\)|)","i"),bool:new RegExp("^(?:"+J+")$","i"),needsContext:new RegExp("^"+K+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+K+"*((?:-\\d)?\\d*)"+K+"*\\)|)(?=[^-]|$)","i")},W=/^(?:input|select|textarea|button)$/i,X=/^h\d$/i,Y=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,$=/[+~]/,_=new RegExp("\\\\([\\da-f]{1,6}"+K+"?|("+K+")|.)","ig"),aa=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:d<0?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},ba=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\x80-\uFFFF\w-]/g,ca=function(a,b){return b?"\0"===a?"\ufffd":a.slice(0,-1)+"\\"+a.charCodeAt(a.length-1).toString(16)+" ":"\\"+a},da=function(){m()},ea=ta(function(a){return a.disabled===!0},{dir:"parentNode",next:"legend"});try{G.apply(D=H.call(v.childNodes),v.childNodes),D[v.childNodes.length].nodeType}catch(fa){G={apply:D.length?function(a,b){F.apply(a,H.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function ga(a,b,d,e){var f,h,j,k,l,o,r,s=b&&b.ownerDocument,w=b?b.nodeType:9;if(d=d||[],"string"!=typeof a||!a||1!==w&&9!==w&&11!==w)return d;if(!e&&((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,p)){if(11!==w&&(l=Z.exec(a)))if(f=l[1]){if(9===w){if(!(j=b.getElementById(f)))return d;if(j.id===f)return d.push(j),d}else if(s&&(j=s.getElementById(f))&&t(b,j)&&j.id===f)return d.push(j),d}else{if(l[2])return G.apply(d,b.getElementsByTagName(a)),d;if((f=l[3])&&c.getElementsByClassName&&b.getElementsByClassName)return G.apply(d,b.getElementsByClassName(f)),d}if(c.qsa&&!A[a+" "]&&(!q||!q.test(a))){if(1!==w)s=b,r=a;else if("object"!==b.nodeName.toLowerCase()){(k=b.getAttribute("id"))?k=k.replace(ba,ca):b.setAttribute("id",k=u),o=g(a),h=o.length;while(h--)o[h]="#"+k+" "+sa(o[h]);r=o.join(","),s=$.test(a)&&qa(b.parentNode)||b}if(r)try{return G.apply(d,s.querySelectorAll(r)),d}catch(x){}finally{k===u&&b.removeAttribute("id")}}}return i(a.replace(P,"$1"),b,d,e)}function ha(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ia(a){return a[u]=!0,a}function ja(a){var b=n.createElement("fieldset");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ka(a,b){var c=a.split("|"),e=c.length;while(e--)d.attrHandle[c[e]]=b}function la(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&a.sourceIndex-b.sourceIndex;if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function na(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function oa(a){return function(b){return"label"in b&&b.disabled===a||"form"in b&&b.disabled===a||"form"in b&&b.disabled===!1&&(b.isDisabled===a||b.isDisabled!==!a&&("label"in b||!ea(b))!==a)}}function pa(a){return ia(function(b){return b=+b,ia(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function qa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=ga.support={},f=ga.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return!!b&&"HTML"!==b.nodeName},m=ga.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=n.documentElement,p=!f(n),v!==n&&(e=n.defaultView)&&e.top!==e&&(e.addEventListener?e.addEventListener("unload",da,!1):e.attachEvent&&e.attachEvent("onunload",da)),c.attributes=ja(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ja(function(a){return a.appendChild(n.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Y.test(n.getElementsByClassName),c.getById=ja(function(a){return o.appendChild(a).id=u,!n.getElementsByName||!n.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c?[c]:[]}},d.filter.ID=function(a){var b=a.replace(_,aa);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(_,aa);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){if("undefined"!=typeof b.getElementsByClassName&&p)return b.getElementsByClassName(a)},r=[],q=[],(c.qsa=Y.test(n.querySelectorAll))&&(ja(function(a){o.appendChild(a).innerHTML="",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+K+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+K+"*(?:value|"+J+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ja(function(a){a.innerHTML="";var b=n.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+K+"*[*^$|!~]?="),2!==a.querySelectorAll(":enabled").length&&q.push(":enabled",":disabled"),o.appendChild(a).disabled=!0,2!==a.querySelectorAll(":disabled").length&&q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=Y.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ja(function(a){c.disconnectedMatch=s.call(a,"*"),s.call(a,"[s!='']:x"),r.push("!=",N)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=Y.test(o.compareDocumentPosition),t=b||Y.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===n||a.ownerDocument===v&&t(v,a)?-1:b===n||b.ownerDocument===v&&t(v,b)?1:k?I(k,a)-I(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,g=[a],h=[b];if(!e||!f)return a===n?-1:b===n?1:e?-1:f?1:k?I(k,a)-I(k,b):0;if(e===f)return la(a,b);c=a;while(c=c.parentNode)g.unshift(c);c=b;while(c=c.parentNode)h.unshift(c);while(g[d]===h[d])d++;return d?la(g[d],h[d]):g[d]===v?-1:h[d]===v?1:0},n):n},ga.matches=function(a,b){return ga(a,null,null,b)},ga.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(S,"='$1']"),c.matchesSelector&&p&&!A[b+" "]&&(!r||!r.test(b))&&(!q||!q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return ga(b,n,null,[a]).length>0},ga.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},ga.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&C.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},ga.escape=function(a){return(a+"").replace(ba,ca)},ga.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},ga.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=ga.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=ga.selectors={cacheLength:50,createPseudo:ia,match:V,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(_,aa),a[3]=(a[3]||a[4]||a[5]||"").replace(_,aa),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||ga.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&ga.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return V.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&T.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(_,aa).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+K+")"+a+"("+K+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=ga.attr(d,a);return null==e?"!="===b:!b||(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(O," ")+" ").indexOf(c)>-1:"|="===b&&(e===c||e.slice(0,c.length+1)===c+"-"))}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h,t=!1;if(q){if(f){while(p){m=b;while(m=m[p])if(h?m.nodeName.toLowerCase()===r:1===m.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){m=q,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n&&j[2],m=n&&q.childNodes[n];while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if(1===m.nodeType&&++t&&m===b){k[a]=[w,n,t];break}}else if(s&&(m=b,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n),t===!1)while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if((h?m.nodeName.toLowerCase()===r:1===m.nodeType)&&++t&&(s&&(l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),k[a]=[w,t]),m===b))break;return t-=e,t===d||t%d===0&&t/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||ga.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ia(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=I(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ia(function(a){var b=[],c=[],d=h(a.replace(P,"$1"));return d[u]?ia(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ia(function(a){return function(b){return ga(a,b).length>0}}),contains:ia(function(a){return a=a.replace(_,aa),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ia(function(a){return U.test(a||"")||ga.error("unsupported lang: "+a),a=a.replace(_,aa).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:oa(!1),disabled:oa(!0),checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return X.test(a.nodeName)},input:function(a){return W.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:pa(function(){return[0]}),last:pa(function(a,b){return[b-1]}),eq:pa(function(a,b,c){return[c<0?c+b:c]}),even:pa(function(a,b){for(var c=0;c=0;)a.push(d);return a}),gt:pa(function(a,b,c){for(var d=c<0?c+b:c;++d1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function va(a,b,c){for(var d=0,e=b.length;d-1&&(f[j]=!(g[j]=l))}}else r=wa(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):G.apply(g,r)})}function ya(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=ta(function(a){return a===b},h,!0),l=ta(function(a){return I(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];i1&&ua(m),i>1&&sa(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(P,"$1"),c,i0,e=a.length>0,f=function(f,g,h,i,k){var l,o,q,r=0,s="0",t=f&&[],u=[],v=j,x=f||e&&d.find.TAG("*",k),y=w+=null==v?1:Math.random()||.1,z=x.length;for(k&&(j=g===n||g||k);s!==z&&null!=(l=x[s]);s++){if(e&&l){o=0,g||l.ownerDocument===n||(m(l),h=!p);while(q=a[o++])if(q(l,g||n,h)){i.push(l);break}k&&(w=y)}c&&((l=!q&&l)&&r--,f&&t.push(l))}if(r+=s,c&&s!==r){o=0;while(q=b[o++])q(t,u,g,h);if(f){if(r>0)while(s--)t[s]||u[s]||(u[s]=E.call(i));u=wa(u)}G.apply(i,u),k&&!f&&u.length>0&&r+b.length>1&&ga.uniqueSort(i)}return k&&(w=y,j=v),t};return c?ia(f):f}return h=ga.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=ya(b[c]),f[u]?d.push(f):e.push(f);f=A(a,za(e,d)),f.selector=a}return f},i=ga.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(_,aa),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=V.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(_,aa),$.test(j[0].type)&&qa(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&sa(j),!a)return G.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,!b||$.test(a)&&qa(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ja(function(a){return 1&a.compareDocumentPosition(n.createElement("fieldset"))}),ja(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||ka("type|href|height|width",function(a,b,c){if(!c)return a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ja(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ka("value",function(a,b,c){if(!c&&"input"===a.nodeName.toLowerCase())return a.defaultValue}),ja(function(a){return null==a.getAttribute("disabled")})||ka(J,function(a,b,c){var d;if(!c)return a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),ga}(a);r.find=x,r.expr=x.selectors,r.expr[":"]=r.expr.pseudos,r.uniqueSort=r.unique=x.uniqueSort,r.text=x.getText,r.isXMLDoc=x.isXML,r.contains=x.contains,r.escapeSelector=x.escape;var y=function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&r(a).is(c))break;d.push(a)}return d},z=function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c},A=r.expr.match.needsContext,B=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i,C=/^.[^:#\[\.,]*$/;function D(a,b,c){if(r.isFunction(b))return r.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return r.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(C.test(b))return r.filter(b,a,c);b=r.filter(b,a)}return r.grep(a,function(a){return i.call(b,a)>-1!==c&&1===a.nodeType})}r.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?r.find.matchesSelector(d,a)?[d]:[]:r.find.matches(a,r.grep(b,function(a){return 1===a.nodeType}))},r.fn.extend({find:function(a){var b,c,d=this.length,e=this;if("string"!=typeof a)return this.pushStack(r(a).filter(function(){for(b=0;b1?r.uniqueSort(c):c},filter:function(a){return this.pushStack(D(this,a||[],!1))},not:function(a){return this.pushStack(D(this,a||[],!0))},is:function(a){return!!D(this,"string"==typeof a&&A.test(a)?r(a):a||[],!1).length}});var E,F=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/,G=r.fn.init=function(a,b,c){var e,f;if(!a)return this;if(c=c||E,"string"==typeof a){if(e="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:F.exec(a),!e||!e[1]&&b)return!b||b.jquery?(b||c).find(a):this.constructor(b).find(a);if(e[1]){if(b=b instanceof r?b[0]:b,r.merge(this,r.parseHTML(e[1],b&&b.nodeType?b.ownerDocument||b:d,!0)),B.test(e[1])&&r.isPlainObject(b))for(e in b)r.isFunction(this[e])?this[e](b[e]):this.attr(e,b[e]);return this}return f=d.getElementById(e[2]),f&&(this[0]=f,this.length=1),this}return a.nodeType?(this[0]=a,this.length=1,this):r.isFunction(a)?void 0!==c.ready?c.ready(a):a(r):r.makeArray(a,this)};G.prototype=r.fn,E=r(d);var H=/^(?:parents|prev(?:Until|All))/,I={children:!0,contents:!0,next:!0,prev:!0};r.fn.extend({has:function(a){var b=r(a,this),c=b.length;return this.filter(function(){for(var a=0;a-1:1===c.nodeType&&r.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?r.uniqueSort(f):f)},index:function(a){return a?"string"==typeof a?i.call(r(a),this[0]):i.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(r.uniqueSort(r.merge(this.get(),r(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function J(a,b){while((a=a[b])&&1!==a.nodeType);return a}r.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return y(a,"parentNode")},parentsUntil:function(a,b,c){return y(a,"parentNode",c)},next:function(a){return J(a,"nextSibling")},prev:function(a){return J(a,"previousSibling")},nextAll:function(a){return y(a,"nextSibling")},prevAll:function(a){return y(a,"previousSibling")},nextUntil:function(a,b,c){return y(a,"nextSibling",c)},prevUntil:function(a,b,c){return y(a,"previousSibling",c)},siblings:function(a){return z((a.parentNode||{}).firstChild,a)},children:function(a){return z(a.firstChild)},contents:function(a){return a.contentDocument||r.merge([],a.childNodes)}},function(a,b){r.fn[a]=function(c,d){var e=r.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=r.filter(d,e)),this.length>1&&(I[a]||r.uniqueSort(e),H.test(a)&&e.reverse()),this.pushStack(e)}});var K=/\S+/g;function L(a){var b={};return r.each(a.match(K)||[],function(a,c){b[c]=!0}),b}r.Callbacks=function(a){a="string"==typeof a?L(a):r.extend({},a);var b,c,d,e,f=[],g=[],h=-1,i=function(){for(e=a.once,d=b=!0;g.length;h=-1){c=g.shift();while(++h-1)f.splice(c,1),c<=h&&h--}),this},has:function(a){return a?r.inArray(a,f)>-1:f.length>0},empty:function(){return f&&(f=[]),this},disable:function(){return e=g=[],f=c="",this},disabled:function(){return!f},lock:function(){return e=g=[],c||b||(f=c=""),this},locked:function(){return!!e},fireWith:function(a,c){return e||(c=c||[],c=[a,c.slice?c.slice():c],g.push(c),b||i()),this},fire:function(){return j.fireWith(this,arguments),this},fired:function(){return!!d}};return j};function M(a){return a}function N(a){throw a}function O(a,b,c){var d;try{a&&r.isFunction(d=a.promise)?d.call(a).done(b).fail(c):a&&r.isFunction(d=a.then)?d.call(a,b,c):b.call(void 0,a)}catch(a){c.call(void 0,a)}}r.extend({Deferred:function(b){var c=[["notify","progress",r.Callbacks("memory"),r.Callbacks("memory"),2],["resolve","done",r.Callbacks("once memory"),r.Callbacks("once memory"),0,"resolved"],["reject","fail",r.Callbacks("once memory"),r.Callbacks("once memory"),1,"rejected"]],d="pending",e={state:function(){return d},always:function(){return f.done(arguments).fail(arguments),this},"catch":function(a){return e.then(null,a)},pipe:function(){var a=arguments;return r.Deferred(function(b){r.each(c,function(c,d){var e=r.isFunction(a[d[4]])&&a[d[4]];f[d[1]](function(){var a=e&&e.apply(this,arguments);a&&r.isFunction(a.promise)?a.promise().progress(b.notify).done(b.resolve).fail(b.reject):b[d[0]+"With"](this,e?[a]:arguments)})}),a=null}).promise()},then:function(b,d,e){var f=0;function g(b,c,d,e){return function(){var h=this,i=arguments,j=function(){var a,j;if(!(b=f&&(d!==N&&(h=void 0,i=[a]),c.rejectWith(h,i))}};b?k():(r.Deferred.getStackHook&&(k.stackTrace=r.Deferred.getStackHook()),a.setTimeout(k))}}return r.Deferred(function(a){c[0][3].add(g(0,a,r.isFunction(e)?e:M,a.notifyWith)),c[1][3].add(g(0,a,r.isFunction(b)?b:M)),c[2][3].add(g(0,a,r.isFunction(d)?d:N))}).promise()},promise:function(a){return null!=a?r.extend(a,e):e}},f={};return r.each(c,function(a,b){var g=b[2],h=b[5];e[b[1]]=g.add,h&&g.add(function(){d=h},c[3-a][2].disable,c[0][2].lock),g.add(b[3].fire),f[b[0]]=function(){return f[b[0]+"With"](this===f?void 0:this,arguments),this},f[b[0]+"With"]=g.fireWith}),e.promise(f),b&&b.call(f,f),f},when:function(a){var b=arguments.length,c=b,d=Array(c),e=f.call(arguments),g=r.Deferred(),h=function(a){return function(c){d[a]=this,e[a]=arguments.length>1?f.call(arguments):c,--b||g.resolveWith(d,e)}};if(b<=1&&(O(a,g.done(h(c)).resolve,g.reject),"pending"===g.state()||r.isFunction(e[c]&&e[c].then)))return g.then();while(c--)O(e[c],h(c),g.reject);return g.promise()}});var P=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;r.Deferred.exceptionHook=function(b,c){a.console&&a.console.warn&&b&&P.test(b.name)&&a.console.warn("jQuery.Deferred exception: "+b.message,b.stack,c)},r.readyException=function(b){a.setTimeout(function(){throw b})};var Q=r.Deferred();r.fn.ready=function(a){return Q.then(a)["catch"](function(a){r.readyException(a)}),this},r.extend({isReady:!1,readyWait:1,holdReady:function(a){a?r.readyWait++:r.ready(!0)},ready:function(a){(a===!0?--r.readyWait:r.isReady)||(r.isReady=!0,a!==!0&&--r.readyWait>0||Q.resolveWith(d,[r]))}}),r.ready.then=Q.then;function R(){d.removeEventListener("DOMContentLoaded",R),a.removeEventListener("load",R),r.ready()}"complete"===d.readyState||"loading"!==d.readyState&&!d.documentElement.doScroll?a.setTimeout(r.ready):(d.addEventListener("DOMContentLoaded",R),a.addEventListener("load",R));var S=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===r.type(c)){e=!0;for(h in c)S(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0, 3 | r.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(r(a),c)})),b))for(;h1,null,!0)},removeData:function(a){return this.each(function(){W.remove(this,a)})}}),r.extend({queue:function(a,b,c){var d;if(a)return b=(b||"fx")+"queue",d=V.get(a,b),c&&(!d||r.isArray(c)?d=V.access(a,b,r.makeArray(c)):d.push(c)),d||[]},dequeue:function(a,b){b=b||"fx";var c=r.queue(a,b),d=c.length,e=c.shift(),f=r._queueHooks(a,b),g=function(){r.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return V.get(a,c)||V.access(a,c,{empty:r.Callbacks("once memory").add(function(){V.remove(a,[b+"queue",c])})})}}),r.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length\x20\t\r\n\f]+)/i,ja=/^$|\/(?:java|ecma)script/i,ka={option:[1,""],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};ka.optgroup=ka.option,ka.tbody=ka.tfoot=ka.colgroup=ka.caption=ka.thead,ka.th=ka.td;function la(a,b){var c="undefined"!=typeof a.getElementsByTagName?a.getElementsByTagName(b||"*"):"undefined"!=typeof a.querySelectorAll?a.querySelectorAll(b||"*"):[];return void 0===b||b&&r.nodeName(a,b)?r.merge([a],c):c}function ma(a,b){for(var c=0,d=a.length;c-1)e&&e.push(f);else if(j=r.contains(f.ownerDocument,f),g=la(l.appendChild(f),"script"),j&&ma(g),c){k=0;while(f=g[k++])ja.test(f.type||"")&&c.push(f)}return l}!function(){var a=d.createDocumentFragment(),b=a.appendChild(d.createElement("div")),c=d.createElement("input");c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),b.appendChild(c),o.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,b.innerHTML="",o.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var pa=d.documentElement,qa=/^key/,ra=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,sa=/^([^.]*)(?:\.(.+)|)/;function ta(){return!0}function ua(){return!1}function va(){try{return d.activeElement}catch(a){}}function wa(a,b,c,d,e,f){var g,h;if("object"==typeof b){"string"!=typeof c&&(d=d||c,c=void 0);for(h in b)wa(a,h,c,d,b[h],f);return a}if(null==d&&null==e?(e=c,d=c=void 0):null==e&&("string"==typeof c?(e=d,d=void 0):(e=d,d=c,c=void 0)),e===!1)e=ua;else if(!e)return a;return 1===f&&(g=e,e=function(a){return r().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=r.guid++)),a.each(function(){r.event.add(this,b,e,d,c)})}r.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,p,q=V.get(a);if(q){c.handler&&(f=c,c=f.handler,e=f.selector),e&&r.find.matchesSelector(pa,e),c.guid||(c.guid=r.guid++),(i=q.events)||(i=q.events={}),(g=q.handle)||(g=q.handle=function(b){return"undefined"!=typeof r&&r.event.triggered!==b.type?r.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(K)||[""],j=b.length;while(j--)h=sa.exec(b[j])||[],n=p=h[1],o=(h[2]||"").split(".").sort(),n&&(l=r.event.special[n]||{},n=(e?l.delegateType:l.bindType)||n,l=r.event.special[n]||{},k=r.extend({type:n,origType:p,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&r.expr.match.needsContext.test(e),namespace:o.join(".")},f),(m=i[n])||(m=i[n]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,o,g)!==!1||a.addEventListener&&a.addEventListener(n,g)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),r.event.global[n]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,p,q=V.hasData(a)&&V.get(a);if(q&&(i=q.events)){b=(b||"").match(K)||[""],j=b.length;while(j--)if(h=sa.exec(b[j])||[],n=p=h[1],o=(h[2]||"").split(".").sort(),n){l=r.event.special[n]||{},n=(d?l.delegateType:l.bindType)||n,m=i[n]||[],h=h[2]&&new RegExp("(^|\\.)"+o.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&p!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,o,q.handle)!==!1||r.removeEvent(a,n,q.handle),delete i[n])}else for(n in i)r.event.remove(a,n+b[j],c,d,!0);r.isEmptyObject(i)&&V.remove(a,"handle events")}},dispatch:function(a){var b=r.event.fix(a),c,d,e,f,g,h,i=new Array(arguments.length),j=(V.get(this,"events")||{})[b.type]||[],k=r.event.special[b.type]||{};for(i[0]=b,c=1;c-1:r.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h\x20\t\r\n\f]*)[^>]*)\/>/gi,ya=/\s*$/g;function Ca(a,b){return r.nodeName(a,"table")&&r.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a:a}function Da(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function Ea(a){var b=Aa.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function Fa(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(V.hasData(a)&&(f=V.access(a),g=V.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;c1&&"string"==typeof q&&!o.checkClone&&za.test(q))return a.each(function(e){var f=a.eq(e);s&&(b[0]=q.call(this,e,f.html())),Ha(f,b,c,d)});if(m&&(e=oa(b,a[0].ownerDocument,!1,a,d),f=e.firstChild,1===e.childNodes.length&&(e=f),f||d)){for(h=r.map(la(e,"script"),Da),i=h.length;l")},clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=r.contains(a.ownerDocument,a);if(!(o.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||r.isXMLDoc(a)))for(g=la(h),f=la(a),d=0,e=f.length;d0&&ma(g,!i&&la(a,"script")),h},cleanData:function(a){for(var b,c,d,e=r.event.special,f=0;void 0!==(c=a[f]);f++)if(T(c)){if(b=c[V.expando]){if(b.events)for(d in b.events)e[d]?r.event.remove(c,d):r.removeEvent(c,d,b.handle);c[V.expando]=void 0}c[W.expando]&&(c[W.expando]=void 0)}}}),r.fn.extend({detach:function(a){return Ia(this,a,!0)},remove:function(a){return Ia(this,a)},text:function(a){return S(this,function(a){return void 0===a?r.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=a)})},null,a,arguments.length)},append:function(){return Ha(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ca(this,a);b.appendChild(a)}})},prepend:function(){return Ha(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ca(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return Ha(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return Ha(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(r.cleanData(la(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null!=a&&a,b=null==b?a:b,this.map(function(){return r.clone(this,a,b)})},html:function(a){return S(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!ya.test(a)&&!ka[(ia.exec(a)||["",""])[1].toLowerCase()]){a=r.htmlPrefilter(a);try{for(;c1)}});function Xa(a,b,c,d,e){return new Xa.prototype.init(a,b,c,d,e)}r.Tween=Xa,Xa.prototype={constructor:Xa,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||r.easing._default,this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(r.cssNumber[c]?"":"px")},cur:function(){var a=Xa.propHooks[this.prop];return a&&a.get?a.get(this):Xa.propHooks._default.get(this)},run:function(a){var b,c=Xa.propHooks[this.prop];return this.options.duration?this.pos=b=r.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):this.pos=b=a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):Xa.propHooks._default.set(this),this}},Xa.prototype.init.prototype=Xa.prototype,Xa.propHooks={_default:{get:function(a){var b;return 1!==a.elem.nodeType||null!=a.elem[a.prop]&&null==a.elem.style[a.prop]?a.elem[a.prop]:(b=r.css(a.elem,a.prop,""),b&&"auto"!==b?b:0)},set:function(a){r.fx.step[a.prop]?r.fx.step[a.prop](a):1!==a.elem.nodeType||null==a.elem.style[r.cssProps[a.prop]]&&!r.cssHooks[a.prop]?a.elem[a.prop]=a.now:r.style(a.elem,a.prop,a.now+a.unit)}}},Xa.propHooks.scrollTop=Xa.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},r.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2},_default:"swing"},r.fx=Xa.prototype.init,r.fx.step={};var Ya,Za,$a=/^(?:toggle|show|hide)$/,_a=/queueHooks$/;function ab(){Za&&(a.requestAnimationFrame(ab),r.fx.tick())}function bb(){return a.setTimeout(function(){Ya=void 0}),Ya=r.now()}function cb(a,b){var c,d=0,e={height:a};for(b=b?1:0;d<4;d+=2-b)c=aa[d],e["margin"+c]=e["padding"+c]=a;return b&&(e.opacity=e.width=a),e}function db(a,b,c){for(var d,e=(gb.tweeners[b]||[]).concat(gb.tweeners["*"]),f=0,g=e.length;f1)},removeAttr:function(a){return this.each(function(){r.removeAttr(this,a)})}}),r.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return"undefined"==typeof a.getAttribute?r.prop(a,b,c):(1===f&&r.isXMLDoc(a)||(e=r.attrHooks[b.toLowerCase()]||(r.expr.match.bool.test(b)?hb:void 0)),void 0!==c?null===c?void r.removeAttr(a,b):e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:(a.setAttribute(b,c+""),c):e&&"get"in e&&null!==(d=e.get(a,b))?d:(d=r.find.attr(a,b),null==d?void 0:d))},attrHooks:{type:{set:function(a,b){if(!o.radioValue&&"radio"===b&&r.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}},removeAttr:function(a,b){var c,d=0,e=b&&b.match(K); 4 | if(e&&1===a.nodeType)while(c=e[d++])a.removeAttribute(c)}}),hb={set:function(a,b,c){return b===!1?r.removeAttr(a,c):a.setAttribute(c,c),c}},r.each(r.expr.match.bool.source.match(/\w+/g),function(a,b){var c=ib[b]||r.find.attr;ib[b]=function(a,b,d){var e,f,g=b.toLowerCase();return d||(f=ib[g],ib[g]=e,e=null!=c(a,b,d)?g:null,ib[g]=f),e}});var jb=/^(?:input|select|textarea|button)$/i,kb=/^(?:a|area)$/i;r.fn.extend({prop:function(a,b){return S(this,r.prop,a,b,arguments.length>1)},removeProp:function(a){return this.each(function(){delete this[r.propFix[a]||a]})}}),r.extend({prop:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return 1===f&&r.isXMLDoc(a)||(b=r.propFix[b]||b,e=r.propHooks[b]),void 0!==c?e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&"get"in e&&null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){var b=r.find.attr(a,"tabindex");return b?parseInt(b,10):jb.test(a.nodeName)||kb.test(a.nodeName)&&a.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),o.optSelected||(r.propHooks.selected={get:function(a){var b=a.parentNode;return b&&b.parentNode&&b.parentNode.selectedIndex,null},set:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex)}}),r.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){r.propFix[this.toLowerCase()]=this});var lb=/[\t\r\n\f]/g;function mb(a){return a.getAttribute&&a.getAttribute("class")||""}r.fn.extend({addClass:function(a){var b,c,d,e,f,g,h,i=0;if(r.isFunction(a))return this.each(function(b){r(this).addClass(a.call(this,b,mb(this)))});if("string"==typeof a&&a){b=a.match(K)||[];while(c=this[i++])if(e=mb(c),d=1===c.nodeType&&(" "+e+" ").replace(lb," ")){g=0;while(f=b[g++])d.indexOf(" "+f+" ")<0&&(d+=f+" ");h=r.trim(d),e!==h&&c.setAttribute("class",h)}}return this},removeClass:function(a){var b,c,d,e,f,g,h,i=0;if(r.isFunction(a))return this.each(function(b){r(this).removeClass(a.call(this,b,mb(this)))});if(!arguments.length)return this.attr("class","");if("string"==typeof a&&a){b=a.match(K)||[];while(c=this[i++])if(e=mb(c),d=1===c.nodeType&&(" "+e+" ").replace(lb," ")){g=0;while(f=b[g++])while(d.indexOf(" "+f+" ")>-1)d=d.replace(" "+f+" "," ");h=r.trim(d),e!==h&&c.setAttribute("class",h)}}return this},toggleClass:function(a,b){var c=typeof a;return"boolean"==typeof b&&"string"===c?b?this.addClass(a):this.removeClass(a):r.isFunction(a)?this.each(function(c){r(this).toggleClass(a.call(this,c,mb(this),b),b)}):this.each(function(){var b,d,e,f;if("string"===c){d=0,e=r(this),f=a.match(K)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else void 0!==a&&"boolean"!==c||(b=mb(this),b&&V.set(this,"__className__",b),this.setAttribute&&this.setAttribute("class",b||a===!1?"":V.get(this,"__className__")||""))})},hasClass:function(a){var b,c,d=0;b=" "+a+" ";while(c=this[d++])if(1===c.nodeType&&(" "+mb(c)+" ").replace(lb," ").indexOf(b)>-1)return!0;return!1}});var nb=/\r/g,ob=/[\x20\t\r\n\f]+/g;r.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=r.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,r(this).val()):a,null==e?e="":"number"==typeof e?e+="":r.isArray(e)&&(e=r.map(e,function(a){return null==a?"":a+""})),b=r.valHooks[this.type]||r.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=r.valHooks[e.type]||r.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(nb,""):null==c?"":c)}}}),r.extend({valHooks:{option:{get:function(a){var b=r.find.attr(a,"value");return null!=b?b:r.trim(r.text(a)).replace(ob," ")}},select:{get:function(a){for(var b,c,d=a.options,e=a.selectedIndex,f="select-one"===a.type,g=f?null:[],h=f?e+1:d.length,i=e<0?h:f?e:0;i-1)&&(c=!0);return c||(a.selectedIndex=-1),f}}}}),r.each(["radio","checkbox"],function(){r.valHooks[this]={set:function(a,b){if(r.isArray(b))return a.checked=r.inArray(r(a).val(),b)>-1}},o.checkOn||(r.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})});var pb=/^(?:focusinfocus|focusoutblur)$/;r.extend(r.event,{trigger:function(b,c,e,f){var g,h,i,j,k,m,n,o=[e||d],p=l.call(b,"type")?b.type:b,q=l.call(b,"namespace")?b.namespace.split("."):[];if(h=i=e=e||d,3!==e.nodeType&&8!==e.nodeType&&!pb.test(p+r.event.triggered)&&(p.indexOf(".")>-1&&(q=p.split("."),p=q.shift(),q.sort()),k=p.indexOf(":")<0&&"on"+p,b=b[r.expando]?b:new r.Event(p,"object"==typeof b&&b),b.isTrigger=f?2:3,b.namespace=q.join("."),b.rnamespace=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=e),c=null==c?[b]:r.makeArray(c,[b]),n=r.event.special[p]||{},f||!n.trigger||n.trigger.apply(e,c)!==!1)){if(!f&&!n.noBubble&&!r.isWindow(e)){for(j=n.delegateType||p,pb.test(j+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),i=h;i===(e.ownerDocument||d)&&o.push(i.defaultView||i.parentWindow||a)}g=0;while((h=o[g++])&&!b.isPropagationStopped())b.type=g>1?j:n.bindType||p,m=(V.get(h,"events")||{})[b.type]&&V.get(h,"handle"),m&&m.apply(h,c),m=k&&h[k],m&&m.apply&&T(h)&&(b.result=m.apply(h,c),b.result===!1&&b.preventDefault());return b.type=p,f||b.isDefaultPrevented()||n._default&&n._default.apply(o.pop(),c)!==!1||!T(e)||k&&r.isFunction(e[p])&&!r.isWindow(e)&&(i=e[k],i&&(e[k]=null),r.event.triggered=p,e[p](),r.event.triggered=void 0,i&&(e[k]=i)),b.result}},simulate:function(a,b,c){var d=r.extend(new r.Event,c,{type:a,isSimulated:!0});r.event.trigger(d,null,b)}}),r.fn.extend({trigger:function(a,b){return this.each(function(){r.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];if(c)return r.event.trigger(a,b,c,!0)}}),r.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(a,b){r.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),r.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),o.focusin="onfocusin"in a,o.focusin||r.each({focus:"focusin",blur:"focusout"},function(a,b){var c=function(a){r.event.simulate(b,a.target,r.event.fix(a))};r.event.special[b]={setup:function(){var d=this.ownerDocument||this,e=V.access(d,b);e||d.addEventListener(a,c,!0),V.access(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=V.access(d,b)-1;e?V.access(d,b,e):(d.removeEventListener(a,c,!0),V.remove(d,b))}}});var qb=a.location,rb=r.now(),sb=/\?/;r.parseXML=function(b){var c;if(!b||"string"!=typeof b)return null;try{c=(new a.DOMParser).parseFromString(b,"text/xml")}catch(d){c=void 0}return c&&!c.getElementsByTagName("parsererror").length||r.error("Invalid XML: "+b),c};var tb=/\[\]$/,ub=/\r?\n/g,vb=/^(?:submit|button|image|reset|file)$/i,wb=/^(?:input|select|textarea|keygen)/i;function xb(a,b,c,d){var e;if(r.isArray(b))r.each(b,function(b,e){c||tb.test(a)?d(a,e):xb(a+"["+("object"==typeof e&&null!=e?b:"")+"]",e,c,d)});else if(c||"object"!==r.type(b))d(a,b);else for(e in b)xb(a+"["+e+"]",b[e],c,d)}r.param=function(a,b){var c,d=[],e=function(a,b){var c=r.isFunction(b)?b():b;d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(null==c?"":c)};if(r.isArray(a)||a.jquery&&!r.isPlainObject(a))r.each(a,function(){e(this.name,this.value)});else for(c in a)xb(c,a[c],b,e);return d.join("&")},r.fn.extend({serialize:function(){return r.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=r.prop(this,"elements");return a?r.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!r(this).is(":disabled")&&wb.test(this.nodeName)&&!vb.test(a)&&(this.checked||!ha.test(a))}).map(function(a,b){var c=r(this).val();return null==c?null:r.isArray(c)?r.map(c,function(a){return{name:b.name,value:a.replace(ub,"\r\n")}}):{name:b.name,value:c.replace(ub,"\r\n")}}).get()}});var yb=/%20/g,zb=/#.*$/,Ab=/([?&])_=[^&]*/,Bb=/^(.*?):[ \t]*([^\r\n]*)$/gm,Cb=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Db=/^(?:GET|HEAD)$/,Eb=/^\/\//,Fb={},Gb={},Hb="*/".concat("*"),Ib=d.createElement("a");Ib.href=qb.href;function Jb(a){return function(b,c){"string"!=typeof b&&(c=b,b="*");var d,e=0,f=b.toLowerCase().match(K)||[];if(r.isFunction(c))while(d=f[e++])"+"===d[0]?(d=d.slice(1)||"*",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function Kb(a,b,c,d){var e={},f=a===Gb;function g(h){var i;return e[h]=!0,r.each(a[h]||[],function(a,h){var j=h(b,c,d);return"string"!=typeof j||f||e[j]?f?!(i=j):void 0:(b.dataTypes.unshift(j),g(j),!1)}),i}return g(b.dataTypes[0])||!e["*"]&&g("*")}function Lb(a,b){var c,d,e=r.ajaxSettings.flatOptions||{};for(c in b)void 0!==b[c]&&((e[c]?a:d||(d={}))[c]=b[c]);return d&&r.extend(!0,a,d),a}function Mb(a,b,c){var d,e,f,g,h=a.contents,i=a.dataTypes;while("*"===i[0])i.shift(),void 0===d&&(d=a.mimeType||b.getResponseHeader("Content-Type"));if(d)for(e in h)if(h[e]&&h[e].test(d)){i.unshift(e);break}if(i[0]in c)f=i[0];else{for(e in c){if(!i[0]||a.converters[e+" "+i[0]]){f=e;break}g||(g=e)}f=f||g}if(f)return f!==i[0]&&i.unshift(f),c[f]}function Nb(a,b,c,d){var e,f,g,h,i,j={},k=a.dataTypes.slice();if(k[1])for(g in a.converters)j[g.toLowerCase()]=a.converters[g];f=k.shift();while(f)if(a.responseFields[f]&&(c[a.responseFields[f]]=b),!i&&d&&a.dataFilter&&(b=a.dataFilter(b,a.dataType)),i=f,f=k.shift())if("*"===f)f=i;else if("*"!==i&&i!==f){if(g=j[i+" "+f]||j["* "+f],!g)for(e in j)if(h=e.split(" "),h[1]===f&&(g=j[i+" "+h[0]]||j["* "+h[0]])){g===!0?g=j[e]:j[e]!==!0&&(f=h[0],k.unshift(h[1]));break}if(g!==!0)if(g&&a["throws"])b=g(b);else try{b=g(b)}catch(l){return{state:"parsererror",error:g?l:"No conversion from "+i+" to "+f}}}return{state:"success",data:b}}r.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:qb.href,type:"GET",isLocal:Cb.test(qb.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Hb,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":JSON.parse,"text xml":r.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?Lb(Lb(a,r.ajaxSettings),b):Lb(r.ajaxSettings,a)},ajaxPrefilter:Jb(Fb),ajaxTransport:Jb(Gb),ajax:function(b,c){"object"==typeof b&&(c=b,b=void 0),c=c||{};var e,f,g,h,i,j,k,l,m,n,o=r.ajaxSetup({},c),p=o.context||o,q=o.context&&(p.nodeType||p.jquery)?r(p):r.event,s=r.Deferred(),t=r.Callbacks("once memory"),u=o.statusCode||{},v={},w={},x="canceled",y={readyState:0,getResponseHeader:function(a){var b;if(k){if(!h){h={};while(b=Bb.exec(g))h[b[1].toLowerCase()]=b[2]}b=h[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return k?g:null},setRequestHeader:function(a,b){return null==k&&(a=w[a.toLowerCase()]=w[a.toLowerCase()]||a,v[a]=b),this},overrideMimeType:function(a){return null==k&&(o.mimeType=a),this},statusCode:function(a){var b;if(a)if(k)y.always(a[y.status]);else for(b in a)u[b]=[u[b],a[b]];return this},abort:function(a){var b=a||x;return e&&e.abort(b),A(0,b),this}};if(s.promise(y),o.url=((b||o.url||qb.href)+"").replace(Eb,qb.protocol+"//"),o.type=c.method||c.type||o.method||o.type,o.dataTypes=(o.dataType||"*").toLowerCase().match(K)||[""],null==o.crossDomain){j=d.createElement("a");try{j.href=o.url,j.href=j.href,o.crossDomain=Ib.protocol+"//"+Ib.host!=j.protocol+"//"+j.host}catch(z){o.crossDomain=!0}}if(o.data&&o.processData&&"string"!=typeof o.data&&(o.data=r.param(o.data,o.traditional)),Kb(Fb,o,c,y),k)return y;l=r.event&&o.global,l&&0===r.active++&&r.event.trigger("ajaxStart"),o.type=o.type.toUpperCase(),o.hasContent=!Db.test(o.type),f=o.url.replace(zb,""),o.hasContent?o.data&&o.processData&&0===(o.contentType||"").indexOf("application/x-www-form-urlencoded")&&(o.data=o.data.replace(yb,"+")):(n=o.url.slice(f.length),o.data&&(f+=(sb.test(f)?"&":"?")+o.data,delete o.data),o.cache===!1&&(f=f.replace(Ab,""),n=(sb.test(f)?"&":"?")+"_="+rb++ +n),o.url=f+n),o.ifModified&&(r.lastModified[f]&&y.setRequestHeader("If-Modified-Since",r.lastModified[f]),r.etag[f]&&y.setRequestHeader("If-None-Match",r.etag[f])),(o.data&&o.hasContent&&o.contentType!==!1||c.contentType)&&y.setRequestHeader("Content-Type",o.contentType),y.setRequestHeader("Accept",o.dataTypes[0]&&o.accepts[o.dataTypes[0]]?o.accepts[o.dataTypes[0]]+("*"!==o.dataTypes[0]?", "+Hb+"; q=0.01":""):o.accepts["*"]);for(m in o.headers)y.setRequestHeader(m,o.headers[m]);if(o.beforeSend&&(o.beforeSend.call(p,y,o)===!1||k))return y.abort();if(x="abort",t.add(o.complete),y.done(o.success),y.fail(o.error),e=Kb(Gb,o,c,y)){if(y.readyState=1,l&&q.trigger("ajaxSend",[y,o]),k)return y;o.async&&o.timeout>0&&(i=a.setTimeout(function(){y.abort("timeout")},o.timeout));try{k=!1,e.send(v,A)}catch(z){if(k)throw z;A(-1,z)}}else A(-1,"No Transport");function A(b,c,d,h){var j,m,n,v,w,x=c;k||(k=!0,i&&a.clearTimeout(i),e=void 0,g=h||"",y.readyState=b>0?4:0,j=b>=200&&b<300||304===b,d&&(v=Mb(o,y,d)),v=Nb(o,v,y,j),j?(o.ifModified&&(w=y.getResponseHeader("Last-Modified"),w&&(r.lastModified[f]=w),w=y.getResponseHeader("etag"),w&&(r.etag[f]=w)),204===b||"HEAD"===o.type?x="nocontent":304===b?x="notmodified":(x=v.state,m=v.data,n=v.error,j=!n)):(n=x,!b&&x||(x="error",b<0&&(b=0))),y.status=b,y.statusText=(c||x)+"",j?s.resolveWith(p,[m,x,y]):s.rejectWith(p,[y,x,n]),y.statusCode(u),u=void 0,l&&q.trigger(j?"ajaxSuccess":"ajaxError",[y,o,j?m:n]),t.fireWith(p,[y,x]),l&&(q.trigger("ajaxComplete",[y,o]),--r.active||r.event.trigger("ajaxStop")))}return y},getJSON:function(a,b,c){return r.get(a,b,c,"json")},getScript:function(a,b){return r.get(a,void 0,b,"script")}}),r.each(["get","post"],function(a,b){r[b]=function(a,c,d,e){return r.isFunction(c)&&(e=e||d,d=c,c=void 0),r.ajax(r.extend({url:a,type:b,dataType:e,data:c,success:d},r.isPlainObject(a)&&a))}}),r._evalUrl=function(a){return r.ajax({url:a,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,"throws":!0})},r.fn.extend({wrapAll:function(a){var b;return this[0]&&(r.isFunction(a)&&(a=a.call(this[0])),b=r(a,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstElementChild)a=a.firstElementChild;return a}).append(this)),this},wrapInner:function(a){return r.isFunction(a)?this.each(function(b){r(this).wrapInner(a.call(this,b))}):this.each(function(){var b=r(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=r.isFunction(a);return this.each(function(c){r(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(a){return this.parent(a).not("body").each(function(){r(this).replaceWith(this.childNodes)}),this}}),r.expr.pseudos.hidden=function(a){return!r.expr.pseudos.visible(a)},r.expr.pseudos.visible=function(a){return!!(a.offsetWidth||a.offsetHeight||a.getClientRects().length)},r.ajaxSettings.xhr=function(){try{return new a.XMLHttpRequest}catch(b){}};var Ob={0:200,1223:204},Pb=r.ajaxSettings.xhr();o.cors=!!Pb&&"withCredentials"in Pb,o.ajax=Pb=!!Pb,r.ajaxTransport(function(b){var c,d;if(o.cors||Pb&&!b.crossDomain)return{send:function(e,f){var g,h=b.xhr();if(h.open(b.type,b.url,b.async,b.username,b.password),b.xhrFields)for(g in b.xhrFields)h[g]=b.xhrFields[g];b.mimeType&&h.overrideMimeType&&h.overrideMimeType(b.mimeType),b.crossDomain||e["X-Requested-With"]||(e["X-Requested-With"]="XMLHttpRequest");for(g in e)h.setRequestHeader(g,e[g]);c=function(a){return function(){c&&(c=d=h.onload=h.onerror=h.onabort=h.onreadystatechange=null,"abort"===a?h.abort():"error"===a?"number"!=typeof h.status?f(0,"error"):f(h.status,h.statusText):f(Ob[h.status]||h.status,h.statusText,"text"!==(h.responseType||"text")||"string"!=typeof h.responseText?{binary:h.response}:{text:h.responseText},h.getAllResponseHeaders()))}},h.onload=c(),d=h.onerror=c("error"),void 0!==h.onabort?h.onabort=d:h.onreadystatechange=function(){4===h.readyState&&a.setTimeout(function(){c&&d()})},c=c("abort");try{h.send(b.hasContent&&b.data||null)}catch(i){if(c)throw i}},abort:function(){c&&c()}}}),r.ajaxPrefilter(function(a){a.crossDomain&&(a.contents.script=!1)}),r.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(a){return r.globalEval(a),a}}}),r.ajaxPrefilter("script",function(a){void 0===a.cache&&(a.cache=!1),a.crossDomain&&(a.type="GET")}),r.ajaxTransport("script",function(a){if(a.crossDomain){var b,c;return{send:function(e,f){b=r(" 6 | 7 | 8 | 9 | 10 | 11 | 股票公告 12 | 13 | 14 |

股票公告查询

15 |
16 | 17 | 公告类型 18 | 19 | 20 | 股票代码 21 | 22 | 23 | 日期 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 |
32 | 33 | 34 | 35 | 36 | 37 | <% if (annctype == 'sse'){ %> 38 | 39 | <% } %> 40 | <% if (annctype == 'csrc'){ %> 41 | 42 | <% } %> 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | <% for(var i = 0; i < announcements.length; i++){ 52 | var annc = announcements[i]; 53 | %> 54 | 55 | 56 | 57 | <% if (annctype == 'sse'){ %> 58 | 59 | <% } %> 60 | <% if (annctype == 'csrc'){ %> 61 | 62 | <% } %> 63 | 64 | 65 | 66 | 67 | 68 | 69 | <% if (annc.Valid == 1){ 70 | var readHref = "http://192.168.0.71:3000/read?anncType=" + annctype + "&anncKey=" + annc.Annc_Key + "&format="; 71 | 72 | if (annc.Format == 'PDF' || annc.Format == 'pdf'){ 73 | %> 74 | 80 | <% } %> 81 | 82 | <% if (annc.Format == 'DOC' || annc.Format == 'doc'){ %> 83 | 89 | <% } %> 90 | 91 | <% if (annc.Format == 'TXT' || annc.Format == 'txt'|| annc.Format == ""){ %> 92 | 96 | <% } %> 97 | <% } %> 98 | 99 | <% } %> 100 |
股票代码 股票简称 监管类型 标题 发布日期 发布时间 文件编号 文件
<%= annc.Symbol %><%= annc.Abbr_Name %><%= annc.Regu_Type %><%= annc.Title %><%= annc.Annc_Date %><%= annc.Annc_Time %><%= annc.Annc_Key %> 75 | target="_blank" > 76 | 77 | target="_blank" > 78 | 79 | 84 | target="_blank" > 85 | 86 | target="_blank"> 87 | 88 | 93 | target="_blank"> 94 | 95 |
101 | 102 | 103 | 104 | 106 |
共 <%= announcements.length.toString() %> 份公告 105 |
107 | 108 | 109 |
110 | 111 | 127 | 128 | 129 | -------------------------------------------------------------------------------- /python_scraw/README.md: -------------------------------------------------------------------------------- 1 | ### 该脚本从巨潮网络的服务器上将公告下载,把每条公告的相关信息存入数据库中。 2 | 3 | ### 公告命名方法为: 4 | * 上市公司:股票代码(6位)+YYYYMMDD(8位)+ 当日当支股票公告的排序号(3位) 5 | * 监管公告:监管代码(3或4位) + YYYYMMDD(8位) + 序号(2位) 6 | 7 | ### 参数介绍 8 | * python cninfo_main.py sse(regulator) [startdate] [enddate] 9 | * sse是公司公告,regulator是监管机构公告,每次只能下载一种 10 | * 无时间参数默认为当天数据,若要下一个区间的数据,则需要startdate,enddate两个参数,如果指明非今天的某一天,则只写一个参数即可 11 | * date的格式YYYYMMDD 12 | * 示例: 下载2017年1月1号到3月31号的公司公告: python cninfo_main.py sse 20170101 20170331 13 | * 示例: 下载2017年1月1号当天的监管公告: python cninfo_main.py regulator 20170101 -------------------------------------------------------------------------------- /python_scraw/annc/README.md: -------------------------------------------------------------------------------- 1 | # annc 2 | 3 | ## 简介 4 | * 该项目旨在替代cninfo_main.py, 用scrapy框架完成 5 | * 从巨潮网络的服务器获取中国股市公告,元数据存入MySQL,公告文件下载到本地 6 | * 目前只支持上市公司,功能会逐渐完善 7 | 8 | ## 使用 9 | * 准备好scrapy环境 10 | * 参考cninfo_main.py 中的数据表建表 11 | * 在 annc//settings.py中,修改文件路径和数据库配置 12 | * 在annc/路径下,执行 scrapy crawl annc -a annc_type="sse" -a date_range="20171227" 或 scrapy crawl annc -a annc_type="sse" -a date_range="20171221~20171231"可进行爬取 -------------------------------------------------------------------------------- /python_scraw/annc/annc/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/startprogress/China_stock_announcement/71e9e520d063f06f8779e4aa96bcac9bbca26eb7/python_scraw/annc/annc/__init__.py -------------------------------------------------------------------------------- /python_scraw/annc/annc/items.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Define here the models for your scraped items 4 | # 5 | # See documentation in: 6 | # http://doc.scrapy.org/en/latest/topics/items.html 7 | 8 | import scrapy 9 | 10 | class anncItem(scrapy.Item): 11 | annc_Key = scrapy.Field() 12 | symbol = scrapy.Field() 13 | abbr_Name = scrapy.Field() 14 | title = scrapy.Field() 15 | annc_Date = scrapy.Field() 16 | annc_Time = scrapy.Field() 17 | format = scrapy.Field() 18 | source = scrapy.Field() 19 | valid = scrapy.Field() 20 | acqu_Time = scrapy.Field() -------------------------------------------------------------------------------- /python_scraw/annc/annc/middlewares.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Define here the models for your spider middleware 4 | # 5 | # See documentation in: 6 | # http://doc.scrapy.org/en/latest/topics/spider-middleware.html 7 | 8 | from scrapy import signals 9 | 10 | 11 | class AnncSpiderMiddleware(object): 12 | # Not all methods need to be defined. If a method is not defined, 13 | # scrapy acts as if the spider middleware does not modify the 14 | # passed objects. 15 | 16 | @classmethod 17 | def from_crawler(cls, crawler): 18 | # This method is used by Scrapy to create your spiders. 19 | s = cls() 20 | crawler.signals.connect(s.spider_opened, signal=signals.spider_opened) 21 | return s 22 | 23 | def process_spider_input(self, response, spider): 24 | # Called for each response that goes through the spider 25 | # middleware and into the spider. 26 | 27 | # Should return None or raise an exception. 28 | return None 29 | 30 | def process_spider_output(self, response, result, spider): 31 | # Called with the results returned from the Spider, after 32 | # it has processed the response. 33 | 34 | # Must return an iterable of Request, dict or Item objects. 35 | for i in result: 36 | yield i 37 | 38 | def process_spider_exception(self, response, exception, spider): 39 | # Called when a spider or process_spider_input() method 40 | # (from other spider middleware) raises an exception. 41 | 42 | # Should return either None or an iterable of Response, dict 43 | # or Item objects. 44 | pass 45 | 46 | def process_start_requests(self, start_requests, spider): 47 | # Called with the start requests of the spider, and works 48 | # similarly to the process_spider_output() method, except 49 | # that it doesn’t have a response associated. 50 | 51 | # Must return only requests (not items). 52 | for r in start_requests: 53 | yield r 54 | 55 | def spider_opened(self, spider): 56 | spider.logger.info('Spider opened: %s' % spider.name) -------------------------------------------------------------------------------- /python_scraw/annc/annc/pipelines.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Define your item pipelines here 4 | # 5 | # Don't forget to add your pipeline to the ITEM_PIPELINES setting 6 | # See: http://doc.scrapy.org/en/latest/topics/item-pipeline.html 7 | import MySQLdb 8 | import MySQLdb.cursors 9 | from twisted.enterprise import adbapi 10 | 11 | class AnncPipeline(object): 12 | 13 | def __init__(self, dbpool): 14 | self.dbpool = dbpool 15 | 16 | # database config 17 | @classmethod 18 | def from_settings(cls, settings): 19 | dbparams = dict( 20 | host = settings['HOST_ADDRESS'], 21 | db = settings['DB_NAME'], 22 | user = settings['USER'], 23 | passwd = settings['PASSWORD'], 24 | charset = 'utf8', # 编码要加上,否则可能出现中文乱码问题 25 | cursorclass = MySQLdb.cursors.DictCursor, 26 | use_unicode = False, 27 | ) 28 | dbpool = adbapi.ConnectionPool('MySQLdb', **dbparams) # **表示将字典扩展为关键字参数,相当于host=xxx,db=yyy.... 29 | return cls(dbpool) # 相当于dbpool付给了这个类,self中可以得到 30 | 31 | # pipeline默认调用 32 | def process_item(self, item, spider): 33 | query = self.dbpool.runInteraction(self._conditional_insert, item) # 调用插入的方法 34 | query.addErrback(self._handle_error, item, spider) # 调用异常处理方法 35 | 36 | # 写入数据库中 37 | # SQL语句在这里 38 | def _conditional_insert(self, tx, item): 39 | sql = "insert into sse_annc_list(Annc_Key, Symbol, Abbr_Name, Title, Annc_Date, Annc_Time, Format, Source, Acqu_Time) values(%s, %s, %s, %s, %s, %s, %s, %s, %s)" 40 | params = (item['annc_Key'], item['symbol'], item['abbr_Name'], item['title'], item['annc_Date'], item['annc_Time'], item['format'], item['source'], item['acqu_Time']) 41 | tx.execute(sql, params) 42 | 43 | # 错误处理方法 44 | def _handle_error(self, failue, item, spider): 45 | print failue -------------------------------------------------------------------------------- /python_scraw/annc/annc/settings.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Scrapy settings for annc project 4 | # 5 | # For simplicity, this file contains only settings considered important or 6 | # commonly used. You can find more settings consulting the documentation: 7 | # 8 | # http://doc.scrapy.org/en/latest/topics/settings.html 9 | # http://scrapy.readthedocs.org/en/latest/topics/downloader-middleware.html 10 | # http://scrapy.readthedocs.org/en/latest/topics/spider-middleware.html 11 | 12 | 13 | ###################### 可编辑区 ################################## 14 | # 根据需要修改,ANNC_PATH是文件路径,LOG_PATH是日志路径 15 | ANNC_PATH = '' 16 | LOG_PATH = '' 17 | 18 | # 根据需要修改,MySQL数据库参数 19 | HOST_ADDRESS = '' 20 | USER = '' 21 | PASSWORD = '' 22 | PORT = '' 23 | # database 名称 24 | DB_NAME = '' 25 | #################################################################### 26 | 27 | 28 | 29 | 30 | BOT_NAME = 'annc' 31 | SPIDER_MODULES = ['annc.spiders'] 32 | NEWSPIDER_MODULE = 'annc.spiders' 33 | 34 | # Configure item pipelines 35 | # See http://scrapy.readthedocs.org/en/latest/topics/item-pipeline.html 36 | ITEM_PIPELINES = { 37 | 'annc.pipelines.AnncPipeline': 300, 38 | } 39 | 40 | 41 | # Crawl responsibly by identifying yourself (and your website) on the user-agent 42 | #USER_AGENT = 'annc (+http://www.yourdomain.com)' 43 | 44 | # Obey robots.txt rules 45 | ROBOTSTXT_OBEY = False 46 | 47 | # Configure maximum concurrent requests performed by Scrapy (default: 16) 48 | #CONCURRENT_REQUESTS = 32 49 | 50 | # Configure a delay for requests for the same website (default: 0) 51 | # See http://scrapy.readthedocs.org/en/latest/topics/settings.html#download-delay 52 | # See also autothrottle settings and docs 53 | #DOWNLOAD_DELAY = 3 54 | # The download delay setting will honor only one of: 55 | #CONCURRENT_REQUESTS_PER_DOMAIN = 16 56 | #CONCURRENT_REQUESTS_PER_IP = 16 57 | 58 | # Disable cookies (enabled by default) 59 | #COOKIES_ENABLED = False 60 | 61 | # Disable Telnet Console (enabled by default) 62 | #TELNETCONSOLE_ENABLED = False 63 | 64 | # Override the default request headers: 65 | #DEFAULT_REQUEST_HEADERS = { 66 | # 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 67 | # 'Accept-Language': 'en', 68 | #} 69 | 70 | # Enable or disable spider middlewares 71 | # See http://scrapy.readthedocs.org/en/latest/topics/spider-middleware.html 72 | #SPIDER_MIDDLEWARES = { 73 | # 'annc.middlewares.AnncSpiderMiddleware': 543, 74 | #} 75 | 76 | # Enable or disable downloader middlewares 77 | # See http://scrapy.readthedocs.org/en/latest/topics/downloader-middleware.html 78 | #DOWNLOADER_MIDDLEWARES = { 79 | # 'annc.middlewares.MyCustomDownloaderMiddleware': 543, 80 | #} 81 | 82 | # Enable or disable extensions 83 | # See http://scrapy.readthedocs.org/en/latest/topics/extensions.html 84 | #EXTENSIONS = { 85 | # 'scrapy.extensions.telnet.TelnetConsole': None, 86 | #} 87 | 88 | # Enable and configure the AutoThrottle extension (disabled by default) 89 | # See http://doc.scrapy.org/en/latest/topics/autothrottle.html 90 | #AUTOTHROTTLE_ENABLED = True 91 | # The initial download delay 92 | #AUTOTHROTTLE_START_DELAY = 5 93 | # The maximum download delay to be set in case of high latencies 94 | #AUTOTHROTTLE_MAX_DELAY = 60 95 | # The average number of requests Scrapy should be sending in parallel to 96 | # each remote server 97 | #AUTOTHROTTLE_TARGET_CONCURRENCY = 1.0 98 | # Enable showing throttling stats for every response received: 99 | #AUTOTHROTTLE_DEBUG = False 100 | 101 | # Enable and configure HTTP caching (disabled by default) 102 | # See http://scrapy.readthedocs.org/en/latest/topics/downloader-middleware.html#httpcache-middleware-settings 103 | #HTTPCACHE_ENABLED = True 104 | #HTTPCACHE_EXPIRATION_SECS = 0 105 | #HTTPCACHE_DIR = 'httpcache' 106 | #HTTPCACHE_IGNORE_HTTP_CODES = [] 107 | #HTTPCACHE_STORAGE = 'scrapy.extensions.httpcache.FilesystemCacheStorage' -------------------------------------------------------------------------------- /python_scraw/annc/annc/spiders/__init__.py: -------------------------------------------------------------------------------- 1 | # This package will contain the spiders of your Scrapy project 2 | # 3 | # Please refer to the documentation for information on how to create and manage 4 | # your spiders. 5 | -------------------------------------------------------------------------------- /python_scraw/annc/annc/spiders/anncSpider.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import sys 3 | reload(sys) 4 | sys.setdefaultencoding('utf-8') 5 | import os 6 | import unicodecsv 7 | import json 8 | import datetime 9 | import time 10 | import scrapy 11 | from scrapy import log 12 | import json 13 | from scrapy.http.request import Request 14 | from annc.items import anncItem 15 | from annc.settings import NEWSPIDER_MODULE 16 | import urllib2 17 | import logging 18 | import logging.handlers 19 | import codecs 20 | from bs4 import BeautifulSoup 21 | 22 | ################### 读取配置文件 ########################### 23 | # file path config 24 | from annc.settings import ANNC_PATH 25 | from annc.settings import LOG_PATH 26 | 27 | #################### 创建目录 ############################## 28 | if os.path.exists(ANNC_PATH) == False: 29 | os.makedirs(ANNC_PATH) 30 | if os.path.exists(LOG_PATH) == False: 31 | os.makedirs(LOG_PATH) 32 | 33 | # API 地址 34 | req = "http://www.cninfo.com.cn/cninfo-new/announcement/query" 35 | # 用于id去重 36 | d = dict() 37 | 38 | # Spider Class 39 | class anncSpider(scrapy.Spider): 40 | name = 'annc' 41 | 42 | def __init__(self, annc_type, date_range, *args, **kwargs): 43 | self.type = annc_type 44 | self.daterange = date_range 45 | 46 | def start_requests(self): 47 | global logger_error 48 | global logger 49 | 50 | if len(self.daterange) == 8: 51 | start_date = self.daterange[0:8] 52 | end_date = self.daterange[0:8] 53 | else: 54 | start_date = self.daterange[0:8] 55 | end_date = self.daterange[9:] 56 | if int(time.strftime('%H', time.localtime(time.time()))) > 14 and end_date == datetime.date.today().strftime("%Y%m%d"): 57 | end_date = (datetime.date.today() + datetime.timedelta(days=1)).strftime("%Y%m%d") 58 | 59 | date_range = [] 60 | # 先变为datetime对象便于操作 61 | curr_date = datetime.date( int(start_date[0:4]), int(start_date[4:6]), int(start_date[6:8]) ) 62 | end_date = datetime.date( int(end_date[0:4]), int(end_date[4:6]), int(end_date[6:8]) ) 63 | while curr_date != end_date: 64 | date_range.append(curr_date) 65 | curr_date += datetime.timedelta(days = 1) 66 | # 再把最后一天的加上 67 | date_range.append(curr_date) 68 | log_record = [] 69 | # 按天去下载 70 | for datei in date_range: 71 | #######################################日志处理############################ 72 | if str(datei)[0:7].replace('-', '') in log_record: 73 | pass 74 | else: 75 | log_record.append(str(datei)[0:7].replace('-', '')) 76 | # 上个月的日志关掉 77 | try: 78 | handler.flush() 79 | handler.close() 80 | logger.removeHandler(handler) 81 | handler_error.flush() 82 | handler_error.close() 83 | logger_error.removeHandler(handler_error) 84 | except: 85 | pass 86 | finally: 87 | # 错误日志 88 | if self.type == 'sse': 89 | LOG_ERROR_FILE = LOG_PATH + str(datei)[0:7].replace('-', '') + '_error.log' 90 | # if self.type == 'regulator': 91 | # LOG_ERROR_FILE = LOG_PATH + str(datei)[0:7].replace('-', '') + '_error.log' 92 | 93 | handler_error = logging.handlers.RotatingFileHandler( 94 | LOG_ERROR_FILE, maxBytes=1024 * 1024, backupCount=5) # 实例化handler 95 | fmt_error = '%(asctime)s - %(filename)s:%(lineno)s - %(levelname)s - %(message)s' 96 | formatter_error = logging.Formatter(fmt_error) # 实例化formatter 97 | handler_error.setFormatter( 98 | formatter_error) # 为handler添加formatter 99 | logger_error = logging.getLogger('annc_error') # 获取名为content的logger 100 | # 为logger添加handler 101 | logger_error.addHandler(handler_error) 102 | logger_error.setLevel(logging.ERROR) 103 | 104 | # INFO日志处理 105 | if self.type == 'sse': 106 | LOG_INFO_FILE = LOG_PATH + str(datei)[0:7].replace('-', '') + '_info.log' 107 | # if annc_type == 'regulator': 108 | # LOG_INFO_FILE = LOG_PATH + str(datei)[0:7].replace('-', '') + '_info.log' 109 | 110 | handler = logging.handlers.RotatingFileHandler( 111 | LOG_INFO_FILE, maxBytes=1024 * 1024, backupCount=5) # 实例化handler 112 | fmt = '%(asctime)s - %(levelname)s - %(message)s' 113 | formatter = logging.Formatter(fmt) # 实例化formatter 114 | handler.setFormatter(formatter) # 为handler添加formatter 115 | logger = logging.getLogger('annc_info') # 获取名为content的logger 116 | logger.addHandler(handler) # 为logger添加handler 117 | logger.setLevel(logging.INFO) 118 | ##################################################################################### 119 | yield scrapy.FormRequest( url = req, method = "POST", formdata={'column': self.type, 'seDate': str(datei)[0:10], 'pageNum': '1', 'tabName': 'fulltext'}, callback = lambda response, datei = datei: self.parse(response, datei), dont_filter = True) 120 | 121 | 122 | def parse(self, response, datei): 123 | j = json.loads(response.body_as_unicode()) 124 | totalRecordNum = j['totalRecordNum'] 125 | pageNum = totalRecordNum / 30 + 1 if totalRecordNum % 30 > 0 else totalRecordNum / 30 126 | for i in range (1, pageNum + 1): 127 | yield scrapy.FormRequest( url = req, method = "POST", formdata={'column': self.type, 'seDate': str(datei)[0:10], 'pageNum': str(i), 'tabName': 'fulltext'}, callback = lambda response, datei = datei: self.main(response, datei), dont_filter = True) 128 | 129 | 130 | def main(self, response, datei): 131 | j = json.loads(response.body_as_unicode())['announcements'] 132 | for i in range(0, len(j)): 133 | item = anncItem() 134 | item['symbol'] = str(j[i]['secCode']) 135 | if len(item['symbol']) == 6: 136 | if item['symbol'] in d: 137 | d[item['symbol']] = int(d[item['symbol']]) + 1 138 | else: 139 | d[item['symbol']] = 1 140 | if d[item['symbol']] < 10: 141 | anncid = item['symbol'] + str(datei).replace('-', '') + '00' + str(d[item['symbol']]) 142 | elif d[item['symbol']] < 100: 143 | anncid = item['symbol'] + str(datei).replace('-', '') + '0' + str(d[item['symbol']]) 144 | else: 145 | anncid = item['symbol'] + str(datei).replace('-', '') + str(d[item['symbol']]) 146 | item['annc_Key'] = str(anncid) 147 | item['title'] = str(j[i]['announcementTitle'].replace(',', '').replace('', '').replace('', '').replace('\n', '')) 148 | item['source'] = str('http://www.cninfo.com.cn/' + j[i]['adjunctUrl'].strip()) 149 | item['abbr_Name'] = str(j[i]['secName']) 150 | item['valid'] = 0 151 | file_type = "" 152 | if str.lower(item['source']).find('html') > -1: 153 | file_type = 'TXT' 154 | if downhtml(item['annc_Key'], item['source']): 155 | item['valid'] = 1 156 | elif str.lower(item['source']).find('.js') > -1: 157 | file_type = 'TXT' 158 | if downjs(item['annc_Key'], item['source']): 159 | item['valid'] = 1 160 | elif str.lower(item['source']).find('.pdf') > -1: 161 | file_type = 'PDF' 162 | if downpdf(item['annc_Key'], item['source']): 163 | item['valid'] = 1 164 | elif str.lower(item['source']).find('.doc') > -1: 165 | if str.lower(item['source']).find('.docx') > -1: 166 | file_type = 'DOCX' 167 | else: 168 | file_type = 'DOC' 169 | if downdoc(item['annc_Key'], item['source']): 170 | item['valid'] = 1 171 | else: 172 | file_type = 'UNKNOWN' 173 | item['format'] = str(file_type) 174 | anncTime = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(j[i]['announcementTime'] / 1000)) 175 | item['annc_Date'] = anncTime[0:10] 176 | item['annc_Time'] = anncTime[-8:] 177 | item['acqu_Time'] = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") 178 | yield item 179 | 180 | 181 | ###################################### 功能性函数 下载公告文件 ############################################# 182 | # 把html网页的文字下载到txt中 183 | def downhtml(anncid, url): 184 | flag = False 185 | try: 186 | contentpage = urllib2.urlopen(url) 187 | except urllib2.URLError, e: 188 | logger_error.error('公告链接错误 id号 URL网址: %s %s %s' % (e, anncid, url)) 189 | except socket.timeout: 190 | downhtml(anncid, url) 191 | except socket.error, e: 192 | if str(e).find('Connection reset by peer') or str(e).find('Operation timed out') != -1: 193 | downhtml(anncid, url) 194 | else: 195 | logger_error.error('公告链接错误 id号 URL网址: %s %s %s' % (e, anncid, url)) 196 | else: 197 | contentsoup = BeautifulSoup( 198 | contentpage, 'lxml', from_encoding="utf-8") 199 | try: 200 | content = contentsoup.findAll('span', {'class': 'da'}) 201 | con_len = len(content) 202 | content_txt = content[con_len - 1].get_text() 203 | except IndexError, e: 204 | try: 205 | content = contentsoup.findAll('pre') 206 | con_len = len(content) 207 | content_txt = content[0].get_text() 208 | except IndexError, e: 209 | logger_error.error('页面解析错误 id号 URL网址: %s %s %s' % (e, anncid, url)) 210 | else: 211 | f_temp = codecs.open(ANNC_PATH + anncid + '.txt', 'w+', encoding='utf-8') 212 | f_temp.write(content_txt) 213 | f_temp.close() 214 | logger.info('成功下载: id为:%s url:%s ' % (anncid, url)) 215 | flag = True 216 | else: 217 | f_temp = codecs.open(ANNC_PATH + anncid + '.txt', 'w+', encoding='utf-8') 218 | f_temp.write(content_txt) 219 | f_temp.close() 220 | logger.info('成功下载: id为:%s url:%s ' % (anncid, url)) 221 | flag = True 222 | finally: 223 | if 'contentpage' in locals().keys(): 224 | contentpage.close() 225 | return flag 226 | 227 | # 把js返回的文字下载到txt中 228 | def downjs(anncid, url): 229 | flag = False 230 | try: 231 | contentpage = urllib2.urlopen(url) 232 | content_txt = contentpage.read() 233 | except urllib2.URLError, e: 234 | logger_error.error('公告链接错误 id号 URL网址: %s %s %s' % (e, anncid, url)) 235 | except socket.timeout: 236 | downjs(anncid, url) 237 | except socket.error, e: 238 | if str(e).find('Connection reset by peer') or str(e).find('Operation timed out') != -1: 239 | downjs(anncid, url) 240 | else: 241 | logger_error.error('公告链接错误 id号 URL网址: %s %s %s' % (e, anncid, url)) 242 | else: 243 | try: 244 | content_txt = content_txt.decode('gbk').encode('utf-8') 245 | except UnicodeDecodeError, e: 246 | logger_error.error('js文件解码错误 id号 URL网址: %s %s %s' % (e, anncid, url)) 247 | else: 248 | content_txt = re.search( 249 | r'"Zw":(.*)
', content_txt) 250 | if content_txt == None: 251 | logger_error.error('js文件解码错误 id号 URL网址: %s %s %s' % (e, anncid, url)) 252 | else: 253 | content_txt = content_txt.group().replace('
', '').replace('"Zw":"', '') 254 | f_temp = codecs.open( 255 | ANNC_PATH + anncid + '.txt', 'w+', encoding='utf-8') 256 | f_temp.write(content_txt) 257 | f_temp.close() 258 | logger.info('成功下载: id为:%s url:%s ' % (anncid, url)) 259 | flag = True 260 | finally: 261 | if 'contentpage' in locals().keys(): 262 | contentpage.close() 263 | return flag 264 | 265 | # 下载doc 266 | def downdoc(anncid, url): 267 | flag = False 268 | try: 269 | contentpage = urllib2.urlopen(url) 270 | content_doc = contentpage.read() 271 | except urllib2.URLError, e: 272 | logger_error.error('公告链接错误 id号 URL网址: %s %s %s' % (e, anncid, url)) 273 | except urllib2.URLError, e: 274 | logger_error.error('公告链接错误 id号 URL网址: %s %s %s' % (e, anncid, url)) 275 | except httplib.BadStatusLine, e: 276 | logger_error.error('公告链接错误 id号 URL网址: %s %s %s' % (e, anncid, url)) 277 | except socket.timeout: 278 | downdoc(anncid, url) 279 | except socket.error, e: 280 | if str(e).find('Connection reset by peer') or str(e).find('Operation timed out') != -1: 281 | downdoc(anncid, url) 282 | else: 283 | logger_error.error('公告链接错误 id号 URL网址: %s %s %s' % (e, anncid, url)) 284 | else: 285 | if url.find('.docx') > -1 or url.find('.DOCX') > -1: 286 | f_temp = open(ANNC_PATH + anncid + '.docx', 'w+') 287 | else: 288 | f_temp = open(ANNC_PATH + anncid + '.doc', 'w+') 289 | f_temp.write(content_doc) 290 | f_temp.close() 291 | logger.info('成功下载: id为:%s url:%s ' % (anncid, url)) 292 | flag =True 293 | finally: 294 | if 'contentpage' in locals().keys(): 295 | contentpage.close() 296 | return flag 297 | 298 | # 下载pdf 299 | def downpdf(anncid, url): 300 | flag = False 301 | try: 302 | contentpage = urllib2.urlopen(url) 303 | content_pdf = contentpage.read() 304 | except httplib.BadStatusLine, e: 305 | logger_error.error('公告链接错误 id号 URL网址: %s %s %s' % (e, anncid, url)) 306 | except socket.timeout: 307 | downpdf(anncid, url) 308 | except socket.error, e: 309 | if str(e).find('Connection reset by peer') or str(e).find('Operation timed out') != -1: 310 | downpdf(anncid, url) 311 | else: 312 | logger_error.error('公告链接错误 id号 URL网址: %s %s %s' % (e, anncid, url)) 313 | else: 314 | f_temp = open(ANNC_PATH + anncid + '.pdf', 'w+') 315 | f_temp.write(content_pdf) 316 | f_temp.close() 317 | logger.info('成功下载: id为:%s url:%s ' % (anncid, url)) 318 | flag = True 319 | finally: 320 | if 'contentpage' in locals().keys(): 321 | contentpage.close() 322 | return flag -------------------------------------------------------------------------------- /python_scraw/annc/scrapy.cfg: -------------------------------------------------------------------------------- 1 | [settings] 2 | default = annc.settings 3 | 4 | [deploy] 5 | #url = http://localhost:6800/ 6 | project = annc -------------------------------------------------------------------------------- /python_scraw/cninfo_main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | #-*- coding: utf-8 -*- 3 | import sys 4 | reload(sys) 5 | sys.setdefaultencoding('utf-8') 6 | import os 7 | import httplib 8 | import urllib 9 | import urllib2 10 | import socket 11 | import unicodecsv 12 | import json 13 | import re 14 | import calendar 15 | import datetime 16 | import time 17 | import logging 18 | import logging.handlers 19 | import codecs 20 | import sys 21 | import gzip 22 | import StringIO 23 | import MySQLdb 24 | from warnings import filterwarnings 25 | filterwarnings('error', category=MySQLdb.Warning) 26 | from bs4 import BeautifulSoup 27 | 28 | ################### 读取配置文件 ########################### 29 | import ConfigParser 30 | #生成config对象 31 | conf = ConfigParser.ConfigParser() 32 | #用config对象读取配置文件 33 | conf.read("config.cfg") 34 | # 赋值 35 | filepath = conf.get('file', 'filepath') 36 | logpath = conf.get('file', 'logpath') 37 | host_address = conf.get('database', 'host_address') 38 | user = conf.get('database', 'user') 39 | password = conf.get('database', 'password') 40 | port = int(conf.get('database', 'port')) 41 | ############################################################ 42 | 43 | ############################mkdir sub path################################### 44 | if os.path.exists(filepath) == False: 45 | os.makedirs(filepath) 46 | if os.path.exists(logpath) == False: 47 | os.makedirs(logpath) 48 | ############################################################################# 49 | 50 | # 把日期按日拆分后,每日都调用parse函数,解析页面,然后根据公告文件类型不同,调用不同的下载函数 51 | def main(annc_type, start_date=datetime.datetime.today().strftime("%Y%m%d"), end_date=datetime.datetime.today().strftime("%Y%m%d"), savepath=filepath): 52 | if savepath[-1] != '/': 53 | savepath += savepath + '/' 54 | currentMinute = int(time.strftime('%M', time.localtime(time.time()))) 55 | currentHour = int(time.strftime('%H', time.localtime(time.time()))) 56 | # 当天下午2点以后要提前追一天,因为有一些公告会提前放出来 57 | if currentHour > 14: 58 | end_date = (datetime.date.today() + datetime.timedelta(days=1)).strftime("%Y%m%d") 59 | global logger_error 60 | global logger 61 | # 生产日期列表 62 | date_range = [] 63 | # 先变为datetime对象便于操作 64 | curr_date = datetime.date( 65 | int(start_date[0:4]), int(start_date[4:6]), int(start_date[6:8])) 66 | end_date = datetime.date( 67 | int(end_date[0:4]), int(end_date[4:6]), int(end_date[6:8])) 68 | while curr_date != end_date: 69 | date_range.append(curr_date) 70 | curr_date += datetime.timedelta(days=1) 71 | # 再把最后一天的加上 72 | date_range.append(curr_date) 73 | # 每日循环下载,并分月建立日志(便于一次性下载很长一段时间的公告) 74 | log_record = [] 75 | for datei in date_range: 76 | #######################################日志处理############################ 77 | if str(datei)[0:7].replace('-', '') in log_record: 78 | pass 79 | else: 80 | log_record.append(str(datei)[0:7].replace('-', '')) 81 | # 上个月的日志关掉 82 | try: 83 | handler.flush() 84 | handler.close() 85 | logger.removeHandler(handler) 86 | handler_error.flush() 87 | handler_error.close() 88 | logger_error.removeHandler(handler_error) 89 | except: 90 | pass 91 | finally: 92 | # 错误日志 93 | if annc_type == 'sse': 94 | LOG_ERROR_FILE = logpath + \ 95 | str(datei)[0:7].replace('-', '') + '_error.log' 96 | if annc_type == 'regulator': 97 | LOG_ERROR_FILE = logpath + \ 98 | str(datei)[0:7].replace('-', '') + '_error.log' 99 | 100 | handler_error = logging.handlers.RotatingFileHandler( 101 | LOG_ERROR_FILE, maxBytes=1024 * 1024, backupCount=5) # 实例化handler 102 | fmt_error = '%(asctime)s - %(filename)s:%(lineno)s - %(levelname)s - %(message)s' 103 | formatter_error = logging.Formatter(fmt_error) # 实例化formatter 104 | handler_error.setFormatter( 105 | formatter_error) # 为handler添加formatter 106 | logger_error = logging.getLogger( 107 | 'annc_error') # 获取名为content的logger 108 | # 为logger添加handler 109 | logger_error.addHandler(handler_error) 110 | logger_error.setLevel(logging.ERROR) 111 | 112 | # INFO日志处理 113 | if annc_type == 'sse': 114 | LOG_INFO_FILE = logpath + \ 115 | str(datei)[0:7].replace('-', '') + '_info.log' 116 | if annc_type == 'regulator': 117 | LOG_INFO_FILE = logpath + \ 118 | str(datei)[0:7].replace('-', '') + '_info.log' 119 | 120 | handler = logging.handlers.RotatingFileHandler( 121 | LOG_INFO_FILE, maxBytes=1024 * 1024, backupCount=5) # 实例化handler 122 | fmt = '%(asctime)s - %(levelname)s - %(message)s' 123 | formatter = logging.Formatter(fmt) # 实例化formatter 124 | handler.setFormatter(formatter) # 为handler添加formatter 125 | logger = logging.getLogger('annc_info') # 获取名为content的logger 126 | logger.addHandler(handler) # 为logger添加handler 127 | logger.setLevel(logging.INFO) 128 | # 按日下载 129 | parse(annc_type, datei, savepath) 130 | 131 | 132 | 133 | ####################################################下载公告列表,解析并下载公告######## 134 | def parse(columntype, daterange_i, downloadpath): 135 | # 检查路径,若没有即创建 136 | if columntype == 'sse': 137 | contentpath = downloadpath + 'sse/content/' + \ 138 | str(daterange_i)[0:4] + '/' + str(daterange_i)[5:7] + '/' 139 | listpath = downloadpath + 'sse/list/' + \ 140 | str(daterange_i)[0:4] + '/' 141 | if columntype == 'regulator': 142 | contentpath = downloadpath + 'reg/content/' + \ 143 | str(daterange_i)[0:4] + '/' + str(daterange_i)[5:7] + '/' 144 | listpath = downloadpath + 'reg/list/' + \ 145 | str(daterange_i)[0:4] + '/' 146 | columntype = 'regulator' 147 | if os.path.exists(contentpath) == False: 148 | os.makedirs(contentpath) 149 | if os.path.exists(listpath) == False: 150 | os.makedirs(listpath) 151 | # 服务器地址starturl 152 | starturl = 'http://www.cninfo.com.cn/cninfo-new/announcement/query' 153 | 154 | ############################################ list 部分 ##################### 155 | # 读取最新的URL列表, 放入now [] 156 | now = [] 157 | # 字典d用于得到每只股票的当日anncid 158 | d = dict() # 用于形成anncid里的序号 159 | flag = True # 用于确认是否有下一页的布尔值 160 | page_num = 1 # 起始页为1 161 | while flag == True: 162 | # request headers 163 | headers = { 164 | "Host": "www.cninfo.com.cn", 165 | "Connection": "keep-alive", 166 | "Accept": "application/json, text/javascript, */*; q=0.01", 167 | "Origin": "http://www.cninfo.com.cn", 168 | "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8", 169 | "Referer": "http://www.cninfo.com.cn/cninfo-new/announcement/show", 170 | "Accept-Encoding": "gzip, deflate", 171 | "Accept-Language": "zh-CN,zh;q=0.8,en;q=0.6" 172 | } 173 | 174 | # request data 175 | datas = [] 176 | sse_data = 'stock=&searchkey=&plate=&category=&trade=&column=' + columntype + '&columnTitle=%E5%8E%86%E5%8F%B2%E5%85%AC%E5%91%8A%E6%9F%A5%E8%AF%A2&pageNum=' + \ 177 | str(page_num) + '&pageSize=30&tabName=fulltext&sortName=&sortType=&limit=&showTitle=&seDate=' + str(daterange_i) 178 | 179 | jgjg_sz_data = 'stock=&searchkey=' + '&plate=jgjg_sz%3B' +'&category=&trade=&column=' + columntype + '&columnTitle=%E5%8E%86%E5%8F%B2%E5%85%AC%E5%91%8A%E6%9F%A5%E8%AF%A2&pageNum=' + \ 180 | str(page_num) + '&pageSize=30&tabName=fulltext&sortName=&sortType=&limit=&showTitle=jgjg_sz%2Fplate%2F%E6%B7%B1%E4%BA%A4%E6%89%80%E5%85%AC%E5%91%8A&seDate=' + str(daterange_i) 181 | jgjg_sh_data = 'stock=&searchkey=' + '&plate=jgjg_sh%3B' + '&category=&trade=&column=' + columntype + '&columnTitle=%E5%8E%86%E5%8F%B2%E5%85%AC%E5%91%8A%E6%9F%A5%E8%AF%A2&pageNum=' + \ 182 | str(page_num) + '&pageSize=30&tabName=fulltext&sortName=&sortType=&limit=&showTitle=jgjg_sh%2Fplate%2F%E4%B8%8A%E4%BA%A4%E6%89%80%E5%85%AC%E5%91%8A&seDate=' + str(daterange_i) 183 | jgjg_jsgs_data = 'stock=&searchkey=' + '&plate=jgjg_jsgs%3B' + '&category=&trade=&column=' + columntype + '&columnTitle=%E5%8E%86%E5%8F%B2%E5%85%AC%E5%91%8A%E6%9F%A5%E8%AF%A2&pageNum=' + \ 184 | str(page_num) + '&pageSize=30&tabName=fulltext&sortName=&sortType=&limit=&showTitle=jgjg_jsgs%2Fplate%2F%E7%BB%93%E7%AE%97%E5%85%AC%E5%8F%B8%E5%85%AC%E5%91%8A&seDate=' + str(daterange_i) 185 | jgjg_zjh_data = 'stock=&searchkey=' + '&plate=jgjg_zjh%3B' + '&category=&trade=&column=' + columntype + '&columnTitle=%E5%8E%86%E5%8F%B2%E5%85%AC%E5%91%8A%E6%9F%A5%E8%AF%A2&pageNum=' + \ 186 | str(page_num) + '&pageSize=30&tabName=fulltext&sortName=&sortType=&limit=&showTitle=jgjg_zjh%2Fplate%2F%E8%AF%81%E7%9B%91%E4%BC%9A%E5%85%AC%E5%91%8A&seDate=' + str(daterange_i) 187 | 188 | 189 | if columntype == 'regulator': 190 | datas.append(jgjg_sz_data) 191 | datas.append(jgjg_sh_data) 192 | datas.append(jgjg_jsgs_data) 193 | datas.append(jgjg_zjh_data) 194 | elif columntype == 'sse': 195 | datas.append(sse_data) 196 | for data in datas: 197 | req = urllib2.Request(starturl, data, headers) 198 | try: 199 | response = urllib2.urlopen(req) 200 | 201 | except urllib2.HTTPError, e: 202 | logger_error.error('响应错误 日期 页数: %s %s %s' % 203 | (e, str(daterange_i), str(page_num))) 204 | flag = False 205 | except urllib2.URLError, e: 206 | logger_error.error('响应错误 日期 页数: %s %s %s' % 207 | (e, str(daterange_i), str(page_num))) 208 | flag = False 209 | except socket.error, e: 210 | logger_error.error('响应错误 日期 页数: %s %s %s' % 211 | (e, str(daterange_i), str(page_num))) 212 | flag = False 213 | else: 214 | # 需要将response解压缩 215 | # 参考: https://www.cnblogs.com/bbcar/p/3625084.html 216 | res_data = StringIO.StringIO(response.read()) 217 | rzip = gzip.GzipFile(fileobj = res_data) 218 | r = rzip.read() 219 | try: 220 | # 将相应json化便于用字典读取 221 | j = json.loads(r) 222 | except ValueError, e: 223 | logger_error.error('响应错误 日期 页数: %s %s %s' % 224 | (e, str(daterange_i), str(page_num))) 225 | flag = False 226 | else: 227 | flag = j['hasMore'] 228 | # 记录日志 229 | logger.info('日 期:' + str(daterange_i) + ' PageNUmber = ' + str(page_num) + 230 | ' hasMore = ' + str(flag)) 231 | # 把每一页的项目append 到now里 232 | for item_num in range(0, len(j['announcements'])): 233 | ii = j['announcements'][item_num] 234 | valid = 0 # 下载成功后变为1 235 | # 得到 title url 和 file_type 236 | title = ii['announcementTitle'].replace(',', '').replace( 237 | '', '').replace('', '').replace('\n', '') 238 | url = 'http://www.cninfo.com.cn/' + \ 239 | ii['adjunctUrl'].strip() 240 | # 防止重复 241 | if (url in d) == False: 242 | d[url] = 'Yes' 243 | ########################确定公告文件的类型file_type############# 244 | if url.find('.html') > -1: 245 | file_type = 'TXT' 246 | elif url.find('.js') > -1: 247 | file_type = 'TXT' 248 | elif url.find('.pdf') > -1 or url.find('.PDF') > -1: 249 | file_type = 'PDF' 250 | elif url.find('.doc') > -1 or url.find('.DOC') > -1: 251 | if url.find('.docx') > -1 or url.find('.DOCX') > -1: 252 | file_type = 'DOCX' 253 | else: 254 | file_type = 'DOC' 255 | else: 256 | file_type = 'UNKNOEN' 257 | ####################################################### 258 | # 把时间戳转为yyyy-mm-dd hh:mm:ss的形式,若没有,则按00:00:00算 259 | try: 260 | antime = time.strftime( 261 | '%Y-%m-%d %H:%M:%S', time.localtime(ii['announcementTime'] / 1000)) 262 | except ValueError, e: 263 | antime = daterange_i + ' 00:00:00' 264 | else: 265 | pass 266 | if columntype == 'sse': 267 | abbv = ii['secName'] 268 | symbol = ii['secCode'] 269 | # 生成anncid 270 | if len(symbol) == 6: 271 | if symbol in d: 272 | d[symbol] = int(d[symbol]) + 1 273 | else: 274 | d[symbol] = 1 275 | # 1位数字添00,2位数字添0 276 | if d[symbol] < 10: 277 | anncid = symbol + \ 278 | str(daterange_i).replace( 279 | '-', '') + '00' + str(d[symbol]) 280 | elif d[symbol] < 100: 281 | anncid = symbol + \ 282 | str(daterange_i).replace( 283 | '-', '') + '0' + str(d[symbol]) 284 | else: 285 | anncid = symbol + \ 286 | str(daterange_i).replace( 287 | '-', '') + str(d[symbol]) 288 | anncid = str(anncid) 289 | 290 | now.append([anncid, symbol, abbv, title, antime[ 291 | 0:10], antime[-8:], file_type, url, valid, datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")]) 292 | elif columntype == 'regulator': 293 | symbol = ii['secCode'].replace(',', ';') 294 | # 根据查询参数来确定公告类型 295 | if data.find('jgjg_sz') > -1: 296 | regu_type = 'SZSE' 297 | elif data.find('jgjg_sh') > -1: 298 | regu_type = 'SSE' 299 | elif data.find('plate=jgjg_jsgs') > -1: 300 | regu_type = 'CSDC' 301 | elif data.find('jgjg_zjh') > -1: 302 | regu_type = 'CSRC' 303 | if regu_type in d: 304 | d[regu_type] = int(d[regu_type]) + 1 305 | else: 306 | d[regu_type] = 1 307 | # 个位数字添0 308 | if d[regu_type] < 10: 309 | anncid = regu_type + \ 310 | str(daterange_i).replace( 311 | '-', '') + '0' + str(d[regu_type]) 312 | else: 313 | anncid = regu_type + \ 314 | str(daterange_i).replace( 315 | '-', '') + str(d[regu_type]) 316 | now.append([anncid, symbol, regu_type, title, antime[ 317 | 0:10], antime[-8:], file_type, url, valid, datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")]) 318 | 319 | page_num += 1 320 | response.close() 321 | 322 | # 如果没有数据则不进行后续工作 323 | if len(now) != 0: 324 | # 把已存文件的内容读出来,作为old [],若当日无csv则创建,old置空 325 | old = [] 326 | temp = [] 327 | if os.path.exists(listpath + str(daterange_i) + '.csv'): 328 | f_old = open(listpath + str(daterange_i) + '.csv', 'r+') 329 | f_r = unicodecsv.reader(f_old, encoding='utf-8') 330 | for row in f_r: 331 | old.append(row) 332 | f_old.close() 333 | # 把now中与old重复的去掉,计入temp 334 | for i in now: 335 | has = False 336 | for j in old: 337 | if i[7].strip() == j[7].strip(): 338 | has = True 339 | if has == False: 340 | temp.append(i) 341 | else: 342 | temp = now 343 | 344 | #########################################download部分#################### 345 | # 如果有新的,就更新到csv和数据库里 346 | if len(temp) != 0: 347 | # 把temp中url指向的公告下载到contentpath下,并更新temp到tempupdate 348 | temp_update = [] 349 | # temp里的公告都尝试下载,并根据是否成功下载,更新为temp_updata 350 | for row in temp: 351 | url = row[7] 352 | anncid = row[0] 353 | # 解析url类型并下载url链接下的公告 354 | # 根据是否成功下载 更新valid字段的值 355 | if url.find('.html') > -1 and downhtml(contentpath, anncid, url): 356 | row[8] = 1 357 | elif url.find('.js') > -1 and downjs(contentpath, anncid, url): 358 | row[8] = 1 359 | elif (url.find('.doc') > -1 or url.find('.DOC') > -1) and downdoc(contentpath, anncid, url): 360 | row[8] = 1 361 | elif (url.find('.pdf') > -1 or url.find('.PDF') > -1) and downpdf(contentpath, anncid, url): 362 | row[8] = 1 363 | else: 364 | logger_error.error( 365 | '公告新类型未下载: id号 URL网址: %s %s' % (anncid, url)) 366 | temp_update.append(row) 367 | logger.info('本次成功下载了' + str(len(temp_update)) + '份公告') 368 | 369 | # 把之前未存的temp 里的数据 更新到月csv 和 日csv, 日csv里的内容作为下次的 old[] 370 | f_mon = open(listpath + str(daterange_i) 371 | [0:7].replace('-', '') + '.csv', 'a+') 372 | f_w = unicodecsv.writer( 373 | f_mon, encoding='utf-8') # 直接使用csv则存储的都是二进制 374 | for row in temp_update: 375 | f_w.writerow(row) 376 | f_mon.close() 377 | f_day = open(listpath + str(daterange_i) + '.csv', 'a+') 378 | f_w = unicodecsv.writer( 379 | f_day, encoding='utf-8') # 直接使用csv则存储的都是二进制 380 | for row in temp_update: 381 | f_w.writerow(row) 382 | f_day.close() 383 | f_tmp = open(listpath + str(daterange_i) + '_temp.csv', 'a+') 384 | f_w = unicodecsv.writer( 385 | f_tmp, encoding='utf-8') # 直接使用csv则存储的都是二进制 386 | for row in temp_update: 387 | f_w.writerow(row) 388 | f_tmp.close() 389 | 390 | #把更新的数据倒入数据库中 ,然后把temp.csv删掉 391 | if columntype == 'sse': 392 | import2mysql(columntype, listpath + 393 | str(daterange_i) + '_temp.csv', 'sse_annc_list') 394 | if columntype == 'regulator': 395 | import2mysql(columntype, listpath + 396 | str(daterange_i) + '_temp.csv', 'reg_annc_list') 397 | #公告影响表 398 | impact = [] 399 | f_impact = open(listpath + 'impact.csv', 'a+') 400 | f_w = unicodecsv.writer( 401 | f_impact, encoding='utf-8') # 直接使用csv则存储的都是二进制 402 | for row in temp_update: 403 | if len(row[0]) > 3 and row[1] != None and row[1] != '': 404 | impact_i = row[1].strip('\n').split(';') 405 | for imp in impact_i: 406 | if imp != '': 407 | impact.append([row[0], imp]) 408 | for item in impact: 409 | f_w.writerow(item) 410 | f_impact.close() 411 | import2mysql(columntype, listpath + 412 | 'impact.csv', 'reg_impact_list') 413 | os.remove(listpath + 'impact.csv') 414 | os.remove(listpath + str(daterange_i) + '_temp.csv') 415 | 416 | 417 | def import2mysql(columntype, csvfile, tablename): 418 | if columntype == 'sse': 419 | LOG_FILE = logpath + 'sse_mysql.log' 420 | if columntype == 'regulator': 421 | LOG_FILE = logpath + 'regu_mysql.log' 422 | handler_mysql = logging.handlers.RotatingFileHandler( 423 | LOG_FILE, maxBytes=1024 * 1024, backupCount=5) # 实例化handler 424 | fmt_mysql = '%(asctime)s - %(message)s' 425 | formatter_mysql = logging.Formatter(fmt_mysql) # 实例化formatter 426 | handler_mysql.setFormatter(formatter_mysql) # 为handler添加formatter 427 | logger_mysql = logging.getLogger('mysql') # 获取名为import的logger 428 | logger_mysql.addHandler(handler_mysql) # 为logger添加handler 429 | logger_mysql.setLevel(logging.DEBUG) 430 | # 连接数据库 431 | try: 432 | conn = MySQLdb.connect(host=host_address, user=user, 433 | passwd=password, port=port) 434 | cur = conn.cursor() 435 | except MySQLdb.Error, e: 436 | logger_mysql.error("MySQL数据连接不上 %s" % (str(e))) 437 | else: 438 | # datebase stock 439 | cur.execute('use stock;') 440 | sql = "load data local infile " + "'" + csvfile + "'" + \ 441 | " into table " + tablename + " fields terminated by ',' lines terminated by '\n';" 442 | try: 443 | cur.execute(sql) # 执行sql语句 444 | conn.commit() # 提交 445 | except MySQLdb.Warning: 446 | cur.execute("SHOW WARNINGS") 447 | w = cur.fetchall() 448 | for i in w: 449 | logger_mysql.info(" %s" % (i,)) 450 | except MySQLdb.Error, e: 451 | logger_mysql.error("数据导入mysql错误 %s %s" % (csvfile, str(e),)) 452 | else: 453 | logger_mysql.info("处理文件成功 %s" % (csvfile, )) # 操作成功 454 | # 关闭日志 455 | handler_mysql.flush() 456 | handler_mysql.close() 457 | logger_mysql.removeHandler(handler_mysql) 458 | cur.close() # 关闭操作 459 | conn.close() # 关闭连接 460 | 461 | #把html网页的文字下载到txt中 462 | def downhtml(contentpath, anncid, url): 463 | flag = False 464 | try: 465 | contentpage = urllib2.urlopen(url) 466 | except urllib2.URLError, e: 467 | logger_error.error( 468 | '公告链接错误 id号 URL网址: %s %s %s' % (e, anncid, url)) 469 | except socket.timeout: 470 | downhtml(contentpath, anncid, url) 471 | except socket.error, e: 472 | if str(e).find('Connection reset by peer') or str(e).find('Operation timed out') != -1: 473 | downhtml(contentpath, anncid, url) 474 | else: 475 | logger_error.error( 476 | '公告链接错误 id号 URL网址: %s %s %s' % (e, anncid, url)) 477 | else: 478 | contentsoup = BeautifulSoup( 479 | contentpage, 'lxml', from_encoding="utf-8") 480 | try: 481 | content = contentsoup.findAll( 482 | 'span', {'class': 'da'}) 483 | con_len = len(content) 484 | content_txt = content[ 485 | con_len - 1].get_text() 486 | except IndexError, e: 487 | try: 488 | content = contentsoup.findAll( 489 | 'pre') 490 | con_len = len(content) 491 | content_txt = content[0].get_text() 492 | except IndexError, e: 493 | logger_error.error( 494 | '页面解析错误 id号 URL网址: %s %s %s' % (e, anncid, url)) 495 | else: 496 | f_temp = codecs.open( 497 | contentpath + anncid + '.txt', 'w+', encoding='utf-8') 498 | f_temp.write(content_txt) 499 | f_temp.close() 500 | logger.info('成功下载: id为:%s url:%s ' % 501 | (anncid, url)) 502 | flag = True 503 | else: 504 | f_temp = codecs.open( 505 | contentpath + anncid + '.txt', 'w+', encoding='utf-8') 506 | f_temp.write(content_txt) 507 | f_temp.close() 508 | logger.info('成功下载: id为:%s url:%s ' % (anncid, url)) 509 | flag = True 510 | finally: 511 | if 'contentpage' in locals().keys(): 512 | contentpage.close() 513 | return flag 514 | 515 | ##把js返回的文字下载到txt中 516 | def downjs(contentpath, anncid, url): 517 | flag = False 518 | try: 519 | contentpage = urllib2.urlopen(url) 520 | content_txt = contentpage.read() 521 | except urllib2.URLError, e: 522 | logger_error.error( 523 | '公告链接错误 id号 URL网址: %s %s %s' % (e, anncid, url)) 524 | except socket.timeout: 525 | downjs(contentpath, anncid, url) 526 | except socket.error, e: 527 | if str(e).find('Connection reset by peer') or str(e).find('Operation timed out') != -1: 528 | downjs(contentpath, anncid, url) 529 | else: 530 | logger_error.error( 531 | '公告链接错误 id号 URL网址: %s %s %s' % (e, anncid, url)) 532 | else: 533 | try: 534 | content_txt = content_txt.decode('gbk').encode('utf-8') 535 | except UnicodeDecodeError, e: 536 | logger_error.error( 537 | 'js类型解码错误 id号 URL网址: %s %s %s' % (e, anncid, url)) 538 | else: 539 | content_txt = re.search( 540 | r'"Zw":(.*)
', content_txt) 541 | if content_txt == None: 542 | logger_error.error( 543 | 'js类型解码错误 id号 URL网址: %s %s' % (anncid, url)) 544 | else: 545 | content_txt = content_txt.group().replace('
', '').replace('"Zw":"', '') 546 | f_temp = codecs.open( 547 | contentpath + anncid + '.txt', 'w+', encoding='utf-8') 548 | f_temp.write(content_txt) 549 | f_temp.close() 550 | logger.info('成功下载: id为:%s url:%s ' % 551 | (anncid, url)) 552 | flag = True 553 | finally: 554 | if 'contentpage' in locals().keys(): 555 | contentpage.close() 556 | return flag 557 | 558 | ##下载doc 559 | def downdoc(contentpath, anncid, url): 560 | flag = False 561 | try: 562 | contentpage = urllib2.urlopen(url) 563 | content_doc = contentpage.read() 564 | except urllib2.URLError, e: 565 | logger_error.error( 566 | '公告链接错误 id号 URL网址: %s %s %s' % (e, anncid, url)) 567 | except urllib2.URLError, e: 568 | logger_error.error( 569 | '公告链接错误 id号 URL网址: %s %s %s' % (e, anncid, url)) 570 | except httplib.BadStatusLine, e: 571 | logger_error.error( 572 | '公告链接错误 id号 URL网址: %s %s %s' % (e, anncid, url)) 573 | except socket.timeout: 574 | downdoc(contentpath, anncid, url) 575 | except socket.error, e: 576 | if str(e).find('Connection reset by peer') or str(e).find('Operation timed out') != -1: 577 | downdoc(contentpath, anncid, url) 578 | else: 579 | logger_error.error( 580 | '公告链接错误 id号 URL网址: %s %s %s' % (e, anncid, url)) 581 | else: 582 | if url.find('.docx') > -1 or url.find('.DOCX') > -1: 583 | f_temp = open( 584 | contentpath + anncid + '.docx', 'w+') 585 | else: 586 | f_temp = open( 587 | contentpath + anncid + '.doc', 'w+') 588 | f_temp.write(content_doc) 589 | f_temp.close() 590 | logger.info('成功下载: id为:%s url:%s ' % (anncid, url)) 591 | flag =True 592 | finally: 593 | if 'contentpage' in locals().keys(): 594 | contentpage.close() 595 | return flag 596 | 597 | ##下载pdf 598 | def downpdf(contentpath, anncid, url): 599 | flag = False 600 | try: 601 | contentpage = urllib2.urlopen(url) 602 | content_pdf = contentpage.read() 603 | 604 | except httplib.BadStatusLine, e: 605 | logger_error.error( 606 | '公告链接错误 id号 URL网址: %s %s %s' % (e, anncid, url)) 607 | 608 | except socket.timeout: 609 | downpdf(contentpath, anncid, url) 610 | except socket.error, e: 611 | if str(e).find('Connection reset by peer') or str(e).find('Operation timed out') != -1: 612 | downpdf(contentpath, anncid, url) 613 | else: 614 | logger_error.error( 615 | '公告链接错误 id号 URL网址: %s %s %s' % (e, anncid, url)) 616 | else: 617 | f_temp = open( 618 | contentpath + anncid + '.pdf', 'w+') 619 | f_temp.write(content_pdf) 620 | f_temp.close() 621 | logger.info('成功下载: id为:%s url:%s ' % (anncid, url)) 622 | flag = True 623 | finally: 624 | if 'contentpage' in locals().keys(): 625 | contentpage.close() 626 | return flag 627 | 628 | if __name__ == "__main__": 629 | if len(sys.argv) == 4: # 按照参数执行,由于python程序本身(***.py)就是argv[0],所以下标需要从1开始 630 | main(annc_type=sys.argv[1], start_date=sys.argv[ 631 | 2], end_date=sys.argv[3]) 632 | elif len(sys.argv) == 3: 633 | main(annc_type=sys.argv[1], start_date=sys.argv[ 634 | 2], end_date=sys.argv[2]) 635 | elif len(sys.argv) == 2: 636 | main(annc_type=sys.argv[1]) 637 | else: 638 | print '参数输入不正确' -------------------------------------------------------------------------------- /python_scraw/config.cfg: -------------------------------------------------------------------------------- 1 | [file] 2 | filepath = /data/file/ 3 | logpath = /data/logs/ 4 | 5 | [database] 6 | host_address = 127.0.0.1 7 | user = root 8 | password = 123456 9 | port = 3306 10 | --------------------------------------------------------------------------------