├── .gitignore
├── README.md
├── bin
├── downloader.py
├── extractor.py
├── getNewIp.py
├── processor.py
└── scheduler.py
├── crontab
├── docs
├── api.md
├── dev.md
├── guide.md
├── images
│ ├── 1.jpg
│ ├── 2.png
│ ├── 3.png
│ ├── 4.jpg
│ └── 5.png
└── install.md
├── manage.py
├── nginx.conf
├── requirements.txt
├── supervisord.conf
├── uwsgi.ini
├── wechat
├── __init__.py
├── admin.py
├── api_urls.py
├── constants.py
├── downloaders.py
├── extractors.py
├── forms.py
├── management
│ ├── __init__.py
│ └── commands
│ │ ├── __init__.py
│ │ ├── checkproxies.py
│ │ └── getproxies.py
├── migrations
│ ├── 0001_initial.py
│ └── __init__.py
├── models.py
├── processors.py
├── proxies.py
├── templates
│ └── wechat
│ │ ├── edit.html
│ │ ├── index.html
│ │ ├── keywords_list.html
│ │ ├── search_content.html
│ │ ├── topic_available_list.html
│ │ ├── topic_detail.html
│ │ ├── topic_list.html
│ │ └── wechat_topics.html
├── templatetags
│ ├── __init__.py
│ └── wechat_util.py
├── tests.py
├── urls.py
├── util.py
└── views.py
└── wechatspider
├── __init__.py
├── settings.py
├── static
├── bootstrap-datepicker
│ ├── css
│ │ ├── bootstrap-datepicker.css
│ │ ├── bootstrap-datepicker.css.map
│ │ ├── bootstrap-datepicker.min.css
│ │ ├── bootstrap-datepicker.min.css.map
│ │ ├── bootstrap-datepicker.standalone.css
│ │ ├── bootstrap-datepicker.standalone.css.map
│ │ ├── bootstrap-datepicker.standalone.min.css
│ │ ├── bootstrap-datepicker.standalone.min.css.map
│ │ ├── bootstrap-datepicker3.css
│ │ ├── bootstrap-datepicker3.css.map
│ │ ├── bootstrap-datepicker3.min.css
│ │ ├── bootstrap-datepicker3.min.css.map
│ │ ├── bootstrap-datepicker3.standalone.css
│ │ ├── bootstrap-datepicker3.standalone.css.map
│ │ ├── bootstrap-datepicker3.standalone.min.css
│ │ └── bootstrap-datepicker3.standalone.min.css.map
│ ├── js
│ │ ├── bootstrap-datepicker.js
│ │ └── bootstrap-datepicker.min.js
│ └── locales
│ │ ├── bootstrap-datepicker.ar.min.js
│ │ ├── bootstrap-datepicker.az.min.js
│ │ ├── bootstrap-datepicker.bg.min.js
│ │ ├── bootstrap-datepicker.bs.min.js
│ │ ├── bootstrap-datepicker.ca.min.js
│ │ ├── bootstrap-datepicker.cs.min.js
│ │ ├── bootstrap-datepicker.cy.min.js
│ │ ├── bootstrap-datepicker.da.min.js
│ │ ├── bootstrap-datepicker.de.min.js
│ │ ├── bootstrap-datepicker.el.min.js
│ │ ├── bootstrap-datepicker.en-AU.min.js
│ │ ├── bootstrap-datepicker.en-GB.min.js
│ │ ├── bootstrap-datepicker.eo.min.js
│ │ ├── bootstrap-datepicker.es.min.js
│ │ ├── bootstrap-datepicker.et.min.js
│ │ ├── bootstrap-datepicker.eu.min.js
│ │ ├── bootstrap-datepicker.fa.min.js
│ │ ├── bootstrap-datepicker.fi.min.js
│ │ ├── bootstrap-datepicker.fo.min.js
│ │ ├── bootstrap-datepicker.fr-CH.min.js
│ │ ├── bootstrap-datepicker.fr.min.js
│ │ ├── bootstrap-datepicker.gl.min.js
│ │ ├── bootstrap-datepicker.he.min.js
│ │ ├── bootstrap-datepicker.hr.min.js
│ │ ├── bootstrap-datepicker.hu.min.js
│ │ ├── bootstrap-datepicker.hy.min.js
│ │ ├── bootstrap-datepicker.id.min.js
│ │ ├── bootstrap-datepicker.is.min.js
│ │ ├── bootstrap-datepicker.it-CH.min.js
│ │ ├── bootstrap-datepicker.it.min.js
│ │ ├── bootstrap-datepicker.ja.min.js
│ │ ├── bootstrap-datepicker.ka.min.js
│ │ ├── bootstrap-datepicker.kh.min.js
│ │ ├── bootstrap-datepicker.kk.min.js
│ │ ├── bootstrap-datepicker.ko.min.js
│ │ ├── bootstrap-datepicker.kr.min.js
│ │ ├── bootstrap-datepicker.lt.min.js
│ │ ├── bootstrap-datepicker.lv.min.js
│ │ ├── bootstrap-datepicker.me.min.js
│ │ ├── bootstrap-datepicker.mk.min.js
│ │ ├── bootstrap-datepicker.mn.min.js
│ │ ├── bootstrap-datepicker.ms.min.js
│ │ ├── bootstrap-datepicker.nb.min.js
│ │ ├── bootstrap-datepicker.nl-BE.min.js
│ │ ├── bootstrap-datepicker.nl.min.js
│ │ ├── bootstrap-datepicker.no.min.js
│ │ ├── bootstrap-datepicker.pl.min.js
│ │ ├── bootstrap-datepicker.pt-BR.min.js
│ │ ├── bootstrap-datepicker.pt.min.js
│ │ ├── bootstrap-datepicker.ro.min.js
│ │ ├── bootstrap-datepicker.rs-latin.min.js
│ │ ├── bootstrap-datepicker.rs.min.js
│ │ ├── bootstrap-datepicker.ru.min.js
│ │ ├── bootstrap-datepicker.sk.min.js
│ │ ├── bootstrap-datepicker.sl.min.js
│ │ ├── bootstrap-datepicker.sq.min.js
│ │ ├── bootstrap-datepicker.sr-latin.min.js
│ │ ├── bootstrap-datepicker.sr.min.js
│ │ ├── bootstrap-datepicker.sv.min.js
│ │ ├── bootstrap-datepicker.sw.min.js
│ │ ├── bootstrap-datepicker.th.min.js
│ │ ├── bootstrap-datepicker.tr.min.js
│ │ ├── bootstrap-datepicker.uk.min.js
│ │ ├── bootstrap-datepicker.vi.min.js
│ │ ├── bootstrap-datepicker.zh-CN.min.js
│ │ └── bootstrap-datepicker.zh-TW.min.js
├── bootstrap
│ ├── css
│ │ ├── bootstrap-theme.css
│ │ ├── bootstrap-theme.css.map
│ │ ├── bootstrap-theme.min.css
│ │ ├── bootstrap.css
│ │ ├── bootstrap.css.map
│ │ └── bootstrap.min.css
│ ├── fonts
│ │ ├── glyphicons-halflings-regular.eot
│ │ ├── glyphicons-halflings-regular.svg
│ │ ├── glyphicons-halflings-regular.ttf
│ │ ├── glyphicons-halflings-regular.woff
│ │ └── glyphicons-halflings-regular.woff2
│ └── js
│ │ ├── bootstrap.js
│ │ ├── bootstrap.min.js
│ │ └── npm.js
├── favicon.ico
├── font-awesome
│ ├── css
│ │ ├── font-awesome.css
│ │ └── font-awesome.min.css
│ └── fonts
│ │ ├── FontAwesome.otf
│ │ ├── fontawesome-webfont.eot
│ │ ├── fontawesome-webfont.svg
│ │ ├── fontawesome-webfont.ttf
│ │ ├── fontawesome-webfont.woff
│ │ └── fontawesome-webfont.woff2
├── jquery.form.js
├── jquery
│ └── jquery-1.11.3.min.js
└── web
│ ├── css
│ └── base.css
│ ├── images
│ ├── bg.jpg
│ ├── gongsi.jpg
│ ├── jobole.jpg
│ ├── jobs.jpg
│ ├── touxiang.jpg
│ ├── upload-avatar-default.jpg
│ └── wiki.jpg
│ └── js
│ ├── jquery-bootstrap-validator.js
│ └── qiniu-custom.js
├── templates
├── 404.html
├── base.html
├── footer.html
├── index.html
├── nav.html
└── paginator.html
├── templatetags
├── __init__.py
├── paginator.py
└── utils.py
├── urls.py
├── util.py
└── wsgi.py
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | *.pyc
3 | logs
4 | local_settings.py
5 | .DS_Store
6 | /static/
7 | t.py
8 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 注意:搜狗微信在2019.10.29下线相关功能过后,该项目废弃 !!!
2 |
3 | # 微信爬虫
4 | 一个爬取微信公众号文章的爬虫。
5 |
6 | # 微信爬虫的由来
7 | 零分贝是一家帮助中国5000万贫困人口与社会公益组织对接的公司。
8 |
9 | 我们通过国家和地方政府的“建档立卡”系统,获取到了一手的贫困户数据,目前有100万左右,总数为5000万,目前每个月都在增长。
10 |
11 | 为了帮助这部分贫困户对接公益机构,我写了这个微信爬虫,从微信公众号发布的文章中上找出最新的公益项目。
12 |
13 | 这种找项目的方式的可行性,我们还在试验中。
14 |
15 | 起初,为了快速上线,本爬虫的代码是基于我的另一个 [通用爬虫项目](https://github.com/yijingping/unicrawler) 开发的,我也希望任何对本项目感兴趣的人联系我,与我一同改进这个项目。
16 |
17 | 联系方式:在本项目中新建一个issue留言。
18 |
19 | # 界面预览
20 |
21 | 1) 要爬取的微信公众号列表
22 |
23 | 
24 |
25 | 2) 要爬取的文章关键字列表
26 |
27 | 
28 |
29 | 3) 已经爬取的微信文章
30 |
31 | 
32 |
33 | 4) 查看文章,并标记是否可用
34 |
35 | 
36 |
37 | 5) 控制爬取进程数
38 |
39 | 
40 |
41 |
42 | # 安装
43 |
44 | 1)python环境, 检查python的版本,是否为2.7.x,如果不是,安装2.7.6。
45 |
46 | 如果是centos 6.x,升级python2.6到python2.7,参考教程 http://ruiaylin.github.io/2014/12/12/python%20update/
47 |
48 | 如果是centos 7.x,默认就是python2.7,不用升级
49 |
50 | 如果是mac osx,可以使用virtualenv,安装python2.7
51 |
52 | 2)安装依赖包, clone代码
53 | 安装Mysql-python依赖
54 | ```
55 | yum install python-devel mysql-devel gcc
56 | ```
57 |
58 | 安装lxml依赖
59 | ```
60 | yum install libxslt-devel libxml2-devel
61 | ```
62 |
63 | 安装浏览器环境 selenium依赖.(如果是mac环境,仅需安装firefox, 但确保版本是 firefox 36.0,使用最新的版本会报错)
64 | ```
65 | yum install xorg-x11-server-Xvfb
66 | yum upgrade glib2 # 确保glib2版本大于2.42.2,否则firefox启动会报错
67 | yum install firefox # centos下安装最新的firefox版本
68 | ```
69 |
70 | clone代码,安装依赖python库
71 | ```
72 | $ git clone https://github.com/bowenpay/wechat-spider.git
73 | $ cd wechat-spider
74 | $ pip install -r requirements.txt
75 | ```
76 |
77 | 3) 创建mysql数据库
78 |
79 | 创建数据库wechatspider,默认采用utf8编码。(如果系统支持,可以采用utf8mb4,以兼容emoji字符)
80 |
81 | ```
82 | mysql> CREATE DATABASE `wechatspider` CHARACTER SET utf8;
83 | ```
84 |
85 | 4) 安装和运行Redis
86 |
87 | ```shell
88 | $ wget http://download.redis.io/releases/redis-2.8.3.tar.gz
89 | $ tar xzvf redis-2.8.3.tar.gz
90 | $ cd redis-2.8.3
91 | $ make
92 | $ make install
93 | $ redis-server
94 | ```
95 |
96 | 5) 更新配置文件local_settings
97 |
98 | 在 wechatspider 目录下,添加 `local_settings.py` 文件,配置如下:
99 | ```
100 | # -*- coding: utf-8 -*-
101 |
102 | SECRET_KEY="xxxxxx"
103 |
104 | CRAWLER_DEBUG = True
105 |
106 | # aliyun oss2, 可以将图片和视频存储到阿里云,也可以选择不存储,爬取速度会更快。 默认不存储。
107 | #OSS2_ENABLE = True
108 | #OSS2_CONFIG = {
109 | # "ACCESS_KEY_ID": "XXXXXXXXXXXXXX",
110 | # "ACCESS_KEY_SECRET": "YYYYYYYYYYYYYYYYYYYYYY",
111 | # "ENDPOINT": "",
112 | # "BUCKET_DOMAIN": "oss-cn-hangzhou.aliyuncs.com",
113 | # "BUCKET_NAME": "XXXXX",
114 | # "IMAGES_PATH": "images/",
115 | # "VIDEOS_PATH": "videos/",
116 | # "CDN_DOMAIN": "XXXXXX.oss-cn-hangzhou.aliyuncs.com"
117 | #}
118 | # mysql 数据库配置
119 | DATABASES = {
120 | 'default': {
121 | 'ENGINE': 'django.db.backends.mysql',
122 | 'HOST': '127.0.0.1',
123 | 'NAME': 'wechatspider',
124 | 'USER': 'root',
125 | 'PASSWORD': '',
126 | 'OPTIONS':{
127 | 'charset': 'utf8mb4',
128 | },
129 | }
130 | }
131 | # redis配置,用于消息队列和k-v存储
132 | REDIS_OPTIONS = {
133 | 'host': 'localhost',
134 | 'port': 6379,
135 | 'password': '',
136 | 'db': 4
137 | }
138 |
139 | ```
140 |
141 | 6) 初始化表
142 | ```
143 | $ python manage.py migrate
144 | ```
145 |
146 | 7)启动网站
147 |
148 | ```
149 | python manage.py runserver 0.0.0.0:8001
150 | ```
151 | 访问 http://localhost:8001/。
152 |
153 |
154 | 6) 创建超级管理员账号,访问后台,并配置要爬取的公众号和关键字
155 | ```
156 | python manage.py createsuperuser
157 | ```
158 |
159 |
160 | 8)启动爬虫
161 |
162 | ```shell
163 | $ python bin/scheduler.py
164 | $ python bin/downloader.py
165 | $ python bin/extractor.py
166 | $ python bin/processor.py
167 | ```
168 |
169 | 以上步骤执行成功,并能爬取文章后。可以参考以下部分配置生产环境。
170 |
171 | # 部署nginx
172 | 前期先用nginx将域名www.mydomain.com转发到8001端口。
173 |
174 | # 部署supervisor脚本
175 | 参考文件 `supervisord.conf`
176 |
177 | # 部署crontab脚本
178 | 参考文件 `crontab`
179 |
180 | # 系统使用文档
181 |
182 |
183 | # API接口文档
184 |
185 |
--------------------------------------------------------------------------------
/bin/downloader.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # 加载django环境
3 | import sys
4 | import os
5 | reload(sys)
6 | sys.setdefaultencoding('utf8')
7 | sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))
8 | os.environ['DJANGO_SETTINGS_MODULE'] = 'wechatspider.settings'
9 | import django
10 | django.setup()
11 |
12 | import time
13 | import json
14 | from random import randint
15 | from django.conf import settings
16 | from wechatspider.util import get_redis
17 | from wechat.proxies import MysqlProxyBackend
18 | from wechat.downloaders import SeleniumDownloaderBackend
19 | from wechat.constants import KIND_HISTORY, KIND_DETAIL, KIND_KEYWORD
20 | import logging
21 | logger = logging.getLogger()
22 |
23 | CRAWLER_CONFIG = settings.CRAWLER_CONFIG
24 | CRAWLER_GLOBAL_LIMIT_SPEED = settings.CRAWLER_GLOBAL_LIMIT_SPEED
25 |
26 |
27 | class Downloader(object):
28 | def __init__(self):
29 | self.redis = get_redis()
30 |
31 | def get_proxy(self):
32 | return MysqlProxyBackend()
33 |
34 | def check_limit_speed(self):
35 | proxy = self.get_proxy()
36 | key = '%s:%s' % (CRAWLER_CONFIG['global_limit_speed'], proxy)
37 | if self.redis.exists(key):
38 | return True, proxy
39 | else:
40 | self.redis.psetex(key, CRAWLER_GLOBAL_LIMIT_SPEED, CRAWLER_GLOBAL_LIMIT_SPEED)
41 | return False, proxy
42 |
43 | def run(self):
44 | r = self.redis
45 | if settings.CRAWLER_DEBUG:
46 | r.delete(CRAWLER_CONFIG["downloader"])
47 | while True:
48 | try:
49 | resp_data = r.brpop(settings.CRAWLER_CONFIG["downloader"])
50 | except Exception as e:
51 | print e
52 | continue
53 |
54 | try:
55 | data = json.loads(resp_data[1])
56 |
57 | logger.debug(data)
58 | is_limited, proxy = self.check_limit_speed()
59 | if is_limited:
60 | print '# 被限制, 放回去, 下次下载'
61 | time.sleep(1) # 休息一秒, 延迟放回去的时间
62 | r.lpush(CRAWLER_CONFIG["downloader"], resp_data[1])
63 | else:
64 | print '# 未被限制,可以下载'
65 | # 处理文章的函数,用于回调. 每下载一篇, 处理一篇
66 | def process_topic(topic):
67 | if topic.get('kind', None) == KIND_DETAIL:
68 | item_data = topic
69 | elif topic.get('kind', None) == KIND_KEYWORD:
70 | item_data = topic
71 | else:
72 | item_data = topic
73 | item_data["wechat_id"] = data["wechat_id"]
74 | r.lpush(CRAWLER_CONFIG["extractor"], json.dumps(item_data))
75 | logger.debug(item_data)
76 |
77 | with SeleniumDownloaderBackend(proxy=proxy) as browser:
78 | if data.get('kind') == KIND_DETAIL:
79 | res = browser.download_wechat_topic_detail(data, process_topic)
80 | elif data.get('kind') == KIND_HISTORY:
81 | #res = browser.download_wechat_history(data, process_topic)
82 | pass
83 | elif data.get('kind') == KIND_KEYWORD:
84 | res = browser.download_wechat_keyword(data, process_topic)
85 | else:
86 | res = browser.download_wechat(data, process_topic)
87 |
88 | time.sleep(randint(1, 5))
89 | except Exception as e:
90 | print e
91 | raise
92 |
93 |
94 | if __name__ == '__main__':
95 | downloader = Downloader()
96 | downloader.run()
97 |
--------------------------------------------------------------------------------
/bin/extractor.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | __author__ = 'yijingping'
3 | # 加载django环境
4 | import sys
5 | import os
6 | reload(sys)
7 | sys.setdefaultencoding('utf8')
8 | sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))
9 | os.environ['DJANGO_SETTINGS_MODULE'] = 'wechatspider.settings'
10 | import django
11 | django.setup()
12 |
13 | import json
14 | from django.conf import settings
15 | from wechatspider.util import get_redis, get_uniqueid
16 | from wechat.extractors import XPathExtractor, PythonExtractor, ImageExtractor, VideoExtractor, WechatContentExtractor
17 | from wechat.constants import KIND_HISTORY, KIND_DETAIL, KIND_KEYWORD
18 | import logging
19 | logger = logging.getLogger()
20 |
21 | NORMAL_RULES = [
22 | {
23 | "key":"avatar",
24 | "rules":[
25 | {
26 | "kind":"python",
27 | "data":"out_val=data['avatar'];"
28 | },
29 | {
30 | "kind":"image",
31 | "data":""
32 | }
33 | ]
34 | },
35 | {
36 | "key":"origin_title",
37 | "rules":[
38 | {
39 | "kind":"xpath",
40 | "data":"//title/text()"
41 | },
42 | {
43 | "kind":"python",
44 | "data":"out_val=in_val[0] if in_val else '';"
45 | }
46 | ]
47 | },
48 | {
49 | "key":"source",
50 | "rules":[
51 | {
52 | "kind":"image",
53 | "data":""
54 | },
55 | {
56 | "kind":"WechatContent",
57 | "data":""
58 | }
59 | ]
60 | },
61 | {
62 | "key":"content",
63 | "rules":[
64 | {
65 | "kind":"xpath",
66 | "data":"//div[@id='js_content']"
67 | },
68 | {
69 | "kind":"python",
70 | "data":"from lxml import html;out_val=''.join([html.tostring(child, encoding='unicode') for child in in_val])"
71 | },
72 | {
73 | "kind":"image",
74 | "data":""
75 | },
76 | {
77 | "kind":"WechatContent",
78 | "data":""
79 | }
80 | ]
81 | },
82 | {
83 | "key":"words",
84 | "rules":[
85 | {
86 | "kind":"xpath",
87 | "data":"//div[@id='js_content']//text()"
88 | },
89 | {
90 | "kind":"python",
91 | "data":"out_val=sum([len(item.strip()) for item in in_val])"
92 | }
93 | ]
94 | },
95 | {
96 | "key":"publish_time",
97 | "rules":[
98 | {
99 | "kind":"python",
100 | "data":"from datetime import datetime;out_val = str(datetime.now());"
101 | }
102 | ]
103 | },
104 | {
105 | "key": "read_num",
106 | "rules": [
107 | {
108 | "kind": "xpath",
109 | "data": "//span[@id='sg_readNum3']/text()"
110 | },
111 | {
112 | "kind": "python",
113 | "data": "out_val=sum([int(item.strip().strip('+')) for item in in_val])"
114 | }
115 | ]
116 | },
117 | {
118 | "key": "like_num",
119 | "rules": [
120 | {
121 | "kind":"xpath",
122 | "data":"//span[@id='sg_likeNum3']/text()"
123 | },
124 | {
125 | "kind":"python",
126 | "data":"out_val=sum([int(item.strip().strip('+')) for item in in_val])"
127 | }
128 | ]
129 | }
130 | ]
131 |
132 | DETAIL_RULES = [
133 | {
134 | "key":"title",
135 | "rules":[
136 | {
137 | "kind":"xpath",
138 | "data":"//title/text()"
139 | },
140 | {
141 | "kind":"python",
142 | "data":"out_val=in_val[0] if in_val else '';"
143 | }
144 | ]
145 | },
146 | {
147 | "key":"origin_title",
148 | "rules":[
149 | {
150 | "kind":"xpath",
151 | "data":"//title/text()"
152 | },
153 | {
154 | "kind":"python",
155 | "data":"out_val=in_val[0] if in_val else '';"
156 | }
157 | ]
158 | },
159 | {
160 | "key":"source",
161 | "rules":[
162 | {
163 | "kind":"image",
164 | "data":""
165 | },
166 | {
167 | "kind":"WechatContent",
168 | "data":""
169 | }
170 | ]
171 | },
172 | {
173 | "key":"content",
174 | "rules":[
175 | {
176 | "kind":"xpath",
177 | "data":"//div[@id='js_content']"
178 | },
179 | {
180 | "kind":"python",
181 | "data":"from lxml import html;out_val=''.join([html.tostring(child, encoding='unicode') for child in in_val])"
182 | },
183 | {
184 | "kind":"image",
185 | "data":""
186 | },
187 | {
188 | "kind":"WechatContent",
189 | "data":""
190 | }
191 | ]
192 | },
193 | {
194 | "key":"words",
195 | "rules":[
196 | {
197 | "kind":"xpath",
198 | "data":"//div[@id='js_content']//text()"
199 | },
200 | {
201 | "kind":"python",
202 | "data":"out_val=sum([len(item.strip()) for item in in_val])"
203 | }
204 | ]
205 | },
206 | {
207 | "key":"abstract",
208 | "rules":[
209 | {
210 | "kind":"xpath",
211 | "data":"//div[@id='js_content']//text()"
212 | },
213 | {
214 | "kind":"python",
215 | "data":"tmp=''.join([item.strip() for item in in_val]);out_val = '%s...' % tmp[:220] if len(tmp) > 220 else tmp;"
216 | }
217 | ]
218 | },
219 | {
220 | "key":"avatar",
221 | "rules":[
222 | {
223 | "kind":"python",
224 | "data":"out_val=data['content'];"
225 | },
226 | {
227 | "kind":"xpath",
228 | "data":"//img/@src"
229 | },
230 | {
231 | "kind":"python",
232 | "data":"out_val=in_val[1] if len(in_val) > 1 else '';"
233 | }
234 | ]
235 | },
236 | {
237 | "key":"publish_time",
238 | "rules":[
239 | {
240 | "kind":"python",
241 | "data":"from datetime import datetime;out_val = str(datetime.now());"
242 | }
243 | ]
244 | },
245 | {
246 | "key":"wechatid",
247 | "rules":[
248 | {
249 | "kind":"xpath",
250 | "data":"//span[@class='profile_meta_value']/text()"
251 | },
252 | {
253 | "kind":"python",
254 | "data":"out_val=in_val[0] if len(in_val) == 2 else '';"
255 | }
256 | ]
257 | },
258 | {
259 | "key":"name",
260 | "rules":[
261 | {
262 | "kind":"xpath",
263 | "data":"//strong[@class='profile_nickname']/text()"
264 | },
265 | {
266 | "kind":"python",
267 | "data":"out_val=in_val[0] if in_val else '';"
268 | }
269 | ]
270 | },
271 | {
272 | "key":"intro",
273 | "rules":[
274 | {
275 | "kind":"xpath",
276 | "data":"//span[@class='profile_meta_value']/text()"
277 | },
278 | {
279 | "kind":"python",
280 | "data":"out_val=in_val[1] if len(in_val) == 2 else '';"
281 | }
282 | ]
283 | },
284 |
285 | {
286 | "key":"qrcode",
287 | "rules":[
288 | {
289 | "kind":"xpath",
290 | "data":"//img[@id='js_pc_qr_code_img']/@src"
291 | },
292 | {
293 | "kind":"python",
294 | "data":"out_val='http://mp.weixin.qq.com' + in_val[0] if in_val else '';"
295 | }
296 | ]
297 | },
298 | {
299 | "key": "read_num",
300 | "rules": [
301 | {
302 | "kind": "xpath",
303 | "data": "//span[@id='sg_readNum3']/text()"
304 | },
305 | {
306 | "kind": "python",
307 | "data": "out_val=sum([int(item.strip().strip('+')) for item in in_val])"
308 | }
309 | ]
310 | },
311 | {
312 | "key": "like_num",
313 | "rules": [
314 | {
315 | "kind":"xpath",
316 | "data":"//span[@id='sg_likeNum3']/text()"
317 | },
318 | {
319 | "kind":"python",
320 | "data":"out_val=sum([int(item.strip().strip('+')) for item in in_val])"
321 | }
322 | ]
323 | }
324 |
325 | ]
326 | class Extractor(object):
327 | def __init__(self):
328 | self.redis = get_redis()
329 |
330 | def extract(self, content, rules, context):
331 | res = content
332 | for rule in rules:
333 | extractor = None
334 | if rule["kind"] == "xpath":
335 | extractor = XPathExtractor(res, rule["data"])
336 | elif rule["kind"] == "python":
337 | extractor = PythonExtractor(rule["data"], res, context=context)
338 | elif rule["kind"] == "image":
339 | extractor = ImageExtractor(res)
340 | elif rule["kind"] == "video":
341 | extractor = VideoExtractor(res)
342 | elif rule["kind"] == "WechatContent":
343 | extractor = WechatContentExtractor(res)
344 |
345 | res = extractor.extract()
346 |
347 | return res
348 |
349 | def get_detail(self, content, data):
350 | if data.get('kind') == KIND_DETAIL:
351 | result = {
352 | "kind": data["kind"],
353 | "url": data["url"],
354 | "source": data["body"],
355 | "avatar": ''
356 | }
357 | rules = DETAIL_RULES
358 | elif data.get('kind') == KIND_KEYWORD:
359 | result = {
360 | "kind": data["kind"],
361 | "url": data["url"],
362 | "source": data["body"],
363 | "avatar": ''
364 | }
365 | rules = DETAIL_RULES
366 | else:
367 | result = {
368 | "wechat_id": data["wechat_id"],
369 | "url": data["url"],
370 | "title": data["title"],
371 | "source": data["body"],
372 | "avatar": data["avatar"],
373 | "abstract": data["abstract"]
374 | }
375 | rules = NORMAL_RULES
376 |
377 | for item in rules:
378 | col = item["key"]
379 | print col
380 | col_rules = item["rules"]
381 | col_value = self.extract(content, col_rules, {'data': result})
382 | result[col] = col_value
383 |
384 | # 解析结束, 保存
385 | self.redis.lpush(settings.CRAWLER_CONFIG["processor"], json.dumps(result))
386 | result["source"] = ""
387 | result["content"] = ""
388 | logger.debug('extracted:%s' % result)
389 |
390 | def run(self):
391 | r = self.redis
392 | if settings.CRAWLER_DEBUG:
393 | r.delete(settings.CRAWLER_CONFIG["extractor"])
394 | while True:
395 | try:
396 | data = r.brpop(settings.CRAWLER_CONFIG["extractor"])
397 | except Exception as e:
398 | print e
399 | continue
400 | #print data
401 | data = json.loads(data[1])
402 | body = data['body']
403 | # 如果没有多项详情,则只是单项
404 | self.get_detail(body, data)
405 |
406 |
407 | if __name__ == '__main__':
408 | my_extractor = Extractor()
409 | my_extractor.run()
410 |
--------------------------------------------------------------------------------
/bin/getNewIp.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | __author__ = 'yijingping'
3 | import urllib
4 | import socket
5 | import time
6 |
7 | def get_ip():
8 | exip = ''
9 | ipList = socket.gethostbyname_ex(socket.gethostname())
10 |
11 | for itemList in ipList:
12 | if isinstance(itemList, list):
13 | for ip in itemList:
14 | print '####:',ip
15 | if ip not in ['192.168.11.58']:
16 | exip = ip
17 | return exip
18 |
19 |
20 | def save_ip(exip):
21 | if exip:
22 | params = urllib.urlencode({'host': exip, 'port': 808})
23 | f = urllib.urlopen("http://wechatspider.0fenbei.com/wechat/proxy/1/edit/", params)
24 | print f.read()
25 |
26 | if __name__ == '__main__':
27 | while True:
28 | try:
29 | exip = get_ip()
30 | print 'new ip:', exip
31 | save_ip(exip)
32 | except Exception as e:
33 | print e
34 | finally:
35 | print 'sleep 1 second'
36 | time.sleep(1)
37 |
38 |
--------------------------------------------------------------------------------
/bin/processor.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import unicode_literals
3 | __author__ = 'yijingping'
4 | # 加载django环境
5 | import sys
6 | import os
7 | reload(sys)
8 | sys.setdefaultencoding('utf8')
9 | sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))
10 | os.environ['DJANGO_SETTINGS_MODULE'] = 'wechatspider.settings'
11 | import django
12 | django.setup()
13 |
14 | import _mysql
15 | from datetime import datetime
16 | import json
17 | from django.utils.encoding import smart_str, smart_unicode
18 | from django.conf import settings
19 | from wechat.models import Topic
20 | from wechat.processors import DjangoModelBackend
21 | from wechatspider.util import get_redis, get_uniqueid
22 | import logging
23 | logger = logging.getLogger()
24 |
25 |
26 | class Processor():
27 | def __init__(self):
28 | self.pools = {}
29 |
30 | def get_backends(self):
31 | backend = DjangoModelBackend(Topic)
32 | return [backend]
33 |
34 | def process(self, data):
35 | backends = self.get_backends()
36 | for backend in backends:
37 | backend.process(data)
38 |
39 | def run(self):
40 | r = get_redis()
41 | if settings.CRAWLER_DEBUG:
42 | r.delete(settings.CRAWLER_CONFIG["processor"])
43 | while True:
44 | try:
45 | rsp = r.brpop(settings.CRAWLER_CONFIG["processor"])
46 | except Exception as e:
47 | print e
48 | continue
49 |
50 | data = json.loads(rsp[1])
51 | logger.info(json.dumps(data, encoding="UTF-8", ensure_ascii=False))
52 | self.process(data)
53 |
54 |
55 | if __name__ == '__main__':
56 | processor = Processor()
57 | processor.run()
58 |
--------------------------------------------------------------------------------
/bin/scheduler.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | __author__ = 'yijingping'
3 | # 加载django环境
4 | import sys
5 | import os
6 | reload(sys)
7 | sys.setdefaultencoding("utf-8")
8 | sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))
9 | os.environ['DJANGO_SETTINGS_MODULE'] = 'wechatspider.settings'
10 | import django
11 | django.setup()
12 |
13 | import json
14 | from wechat.models import Wechat, Word
15 | from django.conf import settings
16 | import logging
17 | logger = logging.getLogger()
18 | from datetime import datetime, timedelta
19 | import time
20 | from wechatspider.util import get_redis
21 | from wechat.constants import KIND_NORMAL, KIND_KEYWORD
22 |
23 |
24 | class Scheduler(object):
25 | def run(self):
26 | r = get_redis()
27 | if settings.CRAWLER_DEBUG:
28 | r.delete(settings.CRAWLER_CONFIG["downloader"])
29 |
30 | while True:
31 | now = datetime.now()
32 | # 获取要抓取的公众号
33 | wechats = Wechat.objects.filter(frequency__gt=0, next_crawl_time__lt=now, status=Wechat.STATUS_DEFAULT).order_by('-id')
34 | for item in wechats:
35 | data = {
36 | 'kind': KIND_NORMAL,
37 | 'wechat_id': item.id,
38 | 'wechatid': item.wechatid
39 | }
40 |
41 | r.lpush(settings.CRAWLER_CONFIG["downloader"], json.dumps(data))
42 |
43 | # 更新index_rule
44 | item.next_crawl_time = now + timedelta(minutes=item.frequency)
45 | #item.next_crawl_time = now + timedelta(seconds=item.frequency)
46 | item.save()
47 |
48 | logging.debug(data)
49 |
50 | # 获取要抓取的关键词
51 | keywords = Word.objects.filter(frequency__gt=0, next_crawl_time__lt=now).order_by('-id')
52 | for item in keywords:
53 | data = {
54 | 'kind': KIND_KEYWORD,
55 | 'word': item.text
56 | }
57 |
58 | r.lpush(settings.CRAWLER_CONFIG["downloader"], json.dumps(data))
59 |
60 | # 更新index_rule
61 | item.next_crawl_time = now + timedelta(minutes=item.frequency)
62 | #item.next_crawl_time = now + timedelta(seconds=item.frequency)
63 | item.save()
64 |
65 | logging.debug(data)
66 |
67 | time.sleep(1)
68 |
69 | if __name__ == '__main__':
70 | scheduler = Scheduler()
71 | scheduler.run()
72 |
--------------------------------------------------------------------------------
/crontab:
--------------------------------------------------------------------------------
1 | 1 1 * * * ps aux|grep firefox|grep -v grep|xargs kill
2 | 1 1 * * * ps aux|grep Xvfb|grep -v grep|xargs kill
3 | 1 * * * * rm -f /var/log/wechatspider/*.log.*
4 | 40 */3 * * * /usr/bin/supervisorctl -c /etc/supervisord.conf restart wechatspider_downloader:0
5 | 22 */2 * * * /usr/bin/supervisorctl -c /etc/supervisord.conf restart wechatspider_downloader:1
6 | 22 */4 * * * /usr/bin/supervisorctl -c /etc/supervisord.conf restart wechatspider_extractor:0
7 | 22 */4 * * * /usr/bin/supervisorctl -c /etc/supervisord.conf restart wechatspider_extractor:1
8 | 22 */4 * * * /usr/bin/supervisorctl -c /etc/supervisord.conf restart wechatspider_extractor:2
9 | 22 */4 * * * /usr/bin/supervisorctl -c /etc/supervisord.conf restart wechatspider_extractor:3
10 | 22 */4 * * * /usr/bin/supervisorctl -c /etc/supervisord.conf restart wechatspider_processor
11 | 22 */4 * * * /usr/bin/supervisorctl -c /etc/supervisord.conf restart wechatspider_scheduler
12 |
--------------------------------------------------------------------------------
/docs/api.md:
--------------------------------------------------------------------------------
1 | 接口文档
2 | ==========
3 |
4 | # 添加/修改公众号
5 | 功能: 输入需要爬取的公众号id和爬取频率,如果公众号不存在就添加,如果已经存在就更新爬取频率.同事更新公众号信息.包括头像,描述,二维码等.
6 |
7 | URL: http://127.0.0.1:8090/api/wechat/add/
8 |
9 | 方法: POST
10 |
11 | 参数:
12 | ```
13 | wechatid: 微信id
14 | frequency: 爬取频率, 正整数, 单位是分钟
15 | ```
16 | 返回:
17 | ```
18 | // 已存在更新返回
19 | {
20 | "message": "已更新",
21 | "ret": 0
22 | }
23 | // 不存在保存后返回
24 | {
25 | "message": "已添加",
26 | "ret": 0
27 | }
28 | // 没有找到对应的微信id
29 | {
30 | "message": "公众号不存在",
31 | "ret": 1
32 | }
33 | ```
34 |
35 |
36 | # 添加文章
37 |
38 | 功能: 输入需要爬取的文章URL.将文章加入爬取队列优先爬取.同事获取相关公众号信息,并将爬取频率设置为0
39 |
40 | URL: http://127.0.0.1:8090/api/wechat/topic/add/
41 |
42 | 方法: POST
43 |
44 | 参数:
45 | ```
46 | url: 文章连接,如http://mp.weixin.qq.com/s?__biz=MjM5NDg2NjA4MQ==&mid=402566965&idx=1&sn=616fb1ffa9afc5acc3f4f2a210f6dd83&3rd=MzA3MDU4NTYzMw==&scene=6#rd
47 | ```
48 |
49 | 返回:
50 | ```
51 | // 正确返回
52 | {
53 | 'ret': 0,
54 | 'message': '提交成功,链接已经提交给爬虫,稍后查看爬取结果'
55 | }
56 |
57 | // 错误返回
58 | {
59 | 'ret': 1,
60 | 'message': '提交失败,url必须以 http://mp.weixin.qq.com/ 开头'
61 | }
62 | ```
63 |
64 |
65 |
66 |
67 | # 搜索api
68 |
69 | 功能: 输入公众号名称或者id,返回对应的列表.
70 |
71 | URL: http://127.0.0.1:8090/api/wechat/search?query=财经
72 |
73 | 方法: GET
74 |
75 | 返回:
76 |
77 | ```
78 | {
79 | "data": [
80 | {
81 | "qrcode": "http://img03.sogoucdn.com/app/a/100520105/h3VIR0DEFX5qh1EknyCj",
82 | "wechatid": "LLDS365",
83 | "intro": "本号出租/出售.关注后,即可进入【财经论坛】,和大家互动交流! 专注分享最实用的财经消息以及股票内容!欢迎关注!合作QQ800178778",
84 | "name": "財經",
85 | "avatar": "http://img01.sogoucdn.com/app/a/100520090/oIWsFt3HcMp751wj8bt3PNRmRzHg"
86 | },
87 | {
88 | "qrcode": "http://img03.sogoucdn.com/app/a/100520105/vklgb27EEFBvh38Mnxya",
89 | "wechatid": "zdbank",
90 | "intro": "指点财经每日提供全面真实的财经快讯,发布最新银行理财、保险、资管、信托等正规金融机构发布的产品信息并高效对接理财师,成为投资者一站式理财资讯交互平台.",
91 | "name": "指点财经",
92 | "avatar": "http://img01.sogoucdn.com/app/a/100520090/oIWsFt-wxZs0pb4AGlpIKntt-xxo"
93 | },
94 | {
95 | "qrcode": "http://img03.sogoucdn.com/app/a/100520105/MHVmaV-EomHdh04KnyAU",
96 | "wechatid": "cctvyscj",
97 | "intro": "中央电视台",
98 | "name": "央视财经",
99 | "avatar": "http://img01.sogoucdn.com/app/a/100520090/oIWsFt_cUwbglodLkLT749ZABOt4"
100 | },
101 | {
102 | "qrcode": "http://img03.sogoucdn.com/app/a/100520105/dUOmqSDE0R6uhzHKnxZR",
103 | "wechatid": "tttmoney",
104 | "intro": "原创的财经评论,独立的观察视角,深度的市场剖析. 联系方式:QQ:1527356260;邮箱:1527356260@qq.com.",
105 | "name": "博闻财经",
106 | "avatar": "http://img01.sogoucdn.com/app/a/100520090/oIWsFtza9DUiaCPSyfc_MQO4N5PY"
107 | },
108 | {
109 | "qrcode": "http://img03.sogoucdn.com/app/a/100520105/H0jT3OvEsNXPh-q-nx07",
110 | "wechatid": "lianhuacaijing",
111 | "intro": "莲花APP官微,让你的财富在这里绽放.依托证券时报22年资本市场专业背景,抢先知晓上市公司公告解读、热点事件分析、主题机会挖掘;更有上市公司深度研究及最新机构调研动向.",
112 | "name": "莲花财经",
113 | "avatar": "http://img01.sogoucdn.com/app/a/100520090/oIWsFtxNDf-e3-9SNoKmaZ8B9hcw"
114 | },
115 | {
116 | "qrcode": "http://img03.sogoucdn.com/app/a/100520105/5XVNQmXEd1sIh3QhnyDB",
117 | "wechatid": "sohucaijing2013",
118 | "intro": "搜狐财经,不海量,不枯燥,财经可以很简单!这里有最及时资讯、最独家爆料、最麻辣点评,最权威的专家学者声音.",
119 | "name": "搜狐财经",
120 | "avatar": "http://img01.sogoucdn.com/app/a/100520090/oIWsFt89mqsRNr-HSk72nHeLEUls"
121 | },
122 | {
123 | "qrcode": "http://img03.sogoucdn.com/app/a/100520105/D0wGCVjEpGbbh0lqnxkr",
124 | "wechatid": "bxcjtv",
125 | "intro": "百姓财经栏目是四川广播电视台经济频道2007年强力推出的一档财经类节目.从百姓投资理财的需求出发,以中国股市为着眼点,联手全国一流券商、邀请资深专业人士,以超前的眼光、敏锐的视角、权威的分析、把握大势,...",
126 | "name": "百姓财经",
127 | "avatar": "http://img01.sogoucdn.com/app/a/100520090/oIWsFtzfSD2HictGHcf_wip7ImVU"
128 | },
129 | {
130 | "qrcode": "http://img03.sogoucdn.com/app/a/100520105/tkP59tLEEuxth8OVnxaS",
131 | "wechatid": "njue_xcb_weixin",
132 | "intro": "南京财经大学官方公众平台,传播校园文化,传递校园信息,服务广大师生校友.欢迎关注!",
133 | "name": "南京财经大学",
134 | "avatar": "http://img01.sogoucdn.com/app/a/100520090/oIWsFt2H_o--VPZokXgl-56Mhh1g"
135 | },
136 | {
137 | "qrcode": "http://img03.sogoucdn.com/app/a/100520105/UUgYF4fE-rmBh5Z0nx11",
138 | "wechatid": "bh2056",
139 | "intro": "做有趣、有料、有新意的大众金融平台",
140 | "name": "渤海财经",
141 | "avatar": "http://img01.sogoucdn.com/app/a/100520090/oIWsFtyo_x125073RKHO4j27ZEtE"
142 | },
143 | {
144 | "qrcode": "http://img03.sogoucdn.com/app/a/100520105/7HVuYcHEfv8Bh9ACnyDI",
145 | "wechatid": "wzdsbcf",
146 | "intro": "欢迎关注温州财经,本公众号由温州都市报财经部运营,为广大温都爱理财俱乐部成员提供在线搜索、便民服务、财经新闻,以及在线股票问诊、国企类理财产品服务.",
147 | "name": "温州财经",
148 | "avatar": "http://img01.sogoucdn.com/app/a/100520090/oIWsFt0G2xPqCn-pG1sAAY2n8GI4"
149 | }
150 | ],
151 | "ret": 0
152 | }
153 | ```
--------------------------------------------------------------------------------
/docs/dev.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bowenpay/wechat-spider/e585a4913962dfa9a817cd7b139505a0c48aecbc/docs/dev.md
--------------------------------------------------------------------------------
/docs/guide.md:
--------------------------------------------------------------------------------
1 | 使用文档
2 | ==========
3 |
4 | # 微信公众号页面
5 |
6 | 要爬取的微信公众号列表
7 |
8 | 添加公众号
9 |
10 | 修改爬取频率, 间隔0为不爬取
11 |
12 | # 关键词页面
13 |
14 | 关键词列表
15 |
16 | 添加 删除关键词
17 |
18 | # 最新文章
19 |
20 | 最新文章列表
21 |
22 |
23 | 添加单独的文章
24 |
25 | 文章详情页\标记可用
26 |
27 |
28 | # 可用文章列表
29 |
--------------------------------------------------------------------------------
/docs/images/1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bowenpay/wechat-spider/e585a4913962dfa9a817cd7b139505a0c48aecbc/docs/images/1.jpg
--------------------------------------------------------------------------------
/docs/images/2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bowenpay/wechat-spider/e585a4913962dfa9a817cd7b139505a0c48aecbc/docs/images/2.png
--------------------------------------------------------------------------------
/docs/images/3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bowenpay/wechat-spider/e585a4913962dfa9a817cd7b139505a0c48aecbc/docs/images/3.png
--------------------------------------------------------------------------------
/docs/images/4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bowenpay/wechat-spider/e585a4913962dfa9a817cd7b139505a0c48aecbc/docs/images/4.jpg
--------------------------------------------------------------------------------
/docs/images/5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bowenpay/wechat-spider/e585a4913962dfa9a817cd7b139505a0c48aecbc/docs/images/5.png
--------------------------------------------------------------------------------
/docs/install.md:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/manage.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | import os
3 | import sys
4 |
5 | if __name__ == "__main__":
6 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "wechatspider.settings")
7 |
8 | from django.core.management import execute_from_command_line
9 |
10 | execute_from_command_line(sys.argv)
11 |
--------------------------------------------------------------------------------
/nginx.conf:
--------------------------------------------------------------------------------
1 | upstream wechatspider_0fenbei_uwsgi_backend {
2 | server 127.0.0.1:49161;
3 | }
4 |
5 | server {
6 | listen 80;
7 | server_name wechatspider.0fenbei.com;
8 |
9 | location ^~ /.git {
10 | deny all;
11 | }
12 |
13 | location ^~ /static {
14 | root /var/www/0fenbei/wechat-spider;
15 | index index.html;
16 | expires 1M;
17 | access_log off;
18 | add_header Cache-Control "public";
19 | }
20 |
21 | location / {
22 | proxy_next_upstream error timeout http_500 http_503;
23 | proxy_connect_timeout 4000ms;
24 | proxy_read_timeout 30s;
25 | proxy_set_header Host $host;
26 | proxy_set_header X-Real-IP $remote_addr;
27 | proxy_set_header X-Forwarded-For $remote_addr;
28 | proxy_set_header X-Rewrite-URL $request_uri;
29 | client_max_body_size 10m;
30 |
31 | uwsgi_pass wechatspider_0fenbei_uwsgi_backend;
32 | include uwsgi_params;
33 | }
34 |
35 | }
36 |
37 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | Django==1.8.1
2 | MySQL-python==1.2.5
3 | requests==2.9.1
4 | lxml==3.4.4
5 | hiredis==0.2.0
6 | redis==2.10.3
7 | oss2==2.0.5
8 | selenium==2.52.0
9 | PyVirtualDisplay==0.1.5
10 | python-dateutil==2.5.0
11 | beautifulsoup4==4.4.1
12 |
13 |
14 |
--------------------------------------------------------------------------------
/supervisord.conf:
--------------------------------------------------------------------------------
1 | #[program:wechatspider.0fenbei.com]
2 | #command=/usr/bin/python /var/www/0fenbei/wechat-spider/manage.py runserver 0.0.0.0:8090
3 | #umask=022
4 | #user=ripple
5 | #startsecs=0
6 | #stopwaitsecs=0
7 | #autostart=true
8 | #autorestart=true
9 | #stdout_logfile=/var/log/wechatspider/wechatspider.stdout.log
10 | #stderr_logfile=/var/log/wechatspider/wechatspider.stderr.log
11 | #stopsignal=KILL
12 | #killasgroup=true
13 |
14 | [program:uwsgi-wechatspider.0fenbei.com]
15 | command=/usr/bin/uwsgi --ini /var/www/0fenbei/wechat-spider/uwsgi.ini
16 | directory=/var/www/0fenbei/wechat-spider
17 | umask=022
18 | user=ripple
19 | startsecs=0
20 | stopwaitsecs=0
21 | autostart=true
22 | autorestart=true
23 | stdout_logfile=/var/log/bowenpay/wechatspider.stdout.log
24 | stderr_logfile=/var/log/bowenpay/wechatspider.stderr.log
25 | stopsignal=QUIT
26 | killasgroup=true
27 |
28 | [program:wechatspider_scheduler]
29 | command=/usr/bin/python /var/www/0fenbei/wechat-spider/bin/scheduler.py
30 | umask=022
31 | user=ripple
32 | startsecs=0
33 | stopwaitsecs=0
34 | autostart=true
35 | autorestart=true
36 | stdout_logfile=/var/log/wechatspider/wechatspider_scheduler.stdout.log
37 | stderr_logfile=/var/log/wechatspider/wechatspider_scheduler.stderr.log
38 | stopsignal=KILL
39 | killasgroup=true
40 |
41 | [program:wechatspider_downloader]
42 | command=/usr/bin/python /var/www/0fenbei/wechat-spider/bin/downloader.py
43 | umask=022
44 | user=root
45 | startsecs=0
46 | stopwaitsecs=0
47 | autostart=true
48 | autorestart=true
49 | stdout_logfile=/var/log/wechatspider/wechatspider_downloader.stdout.log
50 | stderr_logfile=/var/log/wechatspider/wechatspider_downloader.stderr.log
51 | stopsignal=KILL
52 | killasgroup=true
53 | process_name=%(process_num)s
54 | numprocs=2
55 |
56 | [program:wechatspider_extractor]
57 | command=/usr/bin/python /var/www/0fenbei/wechat-spider/bin/extractor.py
58 | umask=022
59 | user=ripple
60 | startsecs=0
61 | stopwaitsecs=0
62 | autostart=true
63 | autorestart=true
64 | stdout_logfile=/var/log/wechatspider/wechatspider_extractor.stdout.log
65 | stderr_logfile=/var/log/wechatspider/wechatspider_extractor.stderr.log
66 | stopsignal=KILL
67 | killasgroup=true
68 | process_name=%(process_num)s
69 | numprocs=2
70 |
71 | [program:wechatspider_processor]
72 | command=/usr/bin/python /var/www/0fenbei/wechat-spider/bin/processor.py
73 | umask=022
74 | user=ripple
75 | startsecs=0
76 | stopwaitsecs=0
77 | autostart=true
78 | autorestart=true
79 | stdout_logfile=/var/log/wechatspider/wechatspider_processor.stdout.log
80 | stderr_logfile=/var/log/wechatspider/wechatspider_processor.stderr.log
81 | stopsignal=KILL
82 | killasgroup=true
83 |
84 |
--------------------------------------------------------------------------------
/uwsgi.ini:
--------------------------------------------------------------------------------
1 | [uwsgi]
2 | chdir=/var/www/0fenbei/wechat-spider
3 | py-autoreload=3 #实现和django自带server一样更新文件自动重启功能
4 | module=wechatspider.wsgi:application
5 | master=True
6 | pidfile=/tmp/wechatspider.pid
7 | vacuum=True # clear environment on exit
8 | socket=127.0.0.1:49161
9 | processes=1 # 启动1个进程
10 | harakiri=20 # respawn processes taking more than 20 seconds
11 | max-requests=5000 # 请求5000次后重启
12 | # daemonize=/var/log/bowenpay/weibo-spider-uwsgi.log # 不使用daemon模式,防止supervisor自动重启
13 |
--------------------------------------------------------------------------------
/wechat/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bowenpay/wechat-spider/e585a4913962dfa9a817cd7b139505a0c48aecbc/wechat/__init__.py
--------------------------------------------------------------------------------
/wechat/admin.py:
--------------------------------------------------------------------------------
1 | from django.contrib import admin
2 | from .models import Wechat, Topic, Proxy, Word
3 |
4 |
5 | class WechatAdmin(admin.ModelAdmin):
6 | list_display = ('id', 'name', 'wechatid')
7 | search_fields = ['name']
8 |
9 | admin.site.register(Wechat, WechatAdmin)
10 |
11 |
12 | class TopicAdmin(admin.ModelAdmin):
13 | list_display = ('id', 'title', 'wechat')
14 | search_fields = ['title']
15 |
16 | admin.site.register(Topic, TopicAdmin)
17 |
18 |
19 | class ProxyAdmin(admin.ModelAdmin):
20 | list_display = ('kind', 'host', 'port', 'speed', 'status', 'retry')
21 | list_filter = ('kind', 'status')
22 |
23 |
24 | class WordAdmin(admin.ModelAdmin):
25 | list_display = ('id', 'kind', 'text', 'intro', 'frequency', 'next_crawl_time')
26 | list_filter = ['kind']
27 | search_fields = ['text']
28 |
29 |
30 | admin.site.register(Word, WordAdmin)
31 | admin.site.register(Proxy, ProxyAdmin)
32 |
--------------------------------------------------------------------------------
/wechat/api_urls.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | __author__ = 'yijingping'
3 | from django.conf.urls import url
4 |
5 | from . import views
6 |
7 | urlpatterns = [
8 | url(r'^add/$', views.api_add, name="wechat.api_add"),
9 | url(r'^topic/add/$', views.api_topic_add, name="wechat.api_topic_add"),
10 | url(r'^search/$', views.api_search, name="wechat.api_search"),
11 |
12 | ]
13 |
--------------------------------------------------------------------------------
/wechat/constants.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | __author__ = 'yijingping'
3 |
4 | KIND_NORMAL = 0
5 | KIND_HISTORY = 1
6 | KIND_DETAIL = 2
7 | KIND_KEYWORD = 3
8 |
9 |
--------------------------------------------------------------------------------
/wechat/downloaders.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | __author__ = 'yijingping'
3 | import time
4 | import json
5 | import platform
6 | from datetime import datetime, timedelta
7 | from dateutil.parser import parse
8 | from random import sample, randint
9 | from lxml import etree
10 | from io import StringIO
11 | from pyvirtualdisplay import Display
12 | from selenium import webdriver
13 | from selenium.webdriver.common.keys import Keys
14 | from selenium.webdriver.common.proxy import Proxy, ProxyType
15 | from wechatspider.util import get_uniqueid, get_redis
16 | from wechat.models import Topic
17 | from wechat.constants import KIND_DETAIL, KIND_KEYWORD, KIND_NORMAL
18 | from django.conf import settings
19 | from .util import stringify_children
20 |
21 | import logging
22 | logger = logging.getLogger()
23 |
24 | CRAWLER_CONFIG = settings.CRAWLER_CONFIG
25 |
26 |
27 | class SeleniumDownloaderBackend(object):
28 | headers = [
29 | {
30 | 'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.118 Safari/537.36'
31 | }
32 | ]
33 |
34 | def __init__(self, proxy=None):
35 | # 设置代理
36 | self.proxy = proxy
37 |
38 | def __enter__(self):
39 | # 打开界面
40 | self.display = self.get_display()
41 | # 打开浏览器
42 | self.browser = self.get_browser(self.proxy)
43 | return self
44 |
45 | def __exit__(self, exc_type, exc_val, exc_tb):
46 | # 关闭浏览器
47 | try:
48 | if self.browser:
49 | self.browser.delete_all_cookies()
50 | self.browser.quit()
51 | except Exception as e:
52 | logging.exception(e)
53 | # 关闭界面
54 | try:
55 | # 关闭浏览器,关闭窗口
56 | self.display and self.display.stop()
57 | except Exception as e:
58 | logging.exception(e)
59 |
60 | def get_display(self):
61 | """ 获取操作系统桌面窗口 """
62 | if platform.system() != 'Darwin':
63 | # 不是mac系统, 启动窗口
64 | display = Display(visible=0, size=(1024, 768))
65 | display.start()
66 | else:
67 | display = None
68 | return display
69 |
70 | def get_browser(self, proxy):
71 | """ 启动并返回浏览器,使用firefox """
72 | # 启动浏览器
73 | firefox_profile = webdriver.FirefoxProfile()
74 | # 禁止加载image
75 | #firefox_profile.set_preference('permissions.default.stylesheet', 2)
76 | #firefox_profile.set_preference('permissions.default.image', 2)
77 | #firefox_profile.set_preference('dom.ipc.plugins.enabled.libflashplayer.so', 'false')
78 | # 代理
79 | if proxy.is_valid():
80 | myProxy = '%s:%s' % (proxy.host, proxy.port)
81 | ff_proxy = Proxy({
82 | 'proxyType': ProxyType.MANUAL,
83 | 'httpProxy': myProxy,
84 | 'ftpProxy': myProxy,
85 | 'sslProxy': myProxy,
86 | 'noProxy': ''})
87 |
88 | browser = webdriver.Firefox(firefox_profile=firefox_profile, proxy=ff_proxy)
89 | else:
90 | browser = webdriver.Firefox(firefox_profile=firefox_profile)
91 |
92 | return browser
93 |
94 | def download(self, url):
95 | pass
96 |
97 | def download_wechat(self, data, process_topic):
98 | """ 根据微信号最新文章 """
99 | wechat_id, wechatid = data['wechat_id'], data['wechatid']
100 | try:
101 | self.visit_wechat_index(wechatid)
102 | if self.visit_wechat_topic_list(wechatid):
103 | self.download_wechat_topics(wechat_id, process_topic)
104 | except Exception as e:
105 | logger.exception(e)
106 | self.log_antispider()
107 | self.retry_crawl(data)
108 |
109 | def download_wechat_keyword(self, data, process_topic):
110 | """ 爬取关键词爬取最新文章 """
111 | word = data['word']
112 | try:
113 | self.visit_wechat_index_keyword(word)
114 | self.download_wechat_keyword_topics(word, process_topic)
115 | except Exception as e:
116 | logger.exception(e)
117 | self.log_antispider()
118 | self.retry_crawl(data)
119 |
120 | def download_wechat_topic_detail(self, data, process_topic):
121 | """ 根据url爬取文章的详情页 """
122 | url = data['url']
123 | browser = self.browser
124 | try:
125 | browser.get(url)
126 | time.sleep(3)
127 |
128 | if 'antispider' in browser.current_url:
129 | """被检测出爬虫了"""
130 | self.log_antispider()
131 | self.retry_crawl(data)
132 | time.sleep(randint(1, 5))
133 | else:
134 | js = """
135 | var imgs = document.getElementsByTagName('img');
136 |
137 | for(var i = 0; i < imgs.length; i++) {
138 | var dataSrc = imgs[i].getAttribute('data-src');
139 | if (dataSrc){
140 | imgs[i].setAttribute('src', dataSrc);
141 | }
142 | }
143 | return document.documentElement.innerHTML;
144 | """
145 | body = browser.execute_script(js)
146 | process_topic({
147 | 'url': browser.current_url,
148 | 'body': body,
149 | 'avatar': '',
150 | 'title': '',
151 | 'kind': KIND_DETAIL
152 | })
153 | time.sleep(randint(1, 5))
154 |
155 | except Exception as e:
156 | logger.exception(e)
157 | self.log_antispider()
158 | self.retry_crawl(data)
159 |
160 | def visit_wechat_index(self, wechatid):
161 | """ 访问微信首页,输入微信id,点击搜公众号 """
162 | browser = self.browser
163 | browser.get("http://weixin.sogou.com/")
164 | print browser.title
165 | element_querybox = browser.find_element_by_name('query')
166 | element_querybox.send_keys(wechatid, Keys.ARROW_DOWN)
167 | element_search_btn = browser.find_element_by_xpath("//input[@value='搜公众号']")
168 | element_search_btn.click()
169 | time.sleep(3)
170 | print browser.title
171 |
172 | def visit_wechat_index_keyword(self, word):
173 | """ 访问微信首页,输入关键词,点击搜文章 """
174 | browser = self.browser
175 | browser.get("http://weixin.sogou.com/")
176 | print browser.title
177 | element_querybox = browser.find_element_by_name('query')
178 | element_querybox.send_keys(word, Keys.ARROW_DOWN)
179 | element_search_btn = browser.find_element_by_xpath("//input[@value='搜文章']")
180 | element_search_btn.click()
181 | time.sleep(3)
182 | print browser.title
183 |
184 | def visit_wechat_topic_list(self, wechatid):
185 | """ 找到微信号,并点击进入微信号的文章列表页面 """
186 | browser = self.browser
187 | # 找到搜索列表第一个微信号, 点击打开新窗口
188 | element_wechat = browser.find_element_by_xpath("//div[@class='txt-box']/p[@class='info']/label")
189 | element_wechat_title = browser.find_element_by_xpath("//div[@class='txt-box']/p[@class='tit']/a")
190 | if element_wechat and element_wechat.text == wechatid:
191 | element_wechat_title.click()
192 | time.sleep(3)
193 | # 切到当前的文章列表页窗口
194 | new_handler = browser.window_handles[-1]
195 | browser.switch_to.window(new_handler)
196 | time.sleep(3)
197 | return True
198 | else:
199 | return False
200 |
201 | def download_wechat_topics(self, wechat_id, process_topic):
202 | """ 在微信号的文章列表页面,逐一点击打开每一篇文章,并爬取 """
203 | browser = self.browser
204 | js = """ return document.documentElement.innerHTML; """
205 | body = browser.execute_script(js)
206 |
207 | htmlparser = etree.HTMLParser()
208 | tree = etree.parse(StringIO(body), htmlparser)
209 |
210 | elems = [item.strip() for item in tree.xpath("//h4[@class='weui_media_title']/text()") if item.strip()]
211 | hrefs = ['http://mp.weixin.qq.com%s' % item for item in tree.xpath("//h4[@class='weui_media_title']/@hrefs")]
212 | elems_avatars = tree.xpath("//div[@class='weui_media_box appmsg']/span/@style")
213 | avatars = [item[21:-1] for item in elems_avatars]
214 | elems_abstracts = tree.xpath("//p[@class='weui_media_desc']")
215 | abstracts = [item.text.strip() if item.text else '' for item in elems_abstracts]
216 | links = []
217 | for idx, item in enumerate(elems[:10]):
218 | title = item
219 | print title
220 | if not title:
221 | continue
222 | uniqueid = get_uniqueid('%s:%s' % (wechat_id, title))
223 | try:
224 | Topic.objects.get(uniqueid=uniqueid)
225 | except Topic.DoesNotExist:
226 | #print len(elems), len(hrefs), len(avatars), len(abstracts)
227 | #print elems, hrefs, avatars, abstracts
228 | links.append((title, hrefs[idx], avatars[idx], abstracts[idx]))
229 | logger.debug('文章不存在, title=%s, uniqueid=%s' % (title, uniqueid))
230 | for title, link, avatar, abstract in reversed(links):
231 | # 可以访问了
232 | browser.get(link)
233 | time.sleep(3)
234 |
235 | if 'antispider' in browser.current_url:
236 | """被检测出爬虫了"""
237 | self.log_antispider()
238 | time.sleep(randint(1, 5))
239 | else:
240 | js = """
241 | var imgs = document.getElementsByTagName('img');
242 |
243 | for(var i = 0; i < imgs.length; i++) {
244 | var dataSrc = imgs[i].getAttribute('data-src');
245 | if (dataSrc){
246 | imgs[i].setAttribute('src', dataSrc);
247 | }
248 | }
249 | return document.documentElement.innerHTML;
250 | """
251 | body = browser.execute_script(js)
252 | process_topic({
253 | 'url': browser.current_url,
254 | 'body': body,
255 | 'avatar': avatar,
256 | 'title': title,
257 | 'abstract': abstract,
258 | 'kind': KIND_NORMAL
259 | })
260 | time.sleep(randint(1, 5))
261 |
262 | def download_wechat_keyword_topics(self, word, process_topic):
263 | """ 在关键词下的文章列表页面,逐一点击打开每一篇文章,并爬取 """
264 | browser = self.browser
265 | js = """ return document.documentElement.innerHTML; """
266 | body = browser.execute_script(js)
267 |
268 | htmlparser = etree.HTMLParser()
269 | tree = etree.parse(StringIO(body), htmlparser)
270 |
271 | elems = [stringify_children(item).replace('red_beg', '').replace('red_end', '') for item in tree.xpath("//div[@class='txt-box']/h3/a")]
272 | hrefs = tree.xpath("//div[@class='txt-box']/h3/a/@href")
273 | #avatars = tree.xpath("//div[@class='img-box']/a/img/@src")
274 | #elems_abstracts = tree.xpath("//div[@class='txt-box']/p")
275 | #abstracts = [item.text.strip() if item.text else '' for item in elems_abstracts]
276 | avatars = [''] * len(elems)
277 | abstracts = [''] * len(elems)
278 | links = []
279 | for idx, item in enumerate(elems):
280 | title = item
281 | print title
282 | if not title:
283 | continue
284 | uniqueid = get_uniqueid('%s:%s' % (word, title))
285 | try:
286 | Topic.objects.get(uniqueid=uniqueid)
287 | except Topic.DoesNotExist:
288 | #print len(elems), len(hrefs), len(avatars), len(abstracts)
289 | print elems, hrefs, avatars, abstracts
290 | links.append((title, hrefs[idx], avatars[idx], abstracts[idx]))
291 | logger.debug('文章不存在, title=%s, uniqueid=%s' % (title, uniqueid))
292 | for title, link, avatar, abstract in reversed(links):
293 | # 可以访问了
294 | browser.get(link)
295 | time.sleep(3)
296 |
297 | if 'antispider' in browser.current_url:
298 | """被检测出爬虫了"""
299 | self.log_antispider()
300 | time.sleep(randint(1, 5))
301 | else:
302 | js = """
303 | var imgs = document.getElementsByTagName('img');
304 |
305 | for(var i = 0; i < imgs.length; i++) {
306 | var dataSrc = imgs[i].getAttribute('data-src');
307 | if (dataSrc){
308 | imgs[i].setAttribute('src', dataSrc);
309 | }
310 | }
311 | return document.documentElement.innerHTML;
312 | """
313 | body = browser.execute_script(js)
314 | process_topic({
315 | 'url': browser.current_url,
316 | 'body': body,
317 | 'avatar': avatar,
318 | 'title': title,
319 | 'abstract': abstract,
320 | 'kind': KIND_KEYWORD
321 | })
322 | time.sleep(randint(1, 5))
323 |
324 | def log_antispider(self):
325 | """ 记录1小时内的被禁爬的数量 """
326 | r = get_redis()
327 | if r.incr(CRAWLER_CONFIG['antispider']) <= 1:
328 | r.expire(CRAWLER_CONFIG['antispider'], 3600)
329 |
330 | def retry_crawl(self, data):
331 | """ 如果被禁爬,重试 """
332 | r = get_redis()
333 | retry = data.get('retry', 0)
334 |
335 | if data.get('kind') == KIND_DETAIL:
336 | if retry >= 20:
337 | return
338 | data = {
339 | 'kind': data['kind'],
340 | 'url': data['url'],
341 | 'retry': retry + 1
342 | }
343 | elif data.get('kind') == KIND_KEYWORD:
344 | if retry >= 3:
345 | return
346 | data = {
347 | 'kind': data['kind'],
348 | 'word': data['word'],
349 | 'retry': retry + 1
350 | }
351 | else:
352 | if retry >= 3:
353 | return
354 | data = {
355 | 'kind': data['kind'],
356 | 'wechat_id': data['wechat_id'],
357 | 'wechatid': data['wechatid'],
358 | 'retry': retry + 1
359 | }
360 |
361 | r.lpush(settings.CRAWLER_CONFIG["downloader"], json.dumps(data))
362 |
--------------------------------------------------------------------------------
/wechat/extractors.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | __author__ = 'yijingping'
3 | from abc import ABCMeta
4 | from abc import abstractmethod
5 | import requests
6 | import oss2
7 | import re
8 | from bs4 import BeautifulSoup
9 | from oss2.exceptions import NotFound
10 | from copy import copy
11 | from hashlib import md5
12 | from lxml import etree
13 | from io import StringIO
14 | from django.conf import settings
15 | import logging
16 | logger = logging.getLogger()
17 |
18 |
19 | OSS2_CONF = settings.OSS2_CONFIG
20 | BUCKET = None
21 |
22 |
23 | def get_bucket():
24 | global BUCKET
25 | if not BUCKET:
26 | auth = oss2.Auth(OSS2_CONF['ACCESS_KEY_ID'], OSS2_CONF['ACCESS_KEY_SECRET'])
27 | BUCKET = oss2.Bucket(auth, 'http://%s' % OSS2_CONF['BUCKET_DOMAIN'], OSS2_CONF['BUCKET_NAME'])
28 |
29 | return BUCKET
30 |
31 |
32 | def download_to_oss(url, path):
33 | # 如果没有开启oss,直接返回原url
34 | if not settings.OSS2_ENABLE:
35 | return url
36 |
37 | r = requests.get(url)
38 | r.close()
39 | key = path + md5(r.content).hexdigest()
40 | bucket = get_bucket()
41 | try:
42 | bucket.head_object(key)
43 | except NotFound as e:
44 | logging.exception(e)
45 | bucket.put_object(key, r, headers={'Content-Type': r.headers.get('Content-Type', '')})
46 |
47 | return 'http://%s/%s' % (OSS2_CONF["CDN_DOMAIN"], key)
48 |
49 |
50 | class BaseExtractor(object):
51 | __metaclass__ = ABCMeta
52 |
53 | @abstractmethod
54 | def __init__(self):
55 | pass
56 |
57 | @abstractmethod
58 | def extract(self):
59 | pass
60 |
61 |
62 | def replace_all(content, srcs, new_srcs):
63 | """ 将content中的srcs全部替换成new_srcs
64 | """
65 | replaces = zip(srcs, new_srcs)
66 | for src, new_src in replaces:
67 | content = content.replace(src.split('?')[0], new_src)
68 | return content
69 |
70 |
71 | class ImageExtractor(BaseExtractor):
72 | def __init__(self, data):
73 | """ data 是图片url,或者图片url的列表
74 | :param data:
75 | :return: 如果是url,返回新的url; 如果是列表,返回新的url列表
76 | """
77 | self.data = data
78 |
79 | def extract(self):
80 | d = self.data
81 | res = None
82 | if not d:
83 | return d
84 | elif isinstance(d, basestring):
85 | if d.startswith('http'):
86 | ## 内容是图片地址
87 | res = download_to_oss(d, OSS2_CONF["IMAGES_PATH"])
88 | else:
89 | ## 内容是包含图片的文字
90 | htmlparser = etree.HTMLParser()
91 | tree = etree.parse(StringIO(d), htmlparser)
92 | # 找出所有图片src
93 | srcs = tree.xpath("//img[starts-with(@src,'http')]/@src")
94 | data_srcs = tree.xpath("//img[starts-with(@data-src,'http')]/@data-src")
95 | srcs = list(set(srcs + data_srcs))
96 | # 下载并传到OSS中
97 | new_srcs = [download_to_oss(item, OSS2_CONF["IMAGES_PATH"]) for item in srcs]
98 | # 替换掉原文中的图片src
99 | res = replace_all(d, srcs, new_srcs)
100 | elif isinstance(d, list):
101 | res = [download_to_oss(item, OSS2_CONF["IMAGES_PATH"]) for item in d]
102 |
103 | return res
104 |
105 |
106 | class VideoExtractor(BaseExtractor):
107 | def __init__(self, data):
108 | """ data 是视频url,或者视频url的列表
109 | :param data:
110 | :return: 如果是url,返回新的url; 如果是列表,返回新的url列表
111 | """
112 | self.data = data
113 |
114 | def extract(self):
115 | d = self.data
116 | new_url = None
117 | if not d:
118 | return d
119 | elif isinstance(d, basestring):
120 | new_url = download_to_oss(d, OSS2_CONF["VIDEOS_PATH"])
121 | elif isinstance(d, list):
122 | new_url = [download_to_oss(item, OSS2_CONF["VIDEOS_PATH"]) for item in d]
123 |
124 | return new_url
125 |
126 |
127 | class XPathExtractor(BaseExtractor):
128 | def __init__(self, content, rule):
129 | htmlparser = etree.HTMLParser()
130 | self.tree = etree.parse(StringIO(content), htmlparser)
131 | self.rule = rule
132 |
133 | def extract(self):
134 | return self.tree.xpath(self.rule)
135 |
136 |
137 | class PythonExtractor(BaseExtractor):
138 | def __init__(self, code, in_val, context):
139 | self.code = code
140 | self.in_val = in_val
141 | self.context = copy(context)
142 | self.context.update({'in_val': in_val})
143 |
144 | def extract(self):
145 | res = self.in_val
146 | g, l = {}, self.context
147 | try:
148 | exec(self.code, g, l)
149 | res = l["out_val"]
150 | except Exception as e:
151 | logger.exception(e)
152 | finally:
153 | return res
154 |
155 |
156 |
157 | class WechatContentExtractor(BaseExtractor):
158 | """
159 | 去掉投票的iframe,将图片和视频的宽高变为auto
160 | """
161 | def __init__(self, data):
162 | self.data = data
163 |
164 | def extract(self):
165 | res = self.data
166 | try:
167 | # 去掉图片蒙版
168 | res = res.replace('var occupyImg = ', '')
169 | bs=BeautifulSoup(res)
170 | # 去掉投票的iframe
171 | vote = bs.find('span', {'class':'vote_area'})
172 | if vote:
173 | vote.replace_with('')
174 | # 将图片和视频的宽高变为auto,src替换为data-src
175 | imgs = bs.select('img')
176 | for x in imgs:
177 | if x.get('style'):
178 | x['style'] = re.sub(r'(\w+px)', 'auto', x['style'])
179 |
180 | if x.get('data-src'):
181 | x['src'] = x.get('data-src')
182 |
183 | # 将视频的宽高设置为auto
184 | videos = bs.find_all('iframe', {'class': 'video_iframe'})
185 | for item in videos:
186 | item['width'] = 'auto'
187 | item['height'] = 'auto'
188 | if item.get('src'):
189 | s = item.get('src')
190 | s = re.sub(r'(height=\d+[\.\d+]*)', 'height=auto', s)
191 | s = re.sub(r'(width=\d+[\.\d+]*)', 'width=auto', s)
192 | item['src'] = s
193 | if item.get('data-src'):
194 | s = item.get('data-src')
195 | s = re.sub(r'(height=\d+[\.\d+]*)', 'height=auto', s)
196 | s = re.sub(r'(width=\d+[\.\d+]*)', 'width=auto', s)
197 | item['data-src'] = s
198 | #if item.get('style'):
199 | # item['style'] = re.sub(r'(\w+px)', 'auto', item['style'])
200 |
201 | res = unicode(bs)
202 | except Exception as e:
203 | logger.exception(e)
204 | finally:
205 | return res
--------------------------------------------------------------------------------
/wechat/forms.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | __author__ = 'yijingping'
3 | from django import forms
4 | from .models import Wechat
5 |
6 |
7 | class WechatForm(forms.ModelForm):
8 | class Meta:
9 | model = Wechat
10 | fields = ['avatar', 'qrcode', 'name', 'wechatid', 'intro', 'frequency']
11 |
12 |
13 | class WechatConfigForm(forms.ModelForm):
14 | class Meta:
15 | model = Wechat
16 | fields = ['frequency']
--------------------------------------------------------------------------------
/wechat/management/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | __author__ = 'yijingping'
3 |
--------------------------------------------------------------------------------
/wechat/management/commands/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | __author__ = 'yijingping'
3 |
--------------------------------------------------------------------------------
/wechat/management/commands/checkproxies.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | __author__ = 'yijingping'
3 | import time
4 | from django.core.management.base import BaseCommand
5 | from wechat.models import Proxy
6 | from wechat.util import check_proxy, check_wechat
7 |
8 |
9 | class Command(BaseCommand):
10 | help = 'check proxies'
11 |
12 | def handle(self, *args, **options):
13 | while True:
14 | #self.check_all_proxies()
15 | self.check_wechat_proxies()
16 | time.sleep(60)
17 |
18 | def check_all_proxies(self):
19 | # 检测新代理
20 | qs1 = Proxy.objects.filter(status=Proxy.STATUS_NEW)
21 | # 检测成功代理
22 | qs2 = Proxy.objects.filter(status=Proxy.STATUS_SUCCESS)
23 | # 检测失败代理
24 | qs3 = Proxy.objects.filter(status=Proxy.STATUS_FAIL, retry__lt=3)
25 | for qs in [qs1, qs2, qs3]:
26 | for item in qs:
27 | has_exception, proxy_detected, time_diff = check_proxy(item.host, item.port)
28 | if has_exception or not proxy_detected:
29 | item.status = Proxy.STATUS_FAIL
30 | item.retry += 1
31 | item.save()
32 | else:
33 | item.status = Proxy.STATUS_SUCCESS
34 | item.speed = time_diff * 1000
35 | item.retry = 0
36 | item.save()
37 |
38 | def check_wechat_proxies(self):
39 | # 删除无效代理
40 | qs3 = Proxy.objects.filter(kind=Proxy.KIND_DOWNLOAD, status=Proxy.STATUS_FAIL, retry__gte=1).delete()
41 | # 检测新代理
42 | qs1 = Proxy.objects.filter(kind=Proxy.KIND_DOWNLOAD, status=Proxy.STATUS_NEW)
43 | # 检测成功代理
44 | qs2 = Proxy.objects.filter(kind=Proxy.KIND_DOWNLOAD, status=Proxy.STATUS_SUCCESS)
45 | # 检测失败代理
46 | #qs3 = Proxy.objects.filter(kind=Proxy.KIND_DOWNLOAD, status=Proxy.STATUS_FAIL, retry__lt=1)
47 | for qs in [qs1, qs2]:
48 | for item in qs:
49 | has_exception, proxy_detected, time_diff = check_wechat(item.host, item.port)
50 | if has_exception or not proxy_detected:
51 | item.delete()
52 | else:
53 | item.status = Proxy.STATUS_SUCCESS
54 | item.speed = time_diff * 1000
55 | item.retry = 0
56 | item.save()
57 |
--------------------------------------------------------------------------------
/wechat/management/commands/getproxies.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | __author__ = 'yijingping'
3 | import time
4 | from django.core.management.base import BaseCommand
5 | from wechat.models import Proxy
6 | from wechat.util import check_proxy
7 | import requests
8 | import logging
9 | logger = logging.getLogger()
10 |
11 | class Command(BaseCommand):
12 | help = 'get proxies'
13 |
14 | def handle(self, *args, **options):
15 | while True:
16 | time.sleep(5)
17 | self.get_proxies()
18 |
19 | def get_proxies(self):
20 | # 快代理
21 | #url = 'http://dev.kuaidaili.com/api/getproxy/?orderid=955742122799513&num=100&area=%E5%A4%A7%E9%99%86&b_pcchrome=1&b_pcie=1&b_pcff=1&protocol=1&method=2&an_ha=1&sp1=1&sep=1'
22 | # 代理666
23 | #url = 'http://qsdrk.daili666api.com/ip/?tid=559017461234554&num=100&delay=3&category=2&sortby=time&foreign=none&filter=on'
24 | url = 'http://qsdrk.daili666api.com/ip/?tid=555451817416492&num=100&delay=3&category=2&sortby=time&foreign=none&filter=on'
25 | r = requests.get(url)
26 | lines = r.text.split()
27 | for line in lines:
28 | logger.debug(line)
29 | try:
30 | host, port = line.split(':')
31 | Proxy.objects.get_or_create(host=host, port=int(port))
32 | except Exception as e:
33 | print e
34 |
--------------------------------------------------------------------------------
/wechat/migrations/0001_initial.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import unicode_literals
3 |
4 | from django.db import models, migrations
5 |
6 |
7 | class Migration(migrations.Migration):
8 |
9 | dependencies = [
10 | ]
11 |
12 | operations = [
13 | migrations.CreateModel(
14 | name='Proxy',
15 | fields=[
16 | ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
17 | ('kind', models.IntegerField(default=1, verbose_name=b'\xe7\xb1\xbb\xe5\x9e\x8b', choices=[(0, b'\xe6\x90\x9c\xe7\xb4\xa2\xe4\xbb\xa3\xe7\x90\x86'), (1, b'\xe4\xb8\x8b\xe8\xbd\xbd\xe4\xbb\xa3\xe7\x90\x86')])),
18 | ('user', models.CharField(default=b'', max_length=100, blank=True)),
19 | ('password', models.CharField(default=b'', max_length=100, blank=True)),
20 | ('host', models.CharField(max_length=100)),
21 | ('port', models.IntegerField(default=80)),
22 | ('speed', models.IntegerField(default=0, verbose_name=b'\xe8\xbf\x9e\xe6\x8e\xa5\xe9\x80\x9f\xe5\xba\xa6(ms)')),
23 | ('status', models.IntegerField(default=0, verbose_name=b'\xe7\x8a\xb6\xe6\x80\x81', choices=[(0, b'\xe6\x9c\xaa\xe6\xa3\x80\xe6\xb5\x8b'), (1, b'\xe6\xa3\x80\xe6\xb5\x8b\xe6\x88\x90\xe5\x8a\x9f'), (2, b'\xe6\xa3\x80\xe6\xb5\x8b\xe5\xa4\xb1\xe8\xb4\xa5')])),
24 | ('retry', models.IntegerField(default=0, verbose_name=b'\xe5\xb0\x9d\xe8\xaf\x95\xe6\xac\xa1\xe6\x95\xb0')),
25 | ('create_time', models.DateTimeField(auto_now_add=True, verbose_name=b'\xe5\x88\x9b\xe5\xbb\xba\xe6\x97\xb6\xe9\x97\xb4')),
26 | ('update_time', models.DateTimeField(auto_now=True, verbose_name=b'\xe6\x9b\xb4\xe6\x96\xb0\xe6\x97\xb6\xe9\x97\xb4')),
27 | ],
28 | options={
29 | 'verbose_name_plural': '\u8bbf\u95ee\u4ee3\u7406',
30 | },
31 | ),
32 | migrations.CreateModel(
33 | name='Topic',
34 | fields=[
35 | ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
36 | ('uniqueid', models.CharField(unique=True, max_length=100, verbose_name=b'url\xe7\x9a\x84md5\xe5\x80\xbc')),
37 | ('words', models.IntegerField(default=0, verbose_name=b'\xe5\xad\x97\xe6\x95\xb0')),
38 | ('url', models.CharField(default=b'', max_length=500, verbose_name=b'\xe6\x96\x87\xe7\xab\xa0\xe7\x9a\x84url')),
39 | ('avatar', models.CharField(default=b'', max_length=500, verbose_name=b'\xe7\xbc\xa9\xe7\x95\xa5\xe5\x9b\xbe\xe5\x9c\xb0\xe5\x9d\x80')),
40 | ('title', models.CharField(max_length=200, verbose_name=b'\xe6\xa0\x87\xe9\xa2\x98')),
41 | ('origin_title', models.CharField(default=b'', max_length=200, verbose_name=b'\xe5\x8e\x9f\xe6\x96\x87\xe6\xa0\x87\xe9\xa2\x98')),
42 | ('abstract', models.TextField(default=b'', verbose_name=b'\xe5\x86\x85\xe5\xae\xb9\xe7\xae\x80\xe4\xbb\x8b')),
43 | ('content', models.TextField(default=b'', verbose_name=b'\xe6\x96\x87\xe7\xab\xa0\xe5\x86\x85\xe5\xae\xb9')),
44 | ('source', models.TextField(default=b'', verbose_name=b'\xe6\x96\x87\xe7\xab\xa0\xe5\x8e\x9f\xe5\x86\x85\xe5\xae\xb9')),
45 | ('read_num', models.IntegerField(default=0, verbose_name=b'\xe9\x98\x85\xe8\xaf\xbb\xe6\x95\xb0')),
46 | ('like_num', models.IntegerField(default=0, verbose_name=b'\xe7\x82\xb9\xe8\xb5\x9e\xe6\x95\xb0')),
47 | ('publish_time', models.DateTimeField(verbose_name=b'\xe5\x8f\x91\xe5\xb8\x83\xe6\x97\xb6\xe9\x97\xb4', db_index=True)),
48 | ('create_time', models.DateTimeField(auto_now_add=True, verbose_name=b'\xe5\x88\x9b\xe5\xbb\xba\xe6\x97\xb6\xe9\x97\xb4')),
49 | ('update_time', models.DateTimeField(auto_now=True, verbose_name=b'\xe6\x9b\xb4\xe6\x96\xb0\xe6\x97\xb6\xe9\x97\xb4')),
50 | ('available', models.CharField(default=b'', max_length=100, verbose_name=b'\xe6\x98\xaf\xe5\x90\xa6\xe5\x8f\xaf\xe7\x94\xa8', db_index=True)),
51 | ],
52 | options={
53 | 'verbose_name_plural': '\u6587\u7ae0',
54 | },
55 | ),
56 | migrations.CreateModel(
57 | name='Wechat',
58 | fields=[
59 | ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
60 | ('avatar', models.CharField(default=b'', max_length=500, verbose_name=b'\xe5\x85\xac\xe4\xbc\x97\xe5\x8f\xb7\xe5\xa4\xb4\xe5\x83\x8f', blank=True)),
61 | ('qrcode', models.CharField(default=b'', max_length=500, verbose_name=b'\xe4\xba\x8c\xe7\xbb\xb4\xe7\xa0\x81', blank=True)),
62 | ('name', models.CharField(max_length=100, verbose_name=b'\xe5\x85\xac\xe4\xbc\x97\xe5\x8f\xb7')),
63 | ('wechatid', models.CharField(unique=True, max_length=100, verbose_name=b'\xe5\x85\xac\xe4\xbc\x97\xe5\x8f\xb7id')),
64 | ('intro', models.TextField(default=b'', verbose_name=b'\xe7\xae\x80\xe4\xbb\x8b', blank=True)),
65 | ('frequency', models.IntegerField(default=0, verbose_name=b'\xe7\x88\xac\xe5\x8f\x96\xe9\xa2\x91\xe7\x8e\x87, \xe5\x8d\x95\xe4\xbd\x8d:\xe5\x88\x86\xe9\x92\x9f')),
66 | ('next_crawl_time', models.DateTimeField(auto_now_add=True, verbose_name=b'\xe4\xb8\x8b\xe6\xac\xa1\xe7\x88\xac\xe5\x8f\x96\xe6\x97\xb6\xe9\x97\xb4')),
67 | ('create_time', models.DateTimeField(auto_now_add=True, verbose_name=b'\xe5\x88\x9b\xe5\xbb\xba\xe6\x97\xb6\xe9\x97\xb4')),
68 | ('status', models.IntegerField(default=0, verbose_name=b'\xe7\x8a\xb6\xe6\x80\x81', choices=[(0, b'\xe9\xbb\x98\xe8\xae\xa4'), (1, b'\xe7\xa6\x81\xe7\x94\xa8'), (2, b'\xe5\x88\xa0\xe9\x99\xa4')])),
69 | ],
70 | options={
71 | 'verbose_name_plural': '\u516c\u4f17\u53f7',
72 | },
73 | ),
74 | migrations.CreateModel(
75 | name='Word',
76 | fields=[
77 | ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
78 | ('kind', models.IntegerField(default=0, verbose_name=b'\xe7\xb1\xbb\xe5\x9e\x8b', choices=[(0, b'\xe5\x85\xb3\xe9\x94\xae\xe8\xaf\x8d')])),
79 | ('text', models.CharField(max_length=100, verbose_name=b'\xe8\xaf\x8d')),
80 | ('intro', models.TextField(default=b'', verbose_name=b'\xe7\xae\x80\xe4\xbb\x8b', blank=True)),
81 | ('frequency', models.IntegerField(default=100, verbose_name=b'\xe7\x88\xac\xe5\x8f\x96\xe9\xa2\x91\xe7\x8e\x87, \xe5\x8d\x95\xe4\xbd\x8d:\xe5\x88\x86\xe9\x92\x9f')),
82 | ('next_crawl_time', models.DateTimeField(auto_now_add=True, verbose_name=b'\xe4\xb8\x8b\xe6\xac\xa1\xe7\x88\xac\xe5\x8f\x96\xe6\x97\xb6\xe9\x97\xb4')),
83 | ('create_time', models.DateTimeField(auto_now_add=True, verbose_name=b'\xe5\x88\x9b\xe5\xbb\xba\xe6\x97\xb6\xe9\x97\xb4')),
84 | ],
85 | options={
86 | 'verbose_name_plural': '\u8bcd',
87 | },
88 | ),
89 | migrations.AddField(
90 | model_name='topic',
91 | name='wechat',
92 | field=models.ForeignKey(verbose_name=b'\xe5\x85\xac\xe4\xbc\x97\xe5\x8f\xb7', to='wechat.Wechat'),
93 | ),
94 | ]
95 |
--------------------------------------------------------------------------------
/wechat/migrations/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bowenpay/wechat-spider/e585a4913962dfa9a817cd7b139505a0c48aecbc/wechat/migrations/__init__.py
--------------------------------------------------------------------------------
/wechat/models.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | __author__ = 'yijingping'
3 | from django.db import models
4 | from datetime import date, datetime, timedelta
5 |
6 | class Wechat(models.Model):
7 | STATUS_DEFAULT = 0
8 | STATUS_DISABLE = 1
9 | STATUS_DELETE = 2
10 | STATUS_CHOICES = (
11 | (STATUS_DEFAULT, '默认'),
12 | (STATUS_DISABLE, '禁用'),
13 | (STATUS_DELETE, '删除')
14 | )
15 | avatar = models.CharField(max_length=500, blank=True, default='', verbose_name='公众号头像')
16 | qrcode = models.CharField(max_length=500, blank=True, default='', verbose_name='二维码')
17 | name = models.CharField(max_length=100, verbose_name='公众号')
18 | wechatid = models.CharField(max_length=100, verbose_name='公众号id', unique=True)
19 | intro = models.TextField(default='', blank=True, verbose_name='简介')
20 | frequency = models.IntegerField(default=0, verbose_name='爬取频率, 单位:分钟')
21 | next_crawl_time = models.DateTimeField(auto_now_add=True, verbose_name='下次爬取时间')
22 | create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
23 | status = models.IntegerField(default=STATUS_DEFAULT, choices=STATUS_CHOICES, verbose_name="状态")
24 |
25 | def last_day_topics_count(self):
26 | yestoday = date.today() - timedelta(days=1)
27 | yestoday_datetime = datetime.combine(yestoday, datetime.min.time())
28 | return Topic.objects.filter(wechat=self, publish_time__gt=yestoday_datetime).count()
29 |
30 | def last_week_topics_count(self):
31 | last_week = date.today() - timedelta(days=7)
32 | last_week_datetime = datetime.combine(last_week, datetime.min.time())
33 | return Topic.objects.filter(wechat=self, publish_time__gt=last_week_datetime).count()
34 |
35 | def total_topics_count(self):
36 | return Topic.objects.filter(wechat=self).count()
37 |
38 | def __unicode__(self):
39 | return self.name
40 |
41 | class Meta:
42 | verbose_name_plural = "公众号"
43 |
44 |
45 | class Topic(models.Model):
46 | wechat = models.ForeignKey('Wechat', verbose_name='公众号')
47 | uniqueid = models.CharField(unique=True, max_length=100, verbose_name='url的md5值')
48 | words = models.IntegerField(default=0, verbose_name='字数')
49 |
50 | url = models.CharField(max_length=500, default='', verbose_name='文章的url')
51 | avatar = models.CharField(max_length=500, default='', verbose_name='缩略图地址')
52 | title = models.CharField(max_length=200, verbose_name='标题')
53 | origin_title = models.CharField(max_length=200, default='', verbose_name='原文标题')
54 |
55 | abstract = models.TextField(default='', verbose_name='内容简介')
56 | content = models.TextField(default='', verbose_name='文章内容')
57 | source = models.TextField(default='', verbose_name='文章原内容')
58 |
59 | read_num = models.IntegerField(default=0, verbose_name='阅读数')
60 | like_num = models.IntegerField(default=0, verbose_name='点赞数')
61 |
62 | publish_time = models.DateTimeField(db_index=True, verbose_name='发布时间')
63 | create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
64 | update_time = models.DateTimeField(auto_now=True, verbose_name='更新时间')
65 | available = models.CharField(db_index=True, max_length=100, default='', verbose_name='是否可用')
66 |
67 | def __unicode__(self):
68 | return self.title
69 |
70 | class Meta:
71 | verbose_name_plural = "文章"
72 |
73 |
74 | class Proxy(models.Model):
75 | STATUS_NEW = 0
76 | STATUS_SUCCESS = 1
77 | STATUS_FAIL = 2
78 | STATUS_CHOICES = (
79 | (STATUS_NEW,'未检测'),
80 | (STATUS_SUCCESS,'检测成功'),
81 | (STATUS_FAIL,'检测失败'),
82 | )
83 | KIND_SEARCH = 0
84 | KIND_DOWNLOAD = 1
85 | KIND_CHOICES = (
86 | (KIND_SEARCH, '搜索代理'),
87 | (KIND_DOWNLOAD, '下载代理'),
88 | )
89 | kind = models.IntegerField(default=KIND_DOWNLOAD, choices=KIND_CHOICES, verbose_name="类型")
90 | user = models.CharField(default='', blank=True, max_length=100)
91 | password = models.CharField(default='', blank=True, max_length=100)
92 | host = models.CharField(max_length=100)
93 | port = models.IntegerField(default=80)
94 | speed = models.IntegerField(default=0, verbose_name="连接速度(ms)")
95 | status = models.IntegerField(default=STATUS_NEW, choices=STATUS_CHOICES, verbose_name="状态")
96 | retry = models.IntegerField(default=0, verbose_name="尝试次数")
97 | create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
98 | update_time = models.DateTimeField(auto_now=True, verbose_name='更新时间')
99 |
100 | class Meta:
101 | verbose_name_plural = "访问代理"
102 |
103 |
104 | class Word(models.Model):
105 | KIND_KEYWORD = 0
106 | #KIND_TOPIC = 1 #
107 | KIND_CHOICES = (
108 | (KIND_KEYWORD, '关键词'),
109 | #(KIND_TOPIC, '话题'),
110 | )
111 | kind = models.IntegerField(default=KIND_KEYWORD, choices=KIND_CHOICES, verbose_name="类型")
112 | text = models.CharField(max_length=100, verbose_name='词')
113 | intro = models.TextField(default='', blank=True, verbose_name='简介')
114 | frequency = models.IntegerField(default=100, verbose_name='爬取频率, 单位:分钟')
115 | next_crawl_time = models.DateTimeField(auto_now_add=True, verbose_name='下次爬取时间')
116 | create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
117 |
118 | def __unicode__(self):
119 | return '%s %s' % (self.kind, self.text)
120 |
121 | class Meta:
122 | verbose_name_plural = "词"
123 |
--------------------------------------------------------------------------------
/wechat/processors.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | __author__ = 'yijingping'
3 | from wechatspider.util import get_uniqueid
4 | from wechat.constants import KIND_DETAIL, KIND_KEYWORD
5 | from wechat.models import Wechat
6 |
7 | class DjangoModelBackend(object):
8 | def __init__(self, _class):
9 | self._class = _class
10 |
11 | def process(self, params):
12 | C = self._class
13 | # 排除被屏蔽的情况
14 | if 'mp.weixin.qq.com' not in params.get('url'):
15 | return
16 | # 排除代理失败的情况
17 | if 'wx.qq.com' not in params.get('source'):
18 | return
19 | # 存储数据
20 | if params.get('kind') in [KIND_DETAIL, KIND_KEYWORD]:
21 | params.pop('kind', None)
22 | params.pop('retry', None)
23 | # 保存微信号
24 | wechatid = params.pop('wechatid', '')
25 | name = params.pop('name', '')
26 | intro = params.pop('intro', '')
27 | qrcode = params.pop('qrcode', '')
28 | wechat, created = Wechat.objects.get_or_create(wechatid=wechatid, defaults={
29 | "wechatid": wechatid,
30 | "name": name,
31 | "intro": intro,
32 | "qrcode": qrcode,
33 | "status": Wechat.STATUS_DISABLE
34 | })
35 | # 如果微信号状态为已删除,则不保存这篇文章
36 | if wechat.status == Wechat.STATUS_DELETE:
37 | return
38 |
39 | # 保存文章
40 | params['wechat_id'] = wechat.id
41 | params['uniqueid'] = get_uniqueid('%s:%s' % (params['wechat_id'], params['title']))
42 | C.objects.update_or_create(uniqueid=params['uniqueid'], defaults=params)
43 |
44 | else:
45 | params.pop('kind', None)
46 | params.pop('retry', None)
47 | params['uniqueid'] = get_uniqueid('%s:%s' % (params['wechat_id'], params['title']))
48 | C.objects.update_or_create(uniqueid=params['uniqueid'], defaults=params)
49 |
50 |
--------------------------------------------------------------------------------
/wechat/proxies.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | __author__ = 'yijingping'
3 | from .models import Proxy
4 |
5 | class MysqlProxyBackend(object):
6 | def __init__(self):
7 | proxy = Proxy.objects.filter(kind=Proxy.KIND_DOWNLOAD, status=Proxy.STATUS_SUCCESS).order_by('?').first()
8 | if proxy:
9 | self.user = proxy.user
10 | self.password = proxy.password
11 | self.host = proxy.host
12 | self.port = proxy.port
13 | else:
14 | self.user, self.password, self.host, self.port = '', '', '', ''
15 |
16 | def is_valid(self):
17 | return self.host and self.port
18 |
19 | def __str__(self):
20 | return ':'.join([str(self.user), str(self.password), str(self.host), str(self.port)])
21 |
--------------------------------------------------------------------------------
/wechat/templates/wechat/edit.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 |
3 | {% block main-content %}
4 |
5 |
6 |
7 |
8 | 编辑公众号
9 |
10 |
42 |
43 |
44 |
45 |
46 | {% endblock %}
--------------------------------------------------------------------------------
/wechat/templates/wechat/index.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 | {% load paginator %}
3 | {% load staticfiles %}
4 | {% block main-content %}
5 |
6 |
7 |
8 |
9 |
10 | 添加公众号
11 |
12 |
13 |
22 |
23 |
24 |
25 |
26 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
55 |
95 |
96 |
99 |
100 |
101 |
102 |
103 |
104 | {% endblock %}
105 |
106 | {% block footer-js %}
107 |
108 |
109 |
110 |
111 |
135 | {% endblock %}
136 |
--------------------------------------------------------------------------------
/wechat/templates/wechat/keywords_list.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 | {% load paginator %}
3 | {% block main-content %}
4 |
5 |
6 |
7 |
11 |
12 |
13 |
14 |
15 | #ID |
16 | 关键词 |
17 | 简介 |
18 | 爬取频率 |
19 | 下次爬取时间 |
20 | 操作 |
21 |
22 |
23 |
24 | {% for item in keywords %}
25 |
26 | {{ item.id }} |
27 | {{ item.text }} |
28 | {{ item.intro }} |
29 | {{ item.frequency}} |
30 | {% if item.frequency > 0 %}{{ item.next_crawl_time}}{% else %}N/A{% endif %} |
31 | |
32 |
33 | {% endfor %}
34 |
35 |
36 |
37 |
40 |
41 |
42 |
43 |
44 | {% endblock %}
45 |
--------------------------------------------------------------------------------
/wechat/templates/wechat/search_content.html:
--------------------------------------------------------------------------------
1 | {% load utils %}
2 | {% for item in wechats %}
3 |
17 | {% endfor %}
18 |
--------------------------------------------------------------------------------
/wechat/templates/wechat/topic_available_list.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 | {% load paginator %}
3 | {% block main-content %}
4 |
5 |
6 |
7 |
8 | 文章列表
9 |
10 |
11 |
12 |
13 |
14 | #ID |
15 | 头像 |
16 | 标题 |
17 | 原文链接 |
18 | 公众号 |
19 | 时间 |
20 | 阅读数 |
21 | 点赞数 |
22 | 是否可用 |
23 |
24 |
25 |
26 | {% for item in topics %}
27 | {% with wechat=item.wechat %}
28 |
29 | {{ item.id}} |
30 | |
31 | {{ item.title}} |
32 | |
33 | {{ wechat.name}} |
34 | {{ item.publish_time}} |
35 | {{ item.read_num }} |
36 | {{ item.like_num }} |
37 | {{ item.available }} |
38 |
39 | {% endwith %}
40 | {% endfor %}
41 |
42 |
43 |
44 |
47 |
48 |
49 |
50 |
51 | {% endblock %}
52 |
--------------------------------------------------------------------------------
/wechat/templates/wechat/topic_detail.html:
--------------------------------------------------------------------------------
1 | {% load staticfiles %}
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | {% load wechat_util %}
10 |
11 |
12 |
13 |
17 |
18 |
19 | {{ topic.source | safe }}
20 |
21 | {% block footer-js %}
22 |
31 | {% endblock %}
32 |
--------------------------------------------------------------------------------
/wechat/templates/wechat/topic_list.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 | {% load paginator %}
3 | {% block main-content %}
4 |
5 |
6 |
20 |
21 |
22 | 文章列表
23 |
24 |
25 |
26 |
27 |
28 | #ID |
29 | 头像 |
30 | 标题 |
31 | 原文链接 |
32 | 公众号 |
33 | 时间 |
34 | 阅读数 |
35 | 点赞数 |
36 | 是否可用 |
37 | 操作 |
38 |
39 |
40 |
41 | {% for item in topics %}
42 | {% with wechat=item.wechat %}
43 |
44 | {{ item.id}} |
45 | |
46 | {{ item.title}} |
47 | |
48 | {{ wechat.name}} |
49 | {{ item.publish_time}} |
50 | {{ item.read_num }} |
51 | {{ item.like_num }} |
52 | {{ item.available }} |
53 |
54 | {% if wechat.status == 2 %}
55 | 公众号已删除
56 | {% else %}
57 | 删除公众号
58 | {% endif %}
59 | |
60 |
61 | {% endwith %}
62 | {% endfor %}
63 |
64 |
65 |
66 |
69 |
70 |
71 |
72 |
73 | {% endblock %}
74 |
--------------------------------------------------------------------------------
/wechat/templates/wechat/wechat_topics.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 | {% load paginator %}
3 | {% block main-content %}
4 |
5 |
6 |
7 |
8 |
9 | 文章列表
10 |
11 |
60 |
61 | {% endblock %}
--------------------------------------------------------------------------------
/wechat/templatetags/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | __author__ = 'sincat'
--------------------------------------------------------------------------------
/wechat/templatetags/wechat_util.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | __author__ = 'sincat'
3 | from django import template
4 | from django.utils.safestring import mark_safe
5 | register = template.Library()
6 |
7 |
8 | @register.filter
9 | def radio_checked(value, item_value):
10 | if value == item_value:
11 | return mark_safe('checked value="%s"' % item_value)
12 | else:
13 | return mark_safe('value="%s"' % item_value)
14 |
15 |
16 |
--------------------------------------------------------------------------------
/wechat/tests.py:
--------------------------------------------------------------------------------
1 | from django.test import TestCase
2 |
3 | # Create your tests here.
4 |
--------------------------------------------------------------------------------
/wechat/urls.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | __author__ = 'yijingping'
3 | from django.conf.urls import url
4 |
5 | from . import views
6 |
7 | urlpatterns = [
8 | url(r'^$', views.index, name="wechat.index"),
9 | url(r'^add/$', views.add, name="wechat.add"),
10 | url(r'^(?P
\d+)/edit/$', views.edit, name="wechat.edit"),
11 | url(r'^(?P\d+)/delete/$', views.wechat_delete, name="wechat.wechat_delete"),
12 | url(r'^(?P\d+)/topics/$', views.wechat_topics, name="wechat.wechat_topics"),
13 | url(r'^topic/(?P\d+)/$', views.topic_detail, name="wechat.topic_detail"),
14 | url(r'^topic/(?P\d+)/edit/$', views.topic_edit, name="wechat.topic_edit"),
15 | url(r'^topic/$', views.topic_list, name="wechat.topic_list"),
16 | url(r'^topic/available/$', views.topic_available_list, name="wechat.topic_available_list"),
17 |
18 | url(r'^topic/add/$', views.topic_add, name="wechat.topic_add"),
19 | url(r'^search/$', views.search, name="wechat.search"),
20 |
21 |
22 | url(r'^keywords/$', views.keywords_list, name="wechat.keywords_list"),
23 |
24 | url(r'^proxy/(?P\d+)/edit/$', views.proxy_edit, name="wechat.proxy_edit"),
25 | url(r'^proxy/status/$', views.proxy_status, name="wechat.proxy_status"),
26 | ]
27 |
--------------------------------------------------------------------------------
/wechat/util.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | __author__ = 'yijingping'
3 | import time
4 | import urllib2
5 | import requests
6 | from lxml.etree import tostring
7 | from itertools import chain
8 |
9 | ip_check_url = 'http://api.ipify.org'
10 | user_agent = 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:12.0) Gecko/20100101 Firefox/12.0'
11 | socket_timeout = 3
12 |
13 |
14 | # Get real public IP address
15 | def get_real_pip():
16 | req = urllib2.Request(ip_check_url)
17 | req.add_header('User-agent', user_agent)
18 | conn = urllib2.urlopen(req)
19 | page = conn.read()
20 | conn.close()
21 | return page
22 |
23 | # Set global variable containing "real" public IP address
24 | real_pip = get_real_pip()
25 |
26 |
27 | def check_proxy(host, port):
28 | try:
29 | # Build opener
30 | proxy_handler = urllib2.ProxyHandler({'http': '%s:%s' % (host, port)})
31 | opener = urllib2.build_opener(proxy_handler)
32 | opener.addheaders = [('User-agent', user_agent)]
33 | urllib2.install_opener(opener)
34 |
35 | # Build, time, and execute request
36 | req = urllib2.Request(ip_check_url)
37 | time_start = time.time()
38 | conn = urllib2.urlopen(req, timeout=socket_timeout)
39 | time_end = time.time()
40 | detected_pip = conn.read()
41 | conn.close()
42 |
43 | # Calculate request time
44 | time_diff = time_end - time_start
45 |
46 | # Check if proxy is detected
47 | if detected_pip == real_pip:
48 | proxy_detected = False
49 | else:
50 | proxy_detected = True
51 |
52 | # Catch exceptions
53 | except urllib2.HTTPError, e:
54 | print "ERROR: Code ", e.code
55 | return (True, False, 999)
56 | except Exception, detail:
57 | print "ERROR: ", detail
58 | return (True, False, 999)
59 |
60 | # Return False if no exceptions, proxy_detected=True if proxy detected
61 | return (False, proxy_detected, time_diff)
62 |
63 |
64 | def check_wechat(host, port):
65 | try:
66 | time_start = time.time()
67 | # Build opener
68 | proxies = {
69 | 'http': 'http://%s:%s' % (host, port)
70 | }
71 | headers = {
72 | 'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.118 Safari/537.36'
73 | }
74 | rsp = requests.get("http://weixin.sogou.com/weixin",
75 | params={"type": 1, "query": "金融"},
76 | proxies=proxies, headers=headers,
77 | timeout=1
78 | )
79 | rsp.close()
80 | time_end = time.time()
81 |
82 | # Calculate request time
83 | time_diff = time_end - time_start
84 |
85 | #print rsp.content
86 | # Check if proxy is detected
87 | if '金融的相关微信公众号' in rsp.content:
88 | proxy_detected = True
89 | print rsp.content
90 | else:
91 | proxy_detected = False
92 |
93 | # Catch exceptions
94 | except urllib2.HTTPError, e:
95 | print "ERROR: Code ", e.code
96 | return (True, False, 999)
97 | except Exception, detail:
98 | print "ERROR: ", detail
99 | return (True, False, 999)
100 |
101 | # Return False if no exceptions, proxy_detected=True if proxy detected
102 | return (False, proxy_detected, time_diff)
103 |
104 |
105 | def stringify_children(node):
106 | return "".join([x for x in node.itertext()])
107 |
--------------------------------------------------------------------------------
/wechatspider/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bowenpay/wechat-spider/e585a4913962dfa9a817cd7b139505a0c48aecbc/wechatspider/__init__.py
--------------------------------------------------------------------------------
/wechatspider/settings.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | Django settings for wechatspider project.
5 |
6 | Generated by 'django-admin startproject' using Django 1.8.1.
7 |
8 | For more information on this file, see
9 | https://docs.djangoproject.com/en/1.8/topics/settings/
10 |
11 | For the full list of settings and their values, see
12 | https://docs.djangoproject.com/en/1.8/ref/settings/
13 | """
14 |
15 | # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
16 | import os
17 |
18 | BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
19 |
20 |
21 | # Quick-start development settings - unsuitable for production
22 | # See https://docs.djangoproject.com/en/1.8/howto/deployment/checklist/
23 |
24 | # SECURITY WARNING: keep the secret key used in production secret!
25 | SECRET_KEY = ''
26 |
27 | # SECURITY WARNING: don't run with debug turned on in production!
28 | DEBUG = True
29 |
30 | ALLOWED_HOSTS = []
31 |
32 |
33 | # Application definition
34 |
35 | INSTALLED_APPS = (
36 | 'django.contrib.admin',
37 | 'django.contrib.auth',
38 | 'django.contrib.contenttypes',
39 | 'django.contrib.sessions',
40 | 'django.contrib.messages',
41 | 'django.contrib.staticfiles',
42 |
43 | 'wechatspider',
44 | 'wechat',
45 |
46 | )
47 |
48 | MIDDLEWARE_CLASSES = (
49 | 'django.contrib.sessions.middleware.SessionMiddleware',
50 | 'django.middleware.common.CommonMiddleware',
51 | 'django.middleware.csrf.CsrfViewMiddleware',
52 | 'django.contrib.auth.middleware.AuthenticationMiddleware',
53 | 'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
54 | 'django.contrib.messages.middleware.MessageMiddleware',
55 | 'django.middleware.clickjacking.XFrameOptionsMiddleware',
56 | 'django.middleware.security.SecurityMiddleware',
57 | )
58 |
59 | ROOT_URLCONF = 'wechatspider.urls'
60 |
61 | TEMPLATES = [
62 | {
63 | 'BACKEND': 'django.template.backends.django.DjangoTemplates',
64 | 'DIRS': [],
65 | 'APP_DIRS': True,
66 | 'OPTIONS': {
67 | 'context_processors': [
68 | 'django.template.context_processors.debug',
69 | 'django.template.context_processors.request',
70 | 'django.contrib.auth.context_processors.auth',
71 | 'django.contrib.messages.context_processors.messages',
72 | ],
73 | },
74 | },
75 | ]
76 |
77 | WSGI_APPLICATION = 'wechatspider.wsgi.application'
78 |
79 |
80 | # Database
81 | # https://docs.djangoproject.com/en/1.8/ref/settings/#databases
82 |
83 | DATABASES = {
84 | 'default': {
85 | 'ENGINE': 'django.db.backends.sqlite3',
86 | 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
87 | }
88 | }
89 |
90 |
91 | # Internationalization
92 | # https://docs.djangoproject.com/en/1.8/topics/i18n/
93 |
94 | LANGUAGE_CODE = 'zh-hans'
95 |
96 | TIME_ZONE = 'Asia/Shanghai'
97 |
98 | USE_I18N = True
99 |
100 | USE_L10N = True
101 |
102 | USE_TZ = False
103 |
104 |
105 | # Static files (CSS, JavaScript, Images)
106 | # https://docs.djangoproject.com/en/1.8/howto/static-files/
107 |
108 | STATIC_URL = '/static/'
109 | STATIC_ROOT = 'static'
110 | TEMPLATE_DIRS = (
111 | os.path.join(BASE_DIR, 'templates'),
112 | )
113 |
114 | STATICFILES_FINDERS = (
115 | 'django.contrib.staticfiles.finders.FileSystemFinder',
116 | 'django.contrib.staticfiles.finders.AppDirectoriesFinder',
117 | )
118 |
119 |
120 | # messages
121 | from django.contrib import messages
122 | MESSAGE_TAGS = {
123 | messages.ERROR: 'danger'
124 | }
125 |
126 | # logging config
127 | LOGGING = {
128 | 'version': 1,
129 | 'disable_existing_loggers': False,
130 | 'formatters': {
131 | 'verbose': {
132 | 'format': '%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s'
133 | },
134 | 'simple': {
135 | 'format': '%(levelname)s %(message)s'
136 | },
137 | },
138 | 'handlers': {
139 | 'console': {
140 | 'class': 'logging.StreamHandler',
141 | 'formatter': 'verbose'
142 | },
143 | },
144 | 'loggers': {
145 | 'django': {
146 | 'handlers': ['console'],
147 | 'level': os.getenv('DJANGO_LOG_LEVEL', 'INFO'),
148 | },
149 | '': {
150 | 'handlers': ['console'],
151 | 'level': 'DEBUG',
152 | },
153 | },
154 | }
155 |
156 | # redis config
157 | REDIS_OPTIONS = {
158 | 'host': 'localhost',
159 | 'port': 6379,
160 | 'password': '',
161 | 'db': 4
162 | }
163 |
164 | # crawler config
165 | CRAWLER_DEBUG = False
166 | CRAWLER_CONFIG = {
167 | 'scheduler': 'unicrawler:scheduler',
168 | 'downloader': 'unicrawler:downloader',
169 | 'extractor': 'unicrawler:extractor',
170 | 'processor': 'unicrawler:processor',
171 | 'global_limit_speed': 'unicrawler:global_limit_speed',
172 | 'antispider': 'unicrawler:antispider'
173 | }
174 | CRAWLER_GLOBAL_LIMIT_SPEED = 20 * 1000 # 毫秒
175 |
176 | # aliyun oss2
177 | OSS2_ENABLE = False
178 | OSS2_CONFIG = {
179 | "ACCESS_KEY_ID": "",
180 | "ACCESS_KEY_SECRET": "",
181 | "ENDPOINT": "",
182 | "BUCKET_DOMAIN": "oss-cn-beijing.aliyuncs.com",
183 | "BUCKET_NAME": "pythonzone",
184 | "IMAGES_PATH": "images/",
185 | "VIDEOS_PATH": "videos/",
186 | "CDN_DOMAIN": "pystats.bowenpay.com"
187 | }
188 | LOGIN_URL = '/admin/login/'
189 | ## Import local settings
190 | try:
191 | from local_settings import *
192 | except ImportError:
193 | import sys, traceback
194 | sys.stderr.write("Warning: Can't find the file 'local_settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__)
195 | sys.stderr.write("\nFor debugging purposes, the exception was:\n\n")
196 | traceback.print_exc()
197 |
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/css/bootstrap-datepicker.min.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * Datepicker for Bootstrap v1.6.0 (https://github.com/eternicode/bootstrap-datepicker)
3 | *
4 | * Copyright 2012 Stefan Petre
5 | * Improvements by Andrew Rowls
6 | * Licensed under the Apache License v2.0 (http://www.apache.org/licenses/LICENSE-2.0)
7 | */
8 | .datepicker{padding:4px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;direction:ltr}.datepicker-inline{width:220px}.datepicker.datepicker-rtl{direction:rtl}.datepicker.datepicker-rtl table tr td span{float:right}.datepicker-dropdown{top:0;left:0}.datepicker-dropdown:before{content:'';display:inline-block;border-left:7px solid transparent;border-right:7px solid transparent;border-bottom:7px solid #999;border-top:0;border-bottom-color:rgba(0,0,0,.2);position:absolute}.datepicker-dropdown:after{content:'';display:inline-block;border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid #fff;border-top:0;position:absolute}.datepicker-dropdown.datepicker-orient-left:before{left:6px}.datepicker-dropdown.datepicker-orient-left:after{left:7px}.datepicker-dropdown.datepicker-orient-right:before{right:6px}.datepicker-dropdown.datepicker-orient-right:after{right:7px}.datepicker-dropdown.datepicker-orient-bottom:before{top:-7px}.datepicker-dropdown.datepicker-orient-bottom:after{top:-6px}.datepicker-dropdown.datepicker-orient-top:before{bottom:-7px;border-bottom:0;border-top:7px solid #999}.datepicker-dropdown.datepicker-orient-top:after{bottom:-6px;border-bottom:0;border-top:6px solid #fff}.datepicker>div{display:none}.datepicker table{margin:0;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.datepicker td,.datepicker th{text-align:center;width:20px;height:20px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;border:none}.table-striped .datepicker table tr td,.table-striped .datepicker table tr th{background-color:transparent}.datepicker table tr td.day.focused,.datepicker table tr td.day:hover{background:#eee;cursor:pointer}.datepicker table tr td.new,.datepicker table tr td.old{color:#999}.datepicker table tr td.disabled,.datepicker table tr td.disabled:hover{background:0 0;color:#999;cursor:default}.datepicker table tr td.highlighted{background:#d9edf7;border-radius:0}.datepicker table tr td.today,.datepicker table tr td.today.disabled,.datepicker table tr td.today.disabled:hover,.datepicker table tr td.today:hover{background-color:#fde19a;background-image:-moz-linear-gradient(to bottom,#fdd49a,#fdf59a);background-image:-ms-linear-gradient(to bottom,#fdd49a,#fdf59a);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fdd49a),to(#fdf59a));background-image:-webkit-linear-gradient(to bottom,#fdd49a,#fdf59a);background-image:-o-linear-gradient(to bottom,#fdd49a,#fdf59a);background-image:linear-gradient(to bottom,#fdd49a,#fdf59a);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fdd49a', endColorstr='#fdf59a', GradientType=0);border-color:#fdf59a #fdf59a #fbed50;border-color:rgba(0,0,0,.1) rgba(0,0,0,.1) rgba(0,0,0,.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);color:#000}.datepicker table tr td.today.active,.datepicker table tr td.today.disabled,.datepicker table tr td.today.disabled.active,.datepicker table tr td.today.disabled.disabled,.datepicker table tr td.today.disabled:active,.datepicker table tr td.today.disabled:hover,.datepicker table tr td.today.disabled:hover.active,.datepicker table tr td.today.disabled:hover.disabled,.datepicker table tr td.today.disabled:hover:active,.datepicker table tr td.today.disabled:hover:hover,.datepicker table tr td.today.disabled:hover[disabled],.datepicker table tr td.today.disabled[disabled],.datepicker table tr td.today:active,.datepicker table tr td.today:hover,.datepicker table tr td.today:hover.active,.datepicker table tr td.today:hover.disabled,.datepicker table tr td.today:hover:active,.datepicker table tr td.today:hover:hover,.datepicker table tr td.today:hover[disabled],.datepicker table tr td.today[disabled]{background-color:#fdf59a}.datepicker table tr td.today.active,.datepicker table tr td.today.disabled.active,.datepicker table tr td.today.disabled:active,.datepicker table tr td.today.disabled:hover.active,.datepicker table tr td.today.disabled:hover:active,.datepicker table tr td.today:active,.datepicker table tr td.today:hover.active,.datepicker table tr td.today:hover:active{background-color:#fbf069\9}.datepicker table tr td.today:hover:hover{color:#000}.datepicker table tr td.today.active:hover{color:#fff}.datepicker table tr td.range,.datepicker table tr td.range.disabled,.datepicker table tr td.range.disabled:hover,.datepicker table tr td.range:hover{background:#eee;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.datepicker table tr td.range.today,.datepicker table tr td.range.today.disabled,.datepicker table tr td.range.today.disabled:hover,.datepicker table tr td.range.today:hover{background-color:#f3d17a;background-image:-moz-linear-gradient(to bottom,#f3c17a,#f3e97a);background-image:-ms-linear-gradient(to bottom,#f3c17a,#f3e97a);background-image:-webkit-gradient(linear,0 0,0 100%,from(#f3c17a),to(#f3e97a));background-image:-webkit-linear-gradient(to bottom,#f3c17a,#f3e97a);background-image:-o-linear-gradient(to bottom,#f3c17a,#f3e97a);background-image:linear-gradient(to bottom,#f3c17a,#f3e97a);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#f3c17a', endColorstr='#f3e97a', GradientType=0);border-color:#f3e97a #f3e97a #edde34;border-color:rgba(0,0,0,.1) rgba(0,0,0,.1) rgba(0,0,0,.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.datepicker table tr td.range.today.active,.datepicker table tr td.range.today.disabled,.datepicker table tr td.range.today.disabled.active,.datepicker table tr td.range.today.disabled.disabled,.datepicker table tr td.range.today.disabled:active,.datepicker table tr td.range.today.disabled:hover,.datepicker table tr td.range.today.disabled:hover.active,.datepicker table tr td.range.today.disabled:hover.disabled,.datepicker table tr td.range.today.disabled:hover:active,.datepicker table tr td.range.today.disabled:hover:hover,.datepicker table tr td.range.today.disabled:hover[disabled],.datepicker table tr td.range.today.disabled[disabled],.datepicker table tr td.range.today:active,.datepicker table tr td.range.today:hover,.datepicker table tr td.range.today:hover.active,.datepicker table tr td.range.today:hover.disabled,.datepicker table tr td.range.today:hover:active,.datepicker table tr td.range.today:hover:hover,.datepicker table tr td.range.today:hover[disabled],.datepicker table tr td.range.today[disabled]{background-color:#f3e97a}.datepicker table tr td.range.today.active,.datepicker table tr td.range.today.disabled.active,.datepicker table tr td.range.today.disabled:active,.datepicker table tr td.range.today.disabled:hover.active,.datepicker table tr td.range.today.disabled:hover:active,.datepicker table tr td.range.today:active,.datepicker table tr td.range.today:hover.active,.datepicker table tr td.range.today:hover:active{background-color:#efe24b\9}.datepicker table tr td.selected,.datepicker table tr td.selected.disabled,.datepicker table tr td.selected.disabled:hover,.datepicker table tr td.selected:hover{background-color:#9e9e9e;background-image:-moz-linear-gradient(to bottom,#b3b3b3,grey);background-image:-ms-linear-gradient(to bottom,#b3b3b3,grey);background-image:-webkit-gradient(linear,0 0,0 100%,from(#b3b3b3),to(grey));background-image:-webkit-linear-gradient(to bottom,#b3b3b3,grey);background-image:-o-linear-gradient(to bottom,#b3b3b3,grey);background-image:linear-gradient(to bottom,#b3b3b3,grey);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#b3b3b3', endColorstr='#808080', GradientType=0);border-color:grey grey #595959;border-color:rgba(0,0,0,.1) rgba(0,0,0,.1) rgba(0,0,0,.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,.25)}.datepicker table tr td.selected.active,.datepicker table tr td.selected.disabled,.datepicker table tr td.selected.disabled.active,.datepicker table tr td.selected.disabled.disabled,.datepicker table tr td.selected.disabled:active,.datepicker table tr td.selected.disabled:hover,.datepicker table tr td.selected.disabled:hover.active,.datepicker table tr td.selected.disabled:hover.disabled,.datepicker table tr td.selected.disabled:hover:active,.datepicker table tr td.selected.disabled:hover:hover,.datepicker table tr td.selected.disabled:hover[disabled],.datepicker table tr td.selected.disabled[disabled],.datepicker table tr td.selected:active,.datepicker table tr td.selected:hover,.datepicker table tr td.selected:hover.active,.datepicker table tr td.selected:hover.disabled,.datepicker table tr td.selected:hover:active,.datepicker table tr td.selected:hover:hover,.datepicker table tr td.selected:hover[disabled],.datepicker table tr td.selected[disabled]{background-color:grey}.datepicker table tr td.selected.active,.datepicker table tr td.selected.disabled.active,.datepicker table tr td.selected.disabled:active,.datepicker table tr td.selected.disabled:hover.active,.datepicker table tr td.selected.disabled:hover:active,.datepicker table tr td.selected:active,.datepicker table tr td.selected:hover.active,.datepicker table tr td.selected:hover:active{background-color:#666\9}.datepicker table tr td.active,.datepicker table tr td.active.disabled,.datepicker table tr td.active.disabled:hover,.datepicker table tr td.active:hover{background-color:#006dcc;background-image:-moz-linear-gradient(to bottom,#08c,#04c);background-image:-ms-linear-gradient(to bottom,#08c,#04c);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#04c));background-image:-webkit-linear-gradient(to bottom,#08c,#04c);background-image:-o-linear-gradient(to bottom,#08c,#04c);background-image:linear-gradient(to bottom,#08c,#04c);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0);border-color:#04c #04c #002a80;border-color:rgba(0,0,0,.1) rgba(0,0,0,.1) rgba(0,0,0,.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,.25)}.datepicker table tr td.active.active,.datepicker table tr td.active.disabled,.datepicker table tr td.active.disabled.active,.datepicker table tr td.active.disabled.disabled,.datepicker table tr td.active.disabled:active,.datepicker table tr td.active.disabled:hover,.datepicker table tr td.active.disabled:hover.active,.datepicker table tr td.active.disabled:hover.disabled,.datepicker table tr td.active.disabled:hover:active,.datepicker table tr td.active.disabled:hover:hover,.datepicker table tr td.active.disabled:hover[disabled],.datepicker table tr td.active.disabled[disabled],.datepicker table tr td.active:active,.datepicker table tr td.active:hover,.datepicker table tr td.active:hover.active,.datepicker table tr td.active:hover.disabled,.datepicker table tr td.active:hover:active,.datepicker table tr td.active:hover:hover,.datepicker table tr td.active:hover[disabled],.datepicker table tr td.active[disabled]{background-color:#04c}.datepicker table tr td.active.active,.datepicker table tr td.active.disabled.active,.datepicker table tr td.active.disabled:active,.datepicker table tr td.active.disabled:hover.active,.datepicker table tr td.active.disabled:hover:active,.datepicker table tr td.active:active,.datepicker table tr td.active:hover.active,.datepicker table tr td.active:hover:active{background-color:#039\9}.datepicker table tr td span{display:block;width:23%;height:54px;line-height:54px;float:left;margin:1%;cursor:pointer;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.datepicker table tr td span.focused,.datepicker table tr td span:hover{background:#eee}.datepicker table tr td span.disabled,.datepicker table tr td span.disabled:hover{background:0 0;color:#999;cursor:default}.datepicker table tr td span.active,.datepicker table tr td span.active.disabled,.datepicker table tr td span.active.disabled:hover,.datepicker table tr td span.active:hover{background-color:#006dcc;background-image:-moz-linear-gradient(to bottom,#08c,#04c);background-image:-ms-linear-gradient(to bottom,#08c,#04c);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#04c));background-image:-webkit-linear-gradient(to bottom,#08c,#04c);background-image:-o-linear-gradient(to bottom,#08c,#04c);background-image:linear-gradient(to bottom,#08c,#04c);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0);border-color:#04c #04c #002a80;border-color:rgba(0,0,0,.1) rgba(0,0,0,.1) rgba(0,0,0,.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,.25)}.datepicker table tr td span.active.active,.datepicker table tr td span.active.disabled,.datepicker table tr td span.active.disabled.active,.datepicker table tr td span.active.disabled.disabled,.datepicker table tr td span.active.disabled:active,.datepicker table tr td span.active.disabled:hover,.datepicker table tr td span.active.disabled:hover.active,.datepicker table tr td span.active.disabled:hover.disabled,.datepicker table tr td span.active.disabled:hover:active,.datepicker table tr td span.active.disabled:hover:hover,.datepicker table tr td span.active.disabled:hover[disabled],.datepicker table tr td span.active.disabled[disabled],.datepicker table tr td span.active:active,.datepicker table tr td span.active:hover,.datepicker table tr td span.active:hover.active,.datepicker table tr td span.active:hover.disabled,.datepicker table tr td span.active:hover:active,.datepicker table tr td span.active:hover:hover,.datepicker table tr td span.active:hover[disabled],.datepicker table tr td span.active[disabled]{background-color:#04c}.datepicker table tr td span.active.active,.datepicker table tr td span.active.disabled.active,.datepicker table tr td span.active.disabled:active,.datepicker table tr td span.active.disabled:hover.active,.datepicker table tr td span.active.disabled:hover:active,.datepicker table tr td span.active:active,.datepicker table tr td span.active:hover.active,.datepicker table tr td span.active:hover:active{background-color:#039\9}.datepicker table tr td span.new,.datepicker table tr td span.old{color:#999}.datepicker .datepicker-switch{width:145px}.datepicker .datepicker-switch,.datepicker .next,.datepicker .prev,.datepicker tfoot tr th{cursor:pointer}.datepicker .datepicker-switch:hover,.datepicker .next:hover,.datepicker .prev:hover,.datepicker tfoot tr th:hover{background:#eee}.datepicker .cw{font-size:10px;width:12px;padding:0 2px 0 5px;vertical-align:middle}.input-append.date .add-on,.input-prepend.date .add-on{cursor:pointer}.input-append.date .add-on i,.input-prepend.date .add-on i{margin-top:3px}.input-daterange input{text-align:center}.input-daterange input:first-child{-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px}.input-daterange input:last-child{-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0}.input-daterange .add-on{display:inline-block;width:auto;min-width:16px;height:18px;padding:4px 5px;font-weight:400;line-height:18px;text-align:center;text-shadow:0 1px 0 #fff;vertical-align:middle;background-color:#eee;border:1px solid #ccc;margin-left:-5px;margin-right:-5px}
9 | /*# sourceMappingURL=bootstrap-datepicker.min.css.map */
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/css/bootstrap-datepicker.min.css.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["less/datepicker.less","build/build.less"],"names":[],"mappings":"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"}
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/css/bootstrap-datepicker.standalone.min.css.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["less/datepicker.less","build/build.less","build/build_standalone.less"],"names":[],"mappings":"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"}
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/css/bootstrap-datepicker3.min.css.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["less/datepicker3.less","build/build3.less"],"names":[],"mappings":"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"}
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/css/bootstrap-datepicker3.standalone.min.css.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["less/datepicker3.less","build/build3.less","build/build_standalone3.less"],"names":[],"mappings":"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"}
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.ar.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.ar={days:["الأحد","الاثنين","الثلاثاء","الأربعاء","الخميس","الجمعة","السبت","الأحد"],daysShort:["أحد","اثنين","ثلاثاء","أربعاء","خميس","جمعة","سبت","أحد"],daysMin:["ح","ن","ث","ع","خ","ج","س","ح"],months:["يناير","فبراير","مارس","أبريل","مايو","يونيو","يوليو","أغسطس","سبتمبر","أكتوبر","نوفمبر","ديسمبر"],monthsShort:["يناير","فبراير","مارس","أبريل","مايو","يونيو","يوليو","أغسطس","سبتمبر","أكتوبر","نوفمبر","ديسمبر"],today:"هذا اليوم",rtl:!0}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.az.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.az={days:["Bazar","Bazar ertəsi","Çərşənbə axşamı","Çərşənbə","Cümə axşamı","Cümə","Şənbə"],daysShort:["B.","B.e","Ç.a","Ç.","C.a","C.","Ş."],daysMin:["B.","B.e","Ç.a","Ç.","C.a","C.","Ş."],months:["Yanvar","Fevral","Mart","Aprel","May","İyun","İyul","Avqust","Sentyabr","Oktyabr","Noyabr","Dekabr"],monthsShort:["Yan","Fev","Mar","Apr","May","İyun","İyul","Avq","Sen","Okt","Noy","Dek"],today:"Bu gün",weekStart:1}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.bg.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.bg={days:["Неделя","Понеделник","Вторник","Сряда","Четвъртък","Петък","Събота"],daysShort:["Нед","Пон","Вто","Сря","Чет","Пет","Съб"],daysMin:["Н","П","В","С","Ч","П","С"],months:["Януари","Февруари","Март","Април","Май","Юни","Юли","Август","Септември","Октомври","Ноември","Декември"],monthsShort:["Ян","Фев","Мар","Апр","Май","Юни","Юли","Авг","Сеп","Окт","Ное","Дек"],today:"днес"}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.bs.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.bs={days:["Nedjelja","Ponedjeljak","Utorak","Srijeda","Četvrtak","Petak","Subota"],daysShort:["Ned","Pon","Uto","Sri","Čet","Pet","Sub"],daysMin:["N","Po","U","Sr","Č","Pe","Su"],months:["Januar","Februar","Mart","April","Maj","Juni","Juli","August","Septembar","Oktobar","Novembar","Decembar"],monthsShort:["Jan","Feb","Mar","Apr","Maj","Jun","Jul","Aug","Sep","Okt","Nov","Dec"],today:"Danas",weekStart:1,format:"dd.mm.yyyy"}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.ca.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.ca={days:["Diumenge","Dilluns","Dimarts","Dimecres","Dijous","Divendres","Dissabte"],daysShort:["Diu","Dil","Dmt","Dmc","Dij","Div","Dis"],daysMin:["dg","dl","dt","dc","dj","dv","ds"],months:["Gener","Febrer","Març","Abril","Maig","Juny","Juliol","Agost","Setembre","Octubre","Novembre","Desembre"],monthsShort:["Gen","Feb","Mar","Abr","Mai","Jun","Jul","Ago","Set","Oct","Nov","Des"],today:"Avui",monthsTitle:"Mesos",clear:"Esborrar",weekStart:1,format:"dd/mm/yyyy"}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.cs.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.cs={days:["Neděle","Pondělí","Úterý","Středa","Čtvrtek","Pátek","Sobota"],daysShort:["Ned","Pon","Úte","Stř","Čtv","Pát","Sob"],daysMin:["Ne","Po","Út","St","Čt","Pá","So"],months:["Leden","Únor","Březen","Duben","Květen","Červen","Červenec","Srpen","Září","Říjen","Listopad","Prosinec"],monthsShort:["Led","Úno","Bře","Dub","Kvě","Čer","Čnc","Srp","Zář","Říj","Lis","Pro"],today:"Dnes",clear:"Vymazat",weekStart:1,format:"dd.m.yyyy"}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.cy.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.cy={days:["Sul","Llun","Mawrth","Mercher","Iau","Gwener","Sadwrn"],daysShort:["Sul","Llu","Maw","Mer","Iau","Gwe","Sad"],daysMin:["Su","Ll","Ma","Me","Ia","Gwe","Sa"],months:["Ionawr","Chewfror","Mawrth","Ebrill","Mai","Mehefin","Gorfennaf","Awst","Medi","Hydref","Tachwedd","Rhagfyr"],monthsShort:["Ion","Chw","Maw","Ebr","Mai","Meh","Gor","Aws","Med","Hyd","Tach","Rha"],today:"Heddiw"}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.da.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.da={days:["søndag","mandag","tirsdag","onsdag","torsdag","fredag","lørdag"],daysShort:["søn","man","tir","ons","tor","fre","lør"],daysMin:["sø","ma","ti","on","to","fr","lø"],months:["januar","februar","marts","april","maj","juni","juli","august","september","oktober","november","december"],monthsShort:["jan","feb","mar","apr","maj","jun","jul","aug","sep","okt","nov","dec"],today:"I Dag",clear:"Nulstil"}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.de.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.de={days:["Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag"],daysShort:["Son","Mon","Die","Mit","Don","Fre","Sam"],daysMin:["So","Mo","Di","Mi","Do","Fr","Sa"],months:["Januar","Februar","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember"],monthsShort:["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],today:"Heute",monthsTitle:"Monate",clear:"Löschen",weekStart:1,format:"dd.mm.yyyy"}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.el.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.el={days:["Κυριακή","Δευτέρα","Τρίτη","Τετάρτη","Πέμπτη","Παρασκευή","Σάββατο"],daysShort:["Κυρ","Δευ","Τρι","Τετ","Πεμ","Παρ","Σαβ"],daysMin:["Κυ","Δε","Τρ","Τε","Πε","Πα","Σα"],months:["Ιανουάριος","Φεβρουάριος","Μάρτιος","Απρίλιος","Μάιος","Ιούνιος","Ιούλιος","Αύγουστος","Σεπτέμβριος","Οκτώβριος","Νοέμβριος","Δεκέμβριος"],monthsShort:["Ιαν","Φεβ","Μαρ","Απρ","Μάι","Ιουν","Ιουλ","Αυγ","Σεπ","Οκτ","Νοε","Δεκ"],today:"Σήμερα",clear:"Καθαρισμός",weekStart:1,format:"d/m/yyyy"}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.en-AU.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates["en-AU"]={days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],daysShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],daysMin:["Su","Mo","Tu","We","Th","Fr","Sa"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],monthsShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],today:"Today",monthsTitle:"Months",clear:"Clear",weekStart:1,format:"d/mm/yyyy"}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.en-GB.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates["en-GB"]={days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],daysShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],daysMin:["Su","Mo","Tu","We","Th","Fr","Sa"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],monthsShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],today:"Today",monthsTitle:"Months",clear:"Clear",weekStart:1,format:"dd/mm/yyyy"}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.eo.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.eo={days:["dimanĉo","lundo","mardo","merkredo","ĵaŭdo","vendredo","sabato"],daysShort:["dim.","lun.","mar.","mer.","ĵaŭ.","ven.","sam."],daysMin:["d","l","ma","me","ĵ","v","s"],months:["januaro","februaro","marto","aprilo","majo","junio","julio","aŭgusto","septembro","oktobro","novembro","decembro"],monthsShort:["jan.","feb.","mar.","apr.","majo","jun.","jul.","aŭg.","sep.","okt.","nov.","dec."],today:"Hodiaŭ",clear:"Nuligi",weekStart:1,format:"yyyy-mm-dd"}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.es.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.es={days:["Domingo","Lunes","Martes","Miércoles","Jueves","Viernes","Sábado"],daysShort:["Dom","Lun","Mar","Mié","Jue","Vie","Sáb"],daysMin:["Do","Lu","Ma","Mi","Ju","Vi","Sa"],months:["Enero","Febrero","Marzo","Abril","Mayo","Junio","Julio","Agosto","Septiembre","Octubre","Noviembre","Diciembre"],monthsShort:["Ene","Feb","Mar","Abr","May","Jun","Jul","Ago","Sep","Oct","Nov","Dic"],today:"Hoy",monthsTitle:"Meses",clear:"Borrar",weekStart:1,format:"dd/mm/yyyy"}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.et.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.et={days:["Pühapäev","Esmaspäev","Teisipäev","Kolmapäev","Neljapäev","Reede","Laupäev"],daysShort:["Pühap","Esmasp","Teisip","Kolmap","Neljap","Reede","Laup"],daysMin:["P","E","T","K","N","R","L"],months:["Jaanuar","Veebruar","Märts","Aprill","Mai","Juuni","Juuli","August","September","Oktoober","November","Detsember"],monthsShort:["Jaan","Veebr","Märts","Apr","Mai","Juuni","Juuli","Aug","Sept","Okt","Nov","Dets"],today:"Täna",clear:"Tühjenda",weekStart:1,format:"dd.mm.yyyy"}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.eu.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.eu={days:["Igandea","Astelehena","Asteartea","Asteazkena","Osteguna","Ostirala","Larunbata"],daysShort:["Ig","Al","Ar","Az","Og","Ol","Lr"],daysMin:["Ig","Al","Ar","Az","Og","Ol","Lr"],months:["Urtarrila","Otsaila","Martxoa","Apirila","Maiatza","Ekaina","Uztaila","Abuztua","Iraila","Urria","Azaroa","Abendua"],monthsShort:["Urt","Ots","Mar","Api","Mai","Eka","Uzt","Abu","Ira","Urr","Aza","Abe"],today:"Gaur"}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.fa.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.fa={days:["یکشنبه","دوشنبه","سهشنبه","چهارشنبه","پنجشنبه","جمعه","شنبه","یکشنبه"],daysShort:["یک","دو","سه","چهار","پنج","جمعه","شنبه","یک"],daysMin:["ی","د","س","چ","پ","ج","ش","ی"],months:["ژانویه","فوریه","مارس","آوریل","مه","ژوئن","ژوئیه","اوت","سپتامبر","اکتبر","نوامبر","دسامبر"],monthsShort:["ژان","فور","مار","آور","مه","ژون","ژوی","اوت","سپت","اکت","نوا","دسا"],today:"امروز",clear:"پاک کن",weekStart:1,format:"yyyy/mm/dd"}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.fi.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.fi={days:["sunnuntai","maanantai","tiistai","keskiviikko","torstai","perjantai","lauantai"],daysShort:["sun","maa","tii","kes","tor","per","lau"],daysMin:["su","ma","ti","ke","to","pe","la"],months:["tammikuu","helmikuu","maaliskuu","huhtikuu","toukokuu","kesäkuu","heinäkuu","elokuu","syyskuu","lokakuu","marraskuu","joulukuu"],monthsShort:["tam","hel","maa","huh","tou","kes","hei","elo","syy","lok","mar","jou"],today:"tänään",clear:"Tyhjennä",weekStart:1,format:"d.m.yyyy"}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.fo.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.fo={days:["Sunnudagur","Mánadagur","Týsdagur","Mikudagur","Hósdagur","Fríggjadagur","Leygardagur"],daysShort:["Sun","Mán","Týs","Mik","Hós","Frí","Ley"],daysMin:["Su","Má","Tý","Mi","Hó","Fr","Le"],months:["Januar","Februar","Marts","Apríl","Mei","Juni","Juli","August","Septembur","Oktobur","Novembur","Desembur"],monthsShort:["Jan","Feb","Mar","Apr","Mei","Jun","Jul","Aug","Sep","Okt","Nov","Des"],today:"Í Dag",clear:"Reinsa"}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.fr-CH.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.fr={days:["Dimanche","Lundi","Mardi","Mercredi","Jeudi","Vendredi","Samedi"],daysShort:["Dim","Lun","Mar","Mer","Jeu","Ven","Sam"],daysMin:["D","L","Ma","Me","J","V","S"],months:["Janvier","Février","Mars","Avril","Mai","Juin","Juillet","Août","Septembre","Octobre","Novembre","Décembre"],monthsShort:["Jan","Fév","Mar","Avr","Mai","Jui","Jul","Aou","Sep","Oct","Nov","Déc"],today:"Aujourd'hui",monthsTitle:"Mois",clear:"Effacer",weekStart:1,format:"dd.mm.yyyy"}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.fr.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.fr={days:["dimanche","lundi","mardi","mercredi","jeudi","vendredi","samedi"],daysShort:["dim.","lun.","mar.","mer.","jeu.","ven.","sam."],daysMin:["d","l","ma","me","j","v","s"],months:["janvier","février","mars","avril","mai","juin","juillet","août","septembre","octobre","novembre","décembre"],monthsShort:["janv.","févr.","mars","avril","mai","juin","juil.","août","sept.","oct.","nov.","déc."],today:"Aujourd'hui",monthsTitle:"Mois",clear:"Effacer",weekStart:1,format:"dd/mm/yyyy"}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.gl.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.gl={days:["Domingo","Luns","Martes","Mércores","Xoves","Venres","Sábado"],daysShort:["Dom","Lun","Mar","Mér","Xov","Ven","Sáb"],daysMin:["Do","Lu","Ma","Me","Xo","Ve","Sa"],months:["Xaneiro","Febreiro","Marzo","Abril","Maio","Xuño","Xullo","Agosto","Setembro","Outubro","Novembro","Decembro"],monthsShort:["Xan","Feb","Mar","Abr","Mai","Xun","Xul","Ago","Sep","Out","Nov","Dec"],today:"Hoxe",clear:"Limpar",weekStart:1,format:"dd/mm/yyyy"}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.he.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.he={days:["ראשון","שני","שלישי","רביעי","חמישי","שישי","שבת","ראשון"],daysShort:["א","ב","ג","ד","ה","ו","ש","א"],daysMin:["א","ב","ג","ד","ה","ו","ש","א"],months:["ינואר","פברואר","מרץ","אפריל","מאי","יוני","יולי","אוגוסט","ספטמבר","אוקטובר","נובמבר","דצמבר"],monthsShort:["ינו","פבר","מרץ","אפר","מאי","יונ","יול","אוג","ספט","אוק","נוב","דצמ"],today:"היום",rtl:!0}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.hr.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.hr={days:["Nedjelja","Ponedjeljak","Utorak","Srijeda","Četvrtak","Petak","Subota"],daysShort:["Ned","Pon","Uto","Sri","Čet","Pet","Sub"],daysMin:["Ne","Po","Ut","Sr","Če","Pe","Su"],months:["Siječanj","Veljača","Ožujak","Travanj","Svibanj","Lipanj","Srpanj","Kolovoz","Rujan","Listopad","Studeni","Prosinac"],monthsShort:["Sij","Velj","Ožu","Tra","Svi","Lip","Srp","Kol","Ruj","Lis","Stu","Pro"],today:"Danas"}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.hu.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.hu={days:["vasárnap","hétfő","kedd","szerda","csütörtök","péntek","szombat"],daysShort:["vas","hét","ked","sze","csü","pén","szo"],daysMin:["V","H","K","Sze","Cs","P","Szo"],months:["január","február","március","április","május","június","július","augusztus","szeptember","október","november","december"],monthsShort:["jan","feb","már","ápr","máj","jún","júl","aug","sze","okt","nov","dec"],today:"ma",weekStart:1,clear:"töröl",titleFormat:"yyyy. MM",format:"yyyy.mm.dd"}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.hy.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.hy={days:["Կիրակի","Երկուշաբթի","Երեքշաբթի","Չորեքշաբթի","Հինգշաբթի","Ուրբաթ","Շաբաթ"],daysShort:["Կրկ","Երկ","Երք","Չրք","Հնգ","Ուր","Շբթ"],daysMin:["Կրկ","Երկ","Երք","Չրք","Հնգ","Ուր","Շբթ"],months:["Հունվար","Փետրվար","Մարտ","Ապրիլ","Մայիս","Հունիս","Հուլիս","Օգոստոս","Սեպտեմբեր","Հոկտեմբեր","Նոյեմբեր","Դեկտեմբեր"],monthsShort:["Հուն","Փետ","Մար","Ապր","Մայ","Հնս","Հլս","Օգս","Սեպ","Հոկ","Նմբ","Դեկ"],today:"Այսօր",clear:"Ջնջել",format:"dd.mm.yyyy",weekStart:1}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.id.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.id={days:["Minggu","Senin","Selasa","Rabu","Kamis","Jumat","Sabtu"],daysShort:["Mgu","Sen","Sel","Rab","Kam","Jum","Sab"],daysMin:["Mg","Sn","Sl","Ra","Ka","Ju","Sa"],months:["Januari","Februari","Maret","April","Mei","Juni","Juli","Agustus","September","Oktober","November","Desember"],monthsShort:["Jan","Feb","Mar","Apr","Mei","Jun","Jul","Ags","Sep","Okt","Nov","Des"],today:"Hari Ini",clear:"Kosongkan"}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.is.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.is={days:["Sunnudagur","Mánudagur","Þriðjudagur","Miðvikudagur","Fimmtudagur","Föstudagur","Laugardagur"],daysShort:["Sun","Mán","Þri","Mið","Fim","Fös","Lau"],daysMin:["Su","Má","Þr","Mi","Fi","Fö","La"],months:["Janúar","Febrúar","Mars","Apríl","Maí","Júní","Júlí","Ágúst","September","Október","Nóvember","Desember"],monthsShort:["Jan","Feb","Mar","Apr","Maí","Jún","Júl","Ágú","Sep","Okt","Nóv","Des"],today:"Í Dag"}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.it-CH.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.it={days:["Domenica","Lunedì","Martedì","Mercoledì","Giovedì","Venerdì","Sabato"],daysShort:["Dom","Lun","Mar","Mer","Gio","Ven","Sab"],daysMin:["Do","Lu","Ma","Me","Gi","Ve","Sa"],months:["Gennaio","Febbraio","Marzo","Aprile","Maggio","Giugno","Luglio","Agosto","Settembre","Ottobre","Novembre","Dicembre"],monthsShort:["Gen","Feb","Mar","Apr","Mag","Giu","Lug","Ago","Set","Ott","Nov","Dic"],today:"Oggi",clear:"Cancella",weekStart:1,format:"dd.mm.yyyy"}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.it.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.it={days:["Domenica","Lunedì","Martedì","Mercoledì","Giovedì","Venerdì","Sabato"],daysShort:["Dom","Lun","Mar","Mer","Gio","Ven","Sab"],daysMin:["Do","Lu","Ma","Me","Gi","Ve","Sa"],months:["Gennaio","Febbraio","Marzo","Aprile","Maggio","Giugno","Luglio","Agosto","Settembre","Ottobre","Novembre","Dicembre"],monthsShort:["Gen","Feb","Mar","Apr","Mag","Giu","Lug","Ago","Set","Ott","Nov","Dic"],today:"Oggi",monthsTitle:"Mesi",clear:"Cancella",weekStart:1,format:"dd/mm/yyyy"}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.ja.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.ja={days:["日曜","月曜","火曜","水曜","木曜","金曜","土曜"],daysShort:["日","月","火","水","木","金","土"],daysMin:["日","月","火","水","木","金","土"],months:["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],monthsShort:["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],today:"今日",format:"yyyy/mm/dd",titleFormat:"yyyy年mm月",clear:"クリア"}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.ka.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.ka={days:["კვირა","ორშაბათი","სამშაბათი","ოთხშაბათი","ხუთშაბათი","პარასკევი","შაბათი"],daysShort:["კვი","ორშ","სამ","ოთხ","ხუთ","პარ","შაბ"],daysMin:["კვ","ორ","სა","ოთ","ხუ","პა","შა"],months:["იანვარი","თებერვალი","მარტი","აპრილი","მაისი","ივნისი","ივლისი","აგვისტო","სექტემბერი","ოქტომები","ნოემბერი","დეკემბერი"],monthsShort:["იან","თებ","მარ","აპრ","მაი","ივნ","ივლ","აგვ","სექ","ოქტ","ნოე","დეკ"],today:"დღეს",clear:"გასუფთავება",weekStart:1,format:"dd.mm.yyyy"}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.kh.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.kh={days:["អាទិត្យ","ចន្ទ","អង្គារ","ពុធ","ព្រហស្បតិ៍","សុក្រ","សៅរ៍","អាទិត្យ"],daysShort:["អា.ទិ","ចន្ទ","អង្គារ","ពុធ","ព្រ.ហ","សុក្រ","សៅរ៍","អា.ទិ"],daysMin:["អា.ទិ","ចន្ទ","អង្គារ","ពុធ","ព្រ.ហ","សុក្រ","សៅរ៍","អា.ទិ"],months:["មករា","កុម្ភះ","មិនា","មេសា","ឧសភា","មិថុនា","កក្កដា","សីហា","កញ្ញា","តុលា","វិច្ឆិកា","ធ្នូ"],monthsShort:["មករា","កុម្ភះ","មិនា","មេសា","ឧសភា","មិថុនា","កក្កដា","សីហា","កញ្ញា","តុលា","វិច្ឆិកា","ធ្នូ"],today:"ថ្ងៃនេះ",clear:"សំអាត"}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.kk.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.kk={days:["Жексенбі","Дүйсенбі","Сейсенбі","Сәрсенбі","Бейсенбі","Жұма","Сенбі"],daysShort:["Жек","Дүй","Сей","Сәр","Бей","Жұм","Сен"],daysMin:["Жк","Дс","Сс","Ср","Бс","Жм","Сн"],months:["Қаңтар","Ақпан","Наурыз","Сәуір","Мамыр","Маусым","Шілде","Тамыз","Қыркүйек","Қазан","Қараша","Желтоқсан"],monthsShort:["Қаң","Ақп","Нау","Сәу","Мамыр","Мау","Шлд","Тмз","Қыр","Қзн","Қар","Жел"],today:"Бүгін",weekStart:1}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.ko.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.ko={days:["일요일","월요일","화요일","수요일","목요일","금요일","토요일"],daysShort:["일","월","화","수","목","금","토"],daysMin:["일","월","화","수","목","금","토"],months:["1월","2월","3월","4월","5월","6월","7월","8월","9월","10월","11월","12월"],monthsShort:["1월","2월","3월","4월","5월","6월","7월","8월","9월","10월","11월","12월"],today:"오늘",clear:"삭제",format:"yyyy-mm-dd",titleFormat:"yyyy년mm월",weekStart:0}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.kr.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.kr={days:["일요일","월요일","화요일","수요일","목요일","금요일","토요일"],daysShort:["일","월","화","수","목","금","토"],daysMin:["일","월","화","수","목","금","토"],months:["1월","2월","3월","4월","5월","6월","7월","8월","9월","10월","11월","12월"],monthsShort:["1월","2월","3월","4월","5월","6월","7월","8월","9월","10월","11월","12월"]}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.lt.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.lt={days:["Sekmadienis","Pirmadienis","Antradienis","Trečiadienis","Ketvirtadienis","Penktadienis","Šeštadienis"],daysShort:["S","Pr","A","T","K","Pn","Š"],daysMin:["Sk","Pr","An","Tr","Ke","Pn","Št"],months:["Sausis","Vasaris","Kovas","Balandis","Gegužė","Birželis","Liepa","Rugpjūtis","Rugsėjis","Spalis","Lapkritis","Gruodis"],monthsShort:["Sau","Vas","Kov","Bal","Geg","Bir","Lie","Rugp","Rugs","Spa","Lap","Gru"],today:"Šiandien",monthsTitle:"Mėnesiai",clear:"Išvalyti",weekStart:1,format:"yyyy-mm-dd"}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.lv.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.lv={days:["Svētdiena","Pirmdiena","Otrdiena","Trešdiena","Ceturtdiena","Piektdiena","Sestdiena"],daysShort:["Sv","P","O","T","C","Pk","S"],daysMin:["Sv","Pr","Ot","Tr","Ce","Pk","Se"],months:["Janvāris","Februāris","Marts","Aprīlis","Maijs","Jūnijs","Jūlijs","Augusts","Septembris","Oktobris","Novembris","Decembris"],monthsShort:["Jan","Feb","Mar","Apr","Mai","Jūn","Jūl","Aug","Sep","Okt","Nov","Dec"],today:"Šodien",weekStart:1}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.me.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.me={days:["Nedjelja","Ponedjeljak","Utorak","Srijeda","Četvrtak","Petak","Subota"],daysShort:["Ned","Pon","Uto","Sri","Čet","Pet","Sub"],daysMin:["Ne","Po","Ut","Sr","Če","Pe","Su"],months:["Januar","Februar","Mart","April","Maj","Jun","Jul","Avgust","Septembar","Oktobar","Novembar","Decembar"],monthsShort:["Jan","Feb","Mar","Apr","Maj","Jun","Jul","Avg","Sep","Okt","Nov","Dec"],today:"Danas",weekStart:1,clear:"Izbriši",format:"dd.mm.yyyy"}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.mk.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.mk={days:["Недела","Понеделник","Вторник","Среда","Четврток","Петок","Сабота"],daysShort:["Нед","Пон","Вто","Сре","Чет","Пет","Саб"],daysMin:["Не","По","Вт","Ср","Че","Пе","Са"],months:["Јануари","Февруари","Март","Април","Мај","Јуни","Јули","Август","Септември","Октомври","Ноември","Декември"],monthsShort:["Јан","Фев","Мар","Апр","Мај","Јун","Јул","Авг","Сеп","Окт","Ное","Дек"],today:"Денес",format:"dd.mm.yyyy"}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.mn.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.mn={days:["Ням","Даваа","Мягмар","Лхагва","Пүрэв","Баасан","Бямба"],daysShort:["Ням","Дав","Мяг","Лха","Пүр","Баа","Бям"],daysMin:["Ня","Да","Мя","Лх","Пү","Ба","Бя"],months:["Хулгана","Үхэр","Бар","Туулай","Луу","Могой","Морь","Хонь","Бич","Тахиа","Нохой","Гахай"],monthsShort:["Хул","Үхэ","Бар","Туу","Луу","Мог","Мор","Хон","Бич","Тах","Нох","Гах"],today:"Өнөөдөр",clear:"Тодорхой",format:"yyyy.mm.dd",weekStart:1}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.ms.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.ms={days:["Ahad","Isnin","Selasa","Rabu","Khamis","Jumaat","Sabtu"],daysShort:["Aha","Isn","Sel","Rab","Kha","Jum","Sab"],daysMin:["Ah","Is","Se","Ra","Kh","Ju","Sa"],months:["Januari","Februari","Mac","April","Mei","Jun","Julai","Ogos","September","Oktober","November","Disember"],monthsShort:["Jan","Feb","Mar","Apr","Mei","Jun","Jul","Ogo","Sep","Okt","Nov","Dis"],today:"Hari Ini",clear:"Bersihkan"}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.nb.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.nb={days:["Søndag","Mandag","Tirsdag","Onsdag","Torsdag","Fredag","Lørdag"],daysShort:["Søn","Man","Tir","Ons","Tor","Fre","Lør"],daysMin:["Sø","Ma","Ti","On","To","Fr","Lø"],months:["Januar","Februar","Mars","April","Mai","Juni","Juli","August","September","Oktober","November","Desember"],monthsShort:["Jan","Feb","Mar","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Des"],today:"I Dag",format:"dd.mm.yyyy"}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.nl-BE.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates["nl-BE"]={days:["zondag","maandag","dinsdag","woensdag","donderdag","vrijdag","zaterdag"],daysShort:["zo","ma","di","wo","do","vr","za"],daysMin:["zo","ma","di","wo","do","vr","za"],months:["januari","februari","maart","april","mei","juni","juli","augustus","september","oktober","november","december"],monthsShort:["jan","feb","mrt","apr","mei","jun","jul","aug","sep","okt","nov","dec"],today:"Vandaag",monthsTitle:"Maanden",clear:"Leegmaken",weekStart:1,format:"dd/mm/yyyy"}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.nl.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.nl={days:["zondag","maandag","dinsdag","woensdag","donderdag","vrijdag","zaterdag"],daysShort:["zo","ma","di","wo","do","vr","za"],daysMin:["zo","ma","di","wo","do","vr","za"],months:["januari","februari","maart","april","mei","juni","juli","augustus","september","oktober","november","december"],monthsShort:["jan","feb","mrt","apr","mei","jun","jul","aug","sep","okt","nov","dec"],today:"Vandaag",monthsTitle:"Maanden",clear:"Wissen",weekStart:1,format:"dd-mm-yyyy"}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.no.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.no={days:["Søndag","Mandag","Tirsdag","Onsdag","Torsdag","Fredag","Lørdag"],daysShort:["Søn","Man","Tir","Ons","Tor","Fre","Lør"],daysMin:["Sø","Ma","Ti","On","To","Fr","Lø"],months:["Januar","Februar","Mars","April","Mai","Juni","Juli","August","September","Oktober","November","Desember"],monthsShort:["Jan","Feb","Mar","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Des"],today:"I dag",clear:"Nullstill",weekStart:1,format:"dd.mm.yyyy"}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.pl.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.pl={days:["niedziela","poniedziałek","wtorek","środa","czwartek","piątek","sobota"],daysShort:["niedz.","pon.","wt.","śr.","czw.","piąt.","sob."],daysMin:["ndz.","pn.","wt.","śr.","czw.","pt.","sob."],months:["styczeń","luty","marzec","kwiecień","maj","czerwiec","lipiec","sierpień","wrzesień","październik","listopad","grudzień"],monthsShort:["sty.","lut.","mar.","kwi.","maj","cze.","lip.","sie.","wrz.","paź.","lis.","gru."],today:"dzisiaj",weekStart:1,clear:"wyczyść",format:"dd.mm.yyyy"}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.pt-BR.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates["pt-BR"]={days:["Domingo","Segunda","Terça","Quarta","Quinta","Sexta","Sábado"],daysShort:["Dom","Seg","Ter","Qua","Qui","Sex","Sáb"],daysMin:["Do","Se","Te","Qu","Qu","Se","Sa"],months:["Janeiro","Fevereiro","Março","Abril","Maio","Junho","Julho","Agosto","Setembro","Outubro","Novembro","Dezembro"],monthsShort:["Jan","Fev","Mar","Abr","Mai","Jun","Jul","Ago","Set","Out","Nov","Dez"],today:"Hoje",monthsTitle:"Meses",clear:"Limpar",format:"dd/mm/yyyy"}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.pt.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.pt={days:["Domingo","Segunda","Terça","Quarta","Quinta","Sexta","Sábado"],daysShort:["Dom","Seg","Ter","Qua","Qui","Sex","Sáb"],daysMin:["Do","Se","Te","Qu","Qu","Se","Sa"],months:["Janeiro","Fevereiro","Março","Abril","Maio","Junho","Julho","Agosto","Setembro","Outubro","Novembro","Dezembro"],monthsShort:["Jan","Fev","Mar","Abr","Mai","Jun","Jul","Ago","Set","Out","Nov","Dez"],today:"Hoje",monthsTitle:"Meses",clear:"Limpar",format:"dd/mm/yyyy"}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.ro.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.ro={days:["Duminică","Luni","Marţi","Miercuri","Joi","Vineri","Sâmbătă"],daysShort:["Dum","Lun","Mar","Mie","Joi","Vin","Sâm"],daysMin:["Du","Lu","Ma","Mi","Jo","Vi","Sâ"],months:["Ianuarie","Februarie","Martie","Aprilie","Mai","Iunie","Iulie","August","Septembrie","Octombrie","Noiembrie","Decembrie"],monthsShort:["Ian","Feb","Mar","Apr","Mai","Iun","Iul","Aug","Sep","Oct","Nov","Dec"],today:"Astăzi",clear:"Șterge",weekStart:1}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.rs-latin.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates["rs-latin"]={days:["Nedelja","Ponedeljak","Utorak","Sreda","Četvrtak","Petak","Subota"],daysShort:["Ned","Pon","Uto","Sre","Čet","Pet","Sub"],daysMin:["N","Po","U","Sr","Č","Pe","Su"],months:["Januar","Februar","Mart","April","Maj","Jun","Jul","Avgust","Septembar","Oktobar","Novembar","Decembar"],monthsShort:["Jan","Feb","Mar","Apr","Maj","Jun","Jul","Avg","Sep","Okt","Nov","Dec"],today:"Danas",weekStart:1,format:"dd.mm.yyyy"}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.rs.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.rs={days:["Недеља","Понедељак","Уторак","Среда","Четвртак","Петак","Субота"],daysShort:["Нед","Пон","Уто","Сре","Чет","Пет","Суб"],daysMin:["Н","По","У","Ср","Ч","Пе","Су"],months:["Јануар","Фебруар","Март","Април","Мај","Јун","Јул","Август","Септембар","Октобар","Новембар","Децембар"],monthsShort:["Јан","Феб","Мар","Апр","Мај","Јун","Јул","Авг","Сеп","Окт","Нов","Дец"],today:"Данас",weekStart:1,format:"dd.mm.yyyy"}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.ru.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.ru={days:["Воскресенье","Понедельник","Вторник","Среда","Четверг","Пятница","Суббота"],daysShort:["Вск","Пнд","Втр","Срд","Чтв","Птн","Суб"],daysMin:["Вс","Пн","Вт","Ср","Чт","Пт","Сб"],months:["Январь","Февраль","Март","Апрель","Май","Июнь","Июль","Август","Сентябрь","Октябрь","Ноябрь","Декабрь"],monthsShort:["Янв","Фев","Мар","Апр","Май","Июн","Июл","Авг","Сен","Окт","Ноя","Дек"],today:"Сегодня",clear:"Очистить",format:"dd.mm.yyyy",weekStart:1}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.sk.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.sk={days:["Nedeľa","Pondelok","Utorok","Streda","Štvrtok","Piatok","Sobota"],daysShort:["Ned","Pon","Uto","Str","Štv","Pia","Sob"],daysMin:["Ne","Po","Ut","St","Št","Pia","So"],months:["Január","Február","Marec","Apríl","Máj","Jún","Júl","August","September","Október","November","December"],monthsShort:["Jan","Feb","Mar","Apr","Máj","Jún","Júl","Aug","Sep","Okt","Nov","Dec"],today:"Dnes",clear:"Vymazať",weekStart:1,format:"d.m.yyyy"}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.sl.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.sl={days:["Nedelja","Ponedeljek","Torek","Sreda","Četrtek","Petek","Sobota"],daysShort:["Ned","Pon","Tor","Sre","Čet","Pet","Sob"],daysMin:["Ne","Po","To","Sr","Če","Pe","So"],months:["Januar","Februar","Marec","April","Maj","Junij","Julij","Avgust","September","Oktober","November","December"],monthsShort:["Jan","Feb","Mar","Apr","Maj","Jun","Jul","Avg","Sep","Okt","Nov","Dec"],today:"Danes"}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.sq.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.sq={days:["E Diel","E Hënë","E Martē","E Mërkurë","E Enjte","E Premte","E Shtunë"],daysShort:["Die","Hën","Mar","Mër","Enj","Pre","Shtu"],daysMin:["Di","Hë","Ma","Më","En","Pr","Sht"],months:["Janar","Shkurt","Mars","Prill","Maj","Qershor","Korrik","Gusht","Shtator","Tetor","Nëntor","Dhjetor"],monthsShort:["Jan","Shk","Mar","Pri","Maj","Qer","Korr","Gu","Sht","Tet","Nën","Dhjet"],today:"Sot"}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.sr-latin.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates["sr-latin"]={days:["Nedelja","Ponedeljak","Utorak","Sreda","Četvrtak","Petak","Subota"],daysShort:["Ned","Pon","Uto","Sre","Čet","Pet","Sub"],daysMin:["N","Po","U","Sr","Č","Pe","Su"],months:["Januar","Februar","Mart","April","Maj","Jun","Jul","Avgust","Septembar","Oktobar","Novembar","Decembar"],monthsShort:["Jan","Feb","Mar","Apr","Maj","Jun","Jul","Avg","Sep","Okt","Nov","Dec"],today:"Danas",weekStart:1,format:"dd.mm.yyyy"}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.sr.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.sr={days:["Недеља","Понедељак","Уторак","Среда","Четвртак","Петак","Субота"],daysShort:["Нед","Пон","Уто","Сре","Чет","Пет","Суб"],daysMin:["Н","По","У","Ср","Ч","Пе","Су"],months:["Јануар","Фебруар","Март","Април","Мај","Јун","Јул","Август","Септембар","Октобар","Новембар","Децембар"],monthsShort:["Јан","Феб","Мар","Апр","Мај","Јун","Јул","Авг","Сеп","Окт","Нов","Дец"],today:"Данас",weekStart:1,format:"dd.mm.yyyy"}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.sv.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.sv={days:["Söndag","Måndag","Tisdag","Onsdag","Torsdag","Fredag","Lördag"],daysShort:["Sön","Mån","Tis","Ons","Tor","Fre","Lör"],daysMin:["Sö","Må","Ti","On","To","Fr","Lö"],months:["Januari","Februari","Mars","April","Maj","Juni","Juli","Augusti","September","Oktober","November","December"],monthsShort:["Jan","Feb","Mar","Apr","Maj","Jun","Jul","Aug","Sep","Okt","Nov","Dec"],today:"Idag",format:"yyyy-mm-dd",weekStart:1,clear:"Rensa"}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.sw.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.sw={days:["Jumapili","Jumatatu","Jumanne","Jumatano","Alhamisi","Ijumaa","Jumamosi"],daysShort:["J2","J3","J4","J5","Alh","Ij","J1"],daysMin:["2","3","4","5","A","I","1"],months:["Januari","Februari","Machi","Aprili","Mei","Juni","Julai","Agosti","Septemba","Oktoba","Novemba","Desemba"],monthsShort:["Jan","Feb","Mac","Apr","Mei","Jun","Jul","Ago","Sep","Okt","Nov","Des"],today:"Leo"}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.th.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.th={days:["อาทิตย์","จันทร์","อังคาร","พุธ","พฤหัส","ศุกร์","เสาร์","อาทิตย์"],daysShort:["อา","จ","อ","พ","พฤ","ศ","ส","อา"],daysMin:["อา","จ","อ","พ","พฤ","ศ","ส","อา"],months:["มกราคม","กุมภาพันธ์","มีนาคม","เมษายน","พฤษภาคม","มิถุนายน","กรกฎาคม","สิงหาคม","กันยายน","ตุลาคม","พฤศจิกายน","ธันวาคม"],monthsShort:["ม.ค.","ก.พ.","มี.ค.","เม.ย.","พ.ค.","มิ.ย.","ก.ค.","ส.ค.","ก.ย.","ต.ค.","พ.ย.","ธ.ค."],today:"วันนี้"}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.tr.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.tr={days:["Pazar","Pazartesi","Salı","Çarşamba","Perşembe","Cuma","Cumartesi"],daysShort:["Pz","Pzt","Sal","Çrş","Prş","Cu","Cts"],daysMin:["Pz","Pzt","Sa","Çr","Pr","Cu","Ct"],months:["Ocak","Şubat","Mart","Nisan","Mayıs","Haziran","Temmuz","Ağustos","Eylül","Ekim","Kasım","Aralık"],monthsShort:["Oca","Şub","Mar","Nis","May","Haz","Tem","Ağu","Eyl","Eki","Kas","Ara"],today:"Bugün",clear:"Temizle",weekStart:1,format:"dd.mm.yyyy"}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.uk.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.uk={days:["Неділя","Понеділок","Вівторок","Середа","Четвер","П'ятниця","Субота"],daysShort:["Нед","Пнд","Втр","Срд","Чтв","Птн","Суб"],daysMin:["Нд","Пн","Вт","Ср","Чт","Пт","Сб"],months:["Cічень","Лютий","Березень","Квітень","Травень","Червень","Липень","Серпень","Вересень","Жовтень","Листопад","Грудень"],monthsShort:["Січ","Лют","Бер","Кві","Тра","Чер","Лип","Сер","Вер","Жов","Лис","Гру"],today:"Сьогодні",clear:"Очистити",format:"dd.mm.yyyy",weekStart:1}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.vi.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.vi={days:["Chủ nhật","Thứ hai","Thứ ba","Thứ tư","Thứ năm","Thứ sáu","Thứ bảy"],daysShort:["CN","Thứ 2","Thứ 3","Thứ 4","Thứ 5","Thứ 6","Thứ 7"],daysMin:["CN","T2","T3","T4","T5","T6","T7"],months:["Tháng 1","Tháng 2","Tháng 3","Tháng 4","Tháng 5","Tháng 6","Tháng 7","Tháng 8","Tháng 9","Tháng 10","Tháng 11","Tháng 12"],monthsShort:["Th1","Th2","Th3","Th4","Th5","Th6","Th7","Th8","Th9","Th10","Th11","Th12"],today:"Hôm nay",clear:"Xóa",format:"dd/mm/yyyy"}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.zh-CN.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates["zh-CN"]={days:["星期日","星期一","星期二","星期三","星期四","星期五","星期六"],daysShort:["周日","周一","周二","周三","周四","周五","周六"],daysMin:["日","一","二","三","四","五","六"],months:["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"],monthsShort:["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],today:"今日",clear:"清除",format:"yyyy年mm月dd日",titleFormat:"yyyy年mm月",weekStart:1}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap-datepicker/locales/bootstrap-datepicker.zh-TW.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates["zh-TW"]={days:["星期日","星期一","星期二","星期三","星期四","星期五","星期六"],daysShort:["週日","週一","週二","週三","週四","週五","週六"],daysMin:["日","一","二","三","四","五","六"],months:["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"],monthsShort:["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],today:"今天",format:"yyyy年mm月dd日",weekStart:1,clear:"清除"}}(jQuery);
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap/fonts/glyphicons-halflings-regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bowenpay/wechat-spider/e585a4913962dfa9a817cd7b139505a0c48aecbc/wechatspider/static/bootstrap/fonts/glyphicons-halflings-regular.eot
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap/fonts/glyphicons-halflings-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bowenpay/wechat-spider/e585a4913962dfa9a817cd7b139505a0c48aecbc/wechatspider/static/bootstrap/fonts/glyphicons-halflings-regular.ttf
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap/fonts/glyphicons-halflings-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bowenpay/wechat-spider/e585a4913962dfa9a817cd7b139505a0c48aecbc/wechatspider/static/bootstrap/fonts/glyphicons-halflings-regular.woff
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap/fonts/glyphicons-halflings-regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bowenpay/wechat-spider/e585a4913962dfa9a817cd7b139505a0c48aecbc/wechatspider/static/bootstrap/fonts/glyphicons-halflings-regular.woff2
--------------------------------------------------------------------------------
/wechatspider/static/bootstrap/js/npm.js:
--------------------------------------------------------------------------------
1 | // This file is autogenerated via the `commonjs` Grunt task. You can require() this file in a CommonJS environment.
2 | require('../../js/transition.js')
3 | require('../../js/alert.js')
4 | require('../../js/button.js')
5 | require('../../js/carousel.js')
6 | require('../../js/collapse.js')
7 | require('../../js/dropdown.js')
8 | require('../../js/modal.js')
9 | require('../../js/tooltip.js')
10 | require('../../js/popover.js')
11 | require('../../js/scrollspy.js')
12 | require('../../js/tab.js')
13 | require('../../js/affix.js')
--------------------------------------------------------------------------------
/wechatspider/static/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bowenpay/wechat-spider/e585a4913962dfa9a817cd7b139505a0c48aecbc/wechatspider/static/favicon.ico
--------------------------------------------------------------------------------
/wechatspider/static/font-awesome/fonts/FontAwesome.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bowenpay/wechat-spider/e585a4913962dfa9a817cd7b139505a0c48aecbc/wechatspider/static/font-awesome/fonts/FontAwesome.otf
--------------------------------------------------------------------------------
/wechatspider/static/font-awesome/fonts/fontawesome-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bowenpay/wechat-spider/e585a4913962dfa9a817cd7b139505a0c48aecbc/wechatspider/static/font-awesome/fonts/fontawesome-webfont.eot
--------------------------------------------------------------------------------
/wechatspider/static/font-awesome/fonts/fontawesome-webfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bowenpay/wechat-spider/e585a4913962dfa9a817cd7b139505a0c48aecbc/wechatspider/static/font-awesome/fonts/fontawesome-webfont.ttf
--------------------------------------------------------------------------------
/wechatspider/static/font-awesome/fonts/fontawesome-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bowenpay/wechat-spider/e585a4913962dfa9a817cd7b139505a0c48aecbc/wechatspider/static/font-awesome/fonts/fontawesome-webfont.woff
--------------------------------------------------------------------------------
/wechatspider/static/font-awesome/fonts/fontawesome-webfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bowenpay/wechat-spider/e585a4913962dfa9a817cd7b139505a0c48aecbc/wechatspider/static/font-awesome/fonts/fontawesome-webfont.woff2
--------------------------------------------------------------------------------
/wechatspider/static/web/css/base.css:
--------------------------------------------------------------------------------
1 | /* Global Styles */
2 | body {
3 | background: #E7EAEC;
4 | color: #222527;
5 | }
6 | a {
7 | color: #356DD0;
8 | }
9 | hr {
10 | border-color: #ddd;
11 | }
12 | .btn {
13 | border-radius: 3px;
14 | border: 1px solid #ccc;
15 | padding: 5px 12px;
16 | box-shadow: inset 0px 1px 0px 0px rgba(255,255,255,0.15);
17 | }
18 | .wechat-item {
19 | max-width: 80%;
20 | }
21 |
22 | .wechat-item .intro {
23 | color: #aaa;
24 | }
25 | .wechat-item:hover {
26 | background-color: #f5f5f5;
27 | }
28 | .wechat-item.selected {
29 | background-color: #F5F5F5;
30 | }
31 | .wechat-item .wechat-qrcode {
32 | width: 70px;
33 | height: 70px;
34 | }
35 | .wechat-id{
36 | font-size: x-small;
37 | font-weight: 400;
38 | color: #aaa;
39 | }
40 |
41 | .wechat-frequency {
42 | text-align: center;
43 | }
44 | .topic-avatar {
45 | width: 70px;
46 | height: 70px;
47 | }
48 | .avatar-list{
49 | width: 57px;
50 | height: 57px;
51 | border-radius: 100%;
52 | }
53 | .simple_form .form-control {
54 | border-radius: 0px;
55 | border-color: #D5DCE1;
56 | border: 0px;
57 | border-bottom: 1px solid #D5DCE1;
58 | box-shadow: inset 0 0px 0px #fff !important;
59 | padding: 6px 0px 6px 0;
60 | transition: none;
61 | float: none;
62 | width: auto;
63 | }
64 | .simple_form .submit-btn{
65 | margin-left: 50px;
66 | }
67 | #wechat-edit-form label {
68 | width: 67px;
69 | text-align: center;
70 | }
71 | #wechat-edit-form .submit-btn {
72 | margin-left: 100px;
73 | }
74 | #start, #end {
75 | text-align: center;
76 | }
77 | .wechat-table th {
78 | white-space: nowrap;
79 | }
80 | .wechat-table th,.wechat-table td {
81 | vertical-align: middle !important;
82 | }
83 | .wechat-table .td-center {
84 | text-align: center;
85 | }
86 |
87 | .text-delete, .text-delete a {
88 | text-decoration: line-through;
89 | color: grey!important;
90 | }
91 | .text-disable, .text-disable a {
92 | color: grey!important;
93 | }
94 |
--------------------------------------------------------------------------------
/wechatspider/static/web/images/bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bowenpay/wechat-spider/e585a4913962dfa9a817cd7b139505a0c48aecbc/wechatspider/static/web/images/bg.jpg
--------------------------------------------------------------------------------
/wechatspider/static/web/images/gongsi.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bowenpay/wechat-spider/e585a4913962dfa9a817cd7b139505a0c48aecbc/wechatspider/static/web/images/gongsi.jpg
--------------------------------------------------------------------------------
/wechatspider/static/web/images/jobole.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bowenpay/wechat-spider/e585a4913962dfa9a817cd7b139505a0c48aecbc/wechatspider/static/web/images/jobole.jpg
--------------------------------------------------------------------------------
/wechatspider/static/web/images/jobs.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bowenpay/wechat-spider/e585a4913962dfa9a817cd7b139505a0c48aecbc/wechatspider/static/web/images/jobs.jpg
--------------------------------------------------------------------------------
/wechatspider/static/web/images/touxiang.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bowenpay/wechat-spider/e585a4913962dfa9a817cd7b139505a0c48aecbc/wechatspider/static/web/images/touxiang.jpg
--------------------------------------------------------------------------------
/wechatspider/static/web/images/upload-avatar-default.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bowenpay/wechat-spider/e585a4913962dfa9a817cd7b139505a0c48aecbc/wechatspider/static/web/images/upload-avatar-default.jpg
--------------------------------------------------------------------------------
/wechatspider/static/web/images/wiki.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bowenpay/wechat-spider/e585a4913962dfa9a817cd7b139505a0c48aecbc/wechatspider/static/web/images/wiki.jpg
--------------------------------------------------------------------------------
/wechatspider/static/web/js/jquery-bootstrap-validator.js:
--------------------------------------------------------------------------------
1 | $.validator.setDefaults({
2 | highlight: function(element) {
3 | $(element).closest('.form-group').addClass('has-error');
4 | },
5 | unhighlight: function(element) {
6 | $(element).closest('.form-group').removeClass('has-error');
7 | },
8 | errorElement: 'span',
9 | errorClass: 'help-block',
10 | errorPlacement: function(error, element) {
11 | if(element.parent('.input-group').length) {
12 | error.insertAfter(element.parent());
13 | } else if(element.parent('div').length){
14 | element.parent('div').append(error);
15 | } else {
16 | error.insertAfter(element);
17 | }
18 | }
19 | });
20 | $.validator.addMethod("currency_value", function(value, element) {
21 | return this.optional(element) || /^\d+(\.\d{1,2})?$/i.test(value);
22 | }, "不能超过两位小数");
--------------------------------------------------------------------------------
/wechatspider/static/web/js/qiniu-custom.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by yijingping on 15/11/12.
3 | */
4 | function getQiniuUploader(options){
5 | var uploader_option = {
6 | runtimes: 'html5,flash,html4', //上传模式,依次退化
7 | browse_button: options.browse_button, //上传选择的点选按钮,**必需**
8 | uptoken_url: '/qiniu/uptoken/', //Ajax请求upToken的Url,**强烈建议设置**(服务端提供)
9 | // downtoken_url: '/downtoken',
10 | // Ajax请求downToken的Url,私有空间时使用,JS-SDK将向该地址POST文件的key和domain,服务端返回的JSON必须包含`url`字段,`url`值为该文件的下载地址
11 | // uptoken : '', //若未指定uptoken_url,则必须指定 uptoken ,uptoken由其他程序生成
12 | // unique_names: true, // 默认 false,key为文件名。若开启该选项,SDK会为每个文件自动生成key(文件名)
13 | // save_key: true, // 默认 false。若在服务端生成uptoken的上传策略中指定了 `sava_key`,则开启,SDK在前端将不对key进行任何处理
14 | domain: 'http://7oxfjw.com1.z0.glb.clouddn.com/', //bucket 域名,下载资源时用到,**必需**
15 | get_new_uptoken: false, //设置上传文件的时候是否每次都重新获取新的token
16 | container: options.container, //上传区域DOM ID,默认是browser_button的父元素,
17 | max_file_size: '100mb', //最大文件体积限制
18 | flash_swf_url: 'js/plupload/Moxie.swf', //引入flash,相对路径
19 | max_retries: 3, //上传失败最大重试次数
20 | dragdrop: true, //开启可拖曳上传
21 | drop_element: options.drop_element, //拖曳上传区域元素的ID,拖曳文件或文件夹后可触发上传
22 | chunk_size: '4mb', //分块上传时,每片的体积
23 | auto_start: true, //选择文件后自动上传,若关闭需要自己绑定事件触发上传,
24 | //x_vars : {
25 | // 自定义变量,参考http://developer.qiniu.com/docs/v6/api/overview/up/response/vars.html
26 | // 'time' : function(up,file) {
27 | // var time = (new Date()).getTime();
28 | // do something with 'time'
29 | // return time;
30 | // },
31 | // 'size' : function(up,file) {
32 | // var size = file.size;
33 | // do something with 'size'
34 | // return size;
35 | // }
36 | //},
37 | init: {
38 | 'FilesAdded': function(up, files) {
39 | plupload.each(files, function(file) {
40 | // 文件添加进队列后,处理相关的事情
41 | });
42 | },
43 | 'BeforeUpload': function(up, file) {
44 | // 每个文件上传前,处理相关的事情
45 | },
46 | 'UploadProgress': function(up, file) {
47 | // 每个文件上传时,处理相关的事情
48 | },
49 | 'FileUploaded': options.FileUploaded,
50 | 'Error': function(up, err, errTip) {
51 | //上传出错时,处理相关的事情
52 | },
53 | 'UploadComplete': function() {
54 | //队列文件处理完毕后,处理相关的事情
55 | },
56 | 'Key': function(up, file) {
57 | // 若想在前端对每个文件的key进行个性化处理,可以配置该函数
58 | // 该配置必须要在 unique_names: false , save_key: false 时才生效
59 |
60 | var key = ""+new Date().getTime();
61 | // do something with key here
62 | return key
63 | }
64 | }
65 | };
66 | var uploader = Qiniu.uploader(uploader_option);
67 | // domain 为七牛空间(bucket)对应的域名,选择某个空间后,可通过"空间设置->基本设置->域名设置"查看获取
68 |
69 | // uploader 为一个plupload对象,继承了所有plupload的方法,参考http://plupload.com/docs
70 | }
--------------------------------------------------------------------------------
/wechatspider/templates/404.html:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/wechatspider/templates/base.html:
--------------------------------------------------------------------------------
1 | {% load staticfiles %}
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | {% block title %}
12 | 微信爬虫
13 |
14 |
15 | {% endblock %}
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | {% block header_css %}
26 |
27 | {% endblock %}
28 |
29 |
30 |
34 |
35 |
36 |
37 | {% block nav %}
38 | {% include "nav.html" %}
39 | {% endblock %}
40 | {% block main %}
41 |
42 |
43 | {% for message in messages %}
44 |
45 |
46 | {{ message | safe }}
47 |
48 | {% endfor %}
49 | {% block main-content %}
50 |
51 | {% endblock %}
52 |
53 |
54 | {% endblock %}
55 |
56 | {% block footer %}
57 | {% include "footer.html" %}
58 | {% endblock %}
59 |
60 |
61 |
62 |
63 |
64 |
65 | {% block footer-js %}
66 |
67 | {% endblock %}
68 |
73 |
74 |
75 |
--------------------------------------------------------------------------------
/wechatspider/templates/footer.html:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/wechatspider/templates/index.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 |
3 | {% block main-content %}
4 | Non-responsive grid system
5 |
6 |
One third
7 |
One third
8 |
One third
9 |
10 | {% endblock %}
--------------------------------------------------------------------------------
/wechatspider/templates/nav.html:
--------------------------------------------------------------------------------
1 |
35 |
--------------------------------------------------------------------------------
/wechatspider/templates/paginator.html:
--------------------------------------------------------------------------------
1 | {% load paginator %}
2 | {% if pages > 1 %}
3 |
33 | {% endif %}
--------------------------------------------------------------------------------
/wechatspider/templatetags/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | __author__ = 'yijingping'
3 |
--------------------------------------------------------------------------------
/wechatspider/templatetags/paginator.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | __author__ = 'yijingping'
3 | from copy import copy
4 | from django import template
5 |
6 | register = template.Library()
7 |
8 |
9 | def paginator(context, paginated_object_list, adjacent_pages=2):
10 | """
11 | To be used in conjunction with the object_list generic view.
12 |
13 | Adds pagination context variables for use in displaying first, adjacent and
14 | last page links in addition to those created by the object_list generic
15 | view.
16 |
17 | """
18 | page = paginated_object_list.number
19 | pages = paginated_object_list.paginator.num_pages
20 | page_numbers = [n for n in \
21 | range(page - adjacent_pages, page + adjacent_pages + 1) \
22 | if n > 0 and n <= pages]
23 | return {
24 | 'params': context.get('params'),
25 | #'hits': context['hits'],
26 | 'results_per_page': paginated_object_list.paginator.per_page,
27 | 'page': page,
28 | 'pages': pages,
29 | 'page_numbers': page_numbers,
30 | 'next': page + 1,
31 | 'previous': page - 1,
32 | 'has_next': paginated_object_list.has_next(),
33 | 'has_previous': paginated_object_list.has_previous(),
34 | 'show_first': 1 not in page_numbers,
35 | 'show_last': pages not in page_numbers,
36 | 'count': paginated_object_list.paginator.count,
37 | 'start_index': paginated_object_list.start_index,
38 | 'end_index': paginated_object_list.end_index
39 |
40 | }
41 |
42 | register.inclusion_tag('paginator.html', takes_context=True)(paginator)
43 |
44 |
45 | @register.filter
46 | def update_page(params, page):
47 | res = copy((params or {}))
48 | res['page'] = page
49 | return res
50 |
51 | @register.filter
52 | def update_status(params, value):
53 | res = copy((params or {}))
54 | res['status'] = value
55 | return res
56 |
57 | @register.filter
58 | def gen_get_params(params):
59 | res = []
60 | for k, v in params.iteritems():
61 | res.append('%s=%s' % (k, v))
62 |
63 | return '?' + '&'.join(res)
64 |
65 | @register.filter
66 | def remove_key(params, key):
67 | res = copy((params or {}))
68 | res.pop(key, None)
69 | return res
70 |
--------------------------------------------------------------------------------
/wechatspider/templatetags/utils.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | __author__ = 'yijingping'
3 | import json
4 | from django import template
5 | from django.utils.safestring import mark_safe
6 |
7 | register = template.Library()
8 |
9 |
10 | @register.filter
11 | def as_json(data):
12 | return mark_safe(json.dumps(data))
--------------------------------------------------------------------------------
/wechatspider/urls.py:
--------------------------------------------------------------------------------
1 | """wechatspider URL Configuration
2 |
3 | The `urlpatterns` list routes URLs to views. For more information please see:
4 | https://docs.djangoproject.com/en/1.8/topics/http/urls/
5 | Examples:
6 | Function views
7 | 1. Add an import: from my_app import views
8 | 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home')
9 | Class-based views
10 | 1. Add an import: from other_app.views import Home
11 | 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home')
12 | Including another URLconf
13 | 1. Add an import: from blog import urls as blog_urls
14 | 2. Add a URL to urlpatterns: url(r'^blog/', include(blog_urls))
15 | """
16 | from django.conf.urls import include, url
17 | from django.contrib import admin
18 | from django.views.generic.base import RedirectView
19 |
20 | urlpatterns = [
21 | url(r'^$', RedirectView.as_view(url='wechat/', permanent=False)),
22 |
23 | url(r'^admin/', include(admin.site.urls)),
24 | url(r'^wechat/', include('wechat.urls')),
25 |
26 | url(r'^api/wechat/', include('wechat.api_urls')),
27 |
28 | ]
29 |
--------------------------------------------------------------------------------
/wechatspider/util.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | __author__ = 'yijingping'
3 | import redis
4 | import json
5 | from django.conf import settings
6 | from hashlib import md5
7 | from django.shortcuts import redirect
8 | REDIS_POOL = None
9 |
10 |
11 | def get_redis_pool():
12 | global REDIS_POOL
13 | if not REDIS_POOL:
14 | REDIS_POOL = redis.ConnectionPool(**settings.REDIS_OPTIONS)
15 |
16 | return REDIS_POOL
17 |
18 |
19 | def get_redis():
20 | return redis.Redis(connection_pool=get_redis_pool())
21 |
22 |
23 | def get_uniqueid(url):
24 | link = get_link_from_url(url)
25 | return md5(link).hexdigest()
26 |
27 |
28 | def get_link_from_url(url):
29 | if isinstance(url, basestring):
30 | return url
31 | elif isinstance(url, dict):
32 | return json.dumps(url)
33 |
34 |
35 | def login_required(f):
36 | """
37 | 要求登录的decorator
38 | :param f: 函数
39 | :return:
40 | """
41 | def _wrapper(request, *args, **kwargs):
42 | user = request.user
43 | if not user.is_authenticated():
44 | return redirect('%s?next=%s' % (settings.LOGIN_URL, request.path))
45 | else:
46 | #request_context = RequestContext(request)
47 | #request_context.push({"admin_user": user})
48 | return f(request, *args, **kwargs)
49 | return _wrapper
--------------------------------------------------------------------------------
/wechatspider/wsgi.py:
--------------------------------------------------------------------------------
1 | """
2 | WSGI config for wechatspider project.
3 |
4 | It exposes the WSGI callable as a module-level variable named ``application``.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/1.8/howto/deployment/wsgi/
8 | """
9 |
10 | import os
11 |
12 | from django.core.wsgi import get_wsgi_application
13 |
14 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "wechatspider.settings")
15 |
16 | application = get_wsgi_application()
17 |
--------------------------------------------------------------------------------