个人博客转至:tybai.com

无聊就想打码,打码使我快乐


Fork me on GitHub

唯品会专场监控系统

唯品会的对于数据的封锁是很严重的,例如某个界面:

一片空白!!!

身为一个数据分析师,没有数据更谈不上分析了,所以数据挖掘下还是有的:

果断F12,突然发现了一个页面:

 1 http://stock.vip.com/list/?callback=te_list&brandId=813542 

最后面的813542是这个店铺的ID,前边都是一样的

打开页面:

 

 很醒目的:sold_out

 数据是要自己找的,所以就可以发挥一下自己的小特长来搞个数据监控,顺便为自己的数据分析提供点帮助

这样子就可以做一个售罄的监控系统,监控别家店铺的售罄情况,最后得到的效果图如下:

你们在我眼里是没有秘密的!

代码解析:

确定专场ID、监控的时间间隔、监控的次数:

 1         info_data_id = input('请输入需要监控专场的ID:')
 2 
 3         ##设置间隔时长
 4         try:
 5             info_time_interval = int(input('请输入监控时间间隔分钟(min)(默认3分钟):'))
 6             if info_time_interval < 0:
 7                 print('间隔太短')
 8                 info_time_interval = 3 * 60
 9             else:
10                 info_time_interval = info_time_interval * 60
11         except:
12             info_time_interval = 3 * 60
13 
14         ##设置监控次数
15         try:
16             info_time_frequency = int(input('请输入监控次数(默认2次):'))
17             if info_time_frequency > 50:
18                 print('不要监控那么久,不能超过50次')
19                 info_time_frequency = 2
20         except:
21             info_time_frequency = 2

由于

time.sleep(second)

所以要乘以60变成分钟

给定频率最开始的代码是

frequency = 0
while frequency < info_time_frequency:
    time.sleep(info_time_interval)
    frequency = frequency + 1

在睡眠里面加入代码:

 1             url = 'http://stock.vip.com/list/?callback=te_list&brandId=' + info_data_id
 2             info_data = (get_all(getHtml(url).decode('UTF-8', 'ignore')))  # ('UTF-8')('unicode_escape')('gbk','ignore')
 3 
 4             ##下面是判断
 5             if frequency == 0:
 6                 info_data_new = info_data[0][1].split(',')
 7                 print('######导入售罄情况开始监控######')
 8             elif len(info_data_new) == len(info_data[0][1].split(',')):
 9                 print('######售罄情况没什么变化######')
10             elif len(info_data_new) > len(info_data[0][1].split(',')):
11                 for j in range(0, len(info_data_new)):
12                     info_data_name = []
13                     info_html_jpg = []
14                     if info_data_new[j] in info_data[0][1].split(','):
15                         pass
16                     else:
17                         print('该商品异常,估计被下了订单或者被取消付款:' + info_data_new[j])
18 
19                         ##图片名字,包括专场名称、商品名称
20                         namepath = get_data(getHtml(
21                             'http://www.vip.com/detail-' + info_data_id + '-' + info_data_new[j] + '.html').decode(
22                             'UTF-8', 'ignore'))
23                         rstr = '[’!"#$///%&\'*+,./:;<=>?@[\\]\\\^_`//{|}~]+'
24                         info_data_name = re.sub(rstr, "", namepath[0][1])
25                         name = time.strftime('%Y%m%d%H%S', time.localtime())  # 当时时间
26 
27                         ##得到图片网址
28                         jpgpath = get_jpg(getHtml(
29                             'http://www.vip.com/detail-' + info_data_id + '-' + info_data_new[j] + '.html').decode(
30                             'UTF-8', 'ignore'))
31 
32                         # 图片放大
33                         try:
34                             info_html_jpg = jpgpath[0][1].replace('95x120', '720x720')
35                         except:
36                             info_html_jpg = jpgpath[0][1]
37 
38                         pic = urllib.request.urlopen(info_html_jpg)  # 解析图片网址
39 
40                         ##下面是保存图片
41                         file = 'C:\\Users\\Administrator\\Desktop\\monitor\\' + time.strftime('%Y%m%d',
42                                                                                               time.localtime()) + '-' + info_data_id + '\\'
43                         filess = open(file + name + info_data_name + info_data_new[j] + '异常.jpg', 'wb')
44                         filess.write(pic.read())
45                         filess.close()
46 
47                 info_data_new = info_data[0][1].split(',')  ##更新数组
48                 continue

分段解释:

getHtml#解析头,爬虫的都知道

正则表达式得到商品的ID,附上

 1 ##解析网址的正则表达式,将售罄的product_id搞出来
 2 def get_all(html_all):
 3     reg = r'(sold_out":")(.+?)(","sold_chance)'
 4     all = re.compile(reg);
 5     alllist = re.findall(all, html_all)
 6     return alllist

得到店铺ID,那么我要用商品的的名称来,再去看商品的product_id解析情况:

 那么正则写为:

1 def get_data(html_all):
2     reg = r'(keywords" content=")(.+?)(" />)'
3     all = re.compile(reg);
4     alllist = re.findall(all, html_all)
5     return alllist

图片的网址也要,要下载图片来看看什么东西那么好卖:

 那么正则写为:

1 def get_jpg(html_all):
2     reg = r'(<img src=")(.+?)(" width=)'
3     all = re.compile(reg);
4     alllist = re.findall(all, html_all)
5     return alllist

将得到的product_id按照“,”号来分开存入一个新数组里面,这个心的数组用来作为下次循环的判断依据,即下一次循环得到的数组和这个新数组进行比较:

info_data_new = info_data[0][1].split(',')

如果两个数组长度一样就不判断了

因为解析得到的是售罄的情况

假如售罄的商品不增加还变少了,那么就可以判断是别人下单后取消订单了

因为这里下单后会假如没有库存了就会被判断为售罄

但是别人取消订单,那么售罄状态解除

如果是正常的变多,那就遍历一次就行了,找到没有的

再把判断数组更新就行

info_data_new = info_data[0][1].split(',')

这一段的代码如下:

 1                 if frequency == 0:
 2                 info_data_new = info_data[0][1].split(',')
 3                 print('######导入售罄情况开始监控######')
 4             elif len(info_data_new) == len(info_data[0][1].split(',')):
 5                 print('######售罄情况没什么变化######')
 6             elif len(info_data_new) > len(info_data[0][1].split(',')):
 7                 for j in range(0, len(info_data_new)):
 8                     info_data_name = []
 9                     info_html_jpg = []
10                     if info_data_new[j] in info_data[0][1].split(','):
11                         pass
12                     else:
13                         print('该商品异常,估计被下了订单或者被取消付款:' + info_data_new[j])

 解析也能得到图片的网址,那么就要把图片保存下来:

 1                         ##图片名字,包括专场名称、商品名称
 2                         namepath = get_data(getHtml(
 3                             'http://www.vip.com/detail-' + info_data_id + '-' + info_data_new[j] + '.html').decode(
 4                             'UTF-8', 'ignore'))
 5                         rstr = '[’!"#$///%&\'*+,./:;<=>?@[\\]\\\^_`//{|}~]+'
 6                         info_data_name = re.sub(rstr, "", namepath[0][1])
 7                         name = time.strftime('%Y%m%d%H%S', time.localtime())  # 当时时间
 8 
 9                         ##得到图片网址
10                         jpgpath = get_jpg(getHtml(
11                             'http://www.vip.com/detail-' + info_data_id + '-' + info_data_new[j] + '.html').decode(
12                             'UTF-8', 'ignore'))
13 
14                         # 图片放大
15                         try:
16                             info_html_jpg = jpgpath[0][1].replace('95x120', '720x720')
17                         except:
18                             info_html_jpg = jpgpath[0][1]
19 
20                         pic = urllib.request.urlopen(info_html_jpg)  # 解析图片网址
21 
22                         ##下面是保存图片
23                         file = 'C:\\Users\\Administrator\\Desktop\\monitor\\' + time.strftime('%Y%m%d',
24                                                                                               time.localtime()) + '-' + info_data_id + '\\'
25                         filess = open(file + name + info_data_name + info_data_new[j] + '异常.jpg', 'wb')
26                         filess.write(pic.read())
27                         filess.close()

图片的名字为:当时下载的时间+图片本来的名称+product_id

上面代码没什么特别,无非就是

去掉名字里面的不合字符

把图片变大一点

存入生成的文件夹里面,搞定

上面是异常售罄的情况

后面要写正常售罄的代码

 1             else:
 2                 info_data_linshi = []
 3                 info_data_linshi = info_data[0][1].split(',')
 4                 for i in range(0, len(info_data[0][1].split(','))):
 5                     info_data_name = []
 6                     info_html_jpg = []
 7                     if info_data_linshi[i] in info_data_new:
 8                         pass
 9                     else:
10                         print('新增售罄商品:' + info_data_linshi[i])
11                         ##图片名字,包括专场名称、商品名称
12                         namepath = get_data(getHtml(
13                             'http://www.vip.com/detail-' + info_data_id + '-' + info_data_linshi[i] + '.html').decode(
14                             'UTF-8', 'ignore'))
15                         rstr = '[’!"#$///%&\'*+,./:;<=>?@[\\]\\\^_`//{|}~]+'
16                         info_data_name = re.sub(rstr, "", namepath[0][1])
17                         name = time.strftime('%Y%m%d%H%S', time.localtime())  # 当时时间
18 
19                         ##得到图片网址
20                         jpgpath = get_jpg(getHtml(
21                             'http://www.vip.com/detail-' + info_data_id + '-' + info_data_linshi[i] + '.html').decode(
22                             'UTF-8', 'ignore'))
23 
24                         # 图片放大
25                         try:
26                             info_html_jpg = jpgpath[0][1].replace('95x120', '720x720')
27                         except:
28                             info_html_jpg = jpgpath[0][1]
29 
30                         pic = urllib.request.urlopen(info_html_jpg)  # 解析图片网址
31 
32                         ##下面是保存图片
33                         file = 'C:\\Users\\Administrator\\Desktop\\monitor\\' + time.strftime('%Y%m%d',
34                                                                                               time.localtime()) + '-' + info_data_id + '\\'
35                         filess = open(file + name + info_data_name + info_data_linshi[i] + '.jpg', 'wb')
36                         filess.write(pic.read())
37                         filess.close()
38 
39                         info_data_new.append(info_data_linshi[i])  ##更新数组    

其实和上面是一样的,这样就算搞定了,附上全部代码:

  1 #print('python 的空白页,用来打开PyCharm')
  2 # -*- coding:utf-8 -*-
  3 import re
  4 import urllib.request, urllib.parse, http.cookiejar
  5 import os, time, re
  6 import http.cookies
  7 import time
  8 import xlsxwriter
  9 import datetime
 10 
 11 
 12 ############################################################这里是解析网址的东西###################################################################
 13 ##    说明
 14 ##     安装包
 15 ##  pip3 install bs4
 16 ##  pip3 install -U selenium
 17 ## 抓取不会变的网址用getHtml,否则getFirefox()
 18 
 19 ## 这个函数可以用Post,Get等方式获取网页内容
 20 ## 例子一:
 21 ## 如果网站有使用cookie登录的话可以加载cookie,或者如果网站反爬虫可以加头部
 22 ## 例子二:
 23 ## 被封了Ip,你就无法抓取了,此时你可以设置代理ip,下面那个‘’表示不使用代理,代理可以去网上找,很多
 24 ## 例子三:
 25 ## 有些抓取需要发送一些数据过去,才能获取到内容,此时下面的{}表示数据
 26 
 27 ## 一般使用就是 url=”xxxxxxx“ getHtml(url)   其他不用管
 28 ## 得到原始网页
 29 def getHtml(url, daili='', postdata={}):
 30     """
 31     抓取网页:支持cookie
 32     第一个参数为网址,第二个为POST的数据(这句话看得懂吧)
 33     """
 34     # COOKIE文件保存路径
 35     filename = 'cookie.txt'
 36 
 37     # 声明一个MozillaCookieJar对象实例保存在文件中
 38     cj = http.cookiejar.MozillaCookieJar(filename)
 39     # cj =http.cookiejar.LWPCookieJar(filename)
 40 
 41     # 从文件中读取cookie内容到变量
 42     # ignore_discard的意思是即使cookies将被丢弃也将它保存下来
 43     # ignore_expires的意思是如果在该文件中 cookies已经存在,则覆盖原文件写
 44     # 如果存在,则读取主要COOKIE
 45     if os.path.exists(filename):
 46         cj.load(filename, ignore_discard=True, ignore_expires=True)
 47     # 建造带有COOKIE处理器的打开专家
 48     proxy_support = urllib.request.ProxyHandler({'http': 'http://' + daili})
 49     # 开启代理支持
 50     if daili:
 51         print('代理:' + daili + '启动')
 52         opener = urllib.request.build_opener(proxy_support, urllib.request.HTTPCookieProcessor(cj),
 53                                              urllib.request.HTTPHandler)
 54     else:
 55         opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(cj))
 56 
 57     # 打开专家加头部----与post的数据格式一样,下面是头部,表示我用ipad浏览器!
 58     opener.addheaders = [('User-Agent',
 59                           'Mozilla/5.0 (iPad; U; CPU OS 4_3_3 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5'),
 60                          ]
 61 
 62     # 分配专家
 63     urllib.request.install_opener(opener)
 64     # 有数据需要POST
 65     if postdata:
 66         # 数据URL编码
 67         postdata = urllib.parse.urlencode(postdata)
 68 
 69         # 抓取网页
 70         html_bytes = urllib.request.urlopen(url, postdata.encode(), timeout=30).read()
 71     else:
 72         html_bytes = urllib.request.urlopen(url, timeout=30).read()
 73 
 74     # 保存COOKIE到文件中
 75     cj.save(ignore_discard=True, ignore_expires=True)
 76     return html_bytes
 77 
 78 
 79 ############################################################这里是函数,也是正则表达式###################################################################
 80 ##解析网址的正则表达式,将售罄的product_id搞出来
 81 def get_all(html_all):
 82     reg = r'(sold_out":")(.+?)(","sold_chance)'
 83     all = re.compile(reg);
 84     alllist = re.findall(all, html_all)
 85     return alllist
 86 
 87 
 88 ##解析网址的正则表达式,将变动商品的专场以及名称搞出来
 89 def get_data(html_all):
 90     reg = r'(keywords" content=")(.+?)(" />)'
 91     all = re.compile(reg);
 92     alllist = re.findall(all, html_all)
 93     return alllist
 94 
 95 
 96 def get_jpg(html_all):
 97     reg = r'(<img src=")(.+?)(" width=)'
 98     all = re.compile(reg);
 99     alllist = re.findall(all, html_all)
100     return alllist
101 
102 
103 ###########################################################这里是杂七杂八的东西###################################################################
104 def timetochina(longtime, formats='{}天{}小时{}分钟{}秒'):
105     day = 0
106     hour = 0
107     minutue = 0
108     second = 0
109     try:
110         if longtime > 60:
111             second = longtime % 60
112             minutue = longtime // 60
113         else:
114             second = longtime
115         if minutue > 60:
116             hour = minutue // 60
117             minutue = minutue % 60
118         if hour > 24:
119             day = hour // 24
120             hour = hour % 24
121         return formats.format(day, hour, minutue, second)
122     except:
123         raise Exception('时间非法')
124 
125 ############################################################这里是主函数###################################################################
126 if __name__ == '__main__':
127 
128     a = time.clock()  # 程序测速,后面会有个b = time.clock(),那么b-a就是时间
129 
130     info_data_id = input('请输入需要监控专场的ID:')
131 
132     ##设置间隔时长
133     try:
134         info_time_interval = int(input('请输入监控时间间隔分钟(min)(默认3分钟):'))
135         if info_time_interval < 0:
136             print('间隔太短')
137             info_time_interval = 3 * 60
138         else:
139             info_time_interval = info_time_interval * 60
140     except:
141         info_time_interval = 3 * 60
142 
143     ##设置监控次数
144     try:
145         info_time_frequency = int(input('请输入监控次数(默认2次):'))
146         if info_time_frequency > 50:
147             print('不要监控那么久,不能超过50次')
148             info_time_frequency = 2
149     except:
150         info_time_frequency = 2
151 
152     frequency = 0
153     info_data_new = []
154 
155     if os.path.exists(r'C:\\Users\\Administrator\\Desktop\\monitor'):  # 建立一个文件夹在桌面,文件夹为monitor
156         print('monitor文件夹已经在桌面存在,继续运行程序……')
157     else:
158         print('monitor文件夹不在桌面,新建文件夹monitor')
159         os.mkdir(r'C:\\Users\\Administrator\\Desktop\\monitor')
160         print('文件夹建立成功,继续运行程序')
161 
162     if os.path.exists(r'C:\\Users\\Administrator\\Desktop\\monitor\\' + time.strftime('%Y%m%d',
163                                                                                       time.localtime()) + '-' + info_data_id):
164         print(time.strftime('%Y%m%d', time.localtime()) + '-' + info_data_id + '文件夹已经在桌面存在,继续运行程序……')
165     else:
166         print(time.strftime('%Y%m%d', time.localtime()) + '-' + info_data_id + '文件夹不在桌面,新建文件夹' + time.strftime(
167             '%Y%m%d', time.localtime()) + '-' + info_data_id)
168         os.mkdir(r'C:\\Users\\Administrator\\Desktop\\monitor\\' + time.strftime('%Y%m%d',
169                                                                                  time.localtime()) + '-' + info_data_id)
170         print('文件夹建立成功,继续运行程序')
171 
172     while frequency < info_time_frequency:
173         url = 'http://stock.vip.com/list/?callback=te_list&brandId=' + info_data_id
174         info_data = (get_all(getHtml(url).decode('UTF-8', 'ignore')))  # ('UTF-8')('unicode_escape')('gbk','ignore')
175 
176         ##下面是判断
177         if frequency == 0:
178             info_data_new = info_data[0][1].split(',')
179             print('######导入售罄情况开始监控######')
180         elif len(info_data_new) == len(info_data[0][1].split(',')):
181             print('######售罄情况没什么变化######')
182         elif len(info_data_new) > len(info_data[0][1].split(',')):
183             for j in range(0, len(info_data_new)):
184                 info_data_name = []
185                 info_html_jpg = []
186                 if info_data_new[j] in info_data[0][1].split(','):
187                     pass
188                 else:
189                     print('该商品异常,估计被下了订单或者被取消付款:' + info_data_new[j])
190 
191                     ##图片名字,包括专场名称、商品名称
192                     namepath = get_data(getHtml(
193                         'http://www.vip.com/detail-' + info_data_id + '-' + info_data_new[j] + '.html').decode(
194                         'UTF-8', 'ignore'))
195                     rstr = '[’!"#$///%&\'*+,./:;<=>?@[\\]\\\^_`//{|}~]+'
196                     info_data_name = re.sub(rstr, "", namepath[0][1])
197                     name = time.strftime('%Y%m%d%H%S', time.localtime())  # 当时时间
198 
199                     ##得到图片网址
200                     jpgpath = get_jpg(getHtml(
201                         'http://www.vip.com/detail-' + info_data_id + '-' + info_data_new[j] + '.html').decode(
202                         'UTF-8', 'ignore'))
203 
204                     # 图片放大
205                     try:
206                         info_html_jpg = jpgpath[0][1].replace('95x120', '720x720')
207                     except:
208                         info_html_jpg = jpgpath[0][1]
209 
210                     pic = urllib.request.urlopen(info_html_jpg)  # 解析图片网址
211 
212                     ##下面是保存图片
213                     file = 'C:\\Users\\Administrator\\Desktop\\monitor\\' + time.strftime('%Y%m%d',
214                                                                                           time.localtime()) + '-' + info_data_id + '\\'
215                     filess = open(file + name + info_data_name + info_data_new[j] + '异常.jpg', 'wb')
216                     filess.write(pic.read())
217                     filess.close()
218 
219             info_data_new = info_data[0][1].split(',')  ##更新数组
220             continue
221 
222 
223         else:
224             info_data_linshi = []
225             info_data_linshi = info_data[0][1].split(',')
226             for i in range(0, len(info_data[0][1].split(','))):
227                 info_data_name = []
228                 info_html_jpg = []
229                 if info_data_linshi[i] in info_data_new:
230                     pass
231                 else:
232                     print('新增售罄商品:' + info_data_linshi[i])
233                     ##图片名字,包括专场名称、商品名称
234                     namepath = get_data(getHtml(
235                         'http://www.vip.com/detail-' + info_data_id + '-' + info_data_linshi[i] + '.html').decode(
236                         'UTF-8', 'ignore'))
237                     rstr = '[’!"#$///%&\'*+,./:;<=>?@[\\]\\\^_`//{|}~]+'
238                     info_data_name = re.sub(rstr, "", namepath[0][1])
239                     name = time.strftime('%Y%m%d%H%S', time.localtime())  # 当时时间
240 
241                     ##得到图片网址
242                     jpgpath = get_jpg(getHtml(
243                         'http://www.vip.com/detail-' + info_data_id + '-' + info_data_linshi[i] + '.html').decode(
244                         'UTF-8', 'ignore'))
245 
246                     # 图片放大
247                     try:
248                         info_html_jpg = jpgpath[0][1].replace('95x120', '720x720')
249                     except:
250                         info_html_jpg = jpgpath[0][1]
251 
252                     pic = urllib.request.urlopen(info_html_jpg)  # 解析图片网址
253 
254                     ##下面是保存图片
255                     file = 'C:\\Users\\Administrator\\Desktop\\monitor\\' + time.strftime('%Y%m%d',
256                                                                                           time.localtime()) + '-' + info_data_id + '\\'
257                     filess = open(file + name + info_data_name + info_data_linshi[i] + '.jpg', 'wb')
258                     filess.write(pic.read())
259                     filess.close()
260 
261                     info_data_new.append(info_data_linshi[i])  ##更新数组
262 
263         # print(len(info_data_new))
264         print('暂停' + str(info_time_interval / 60) + '分钟')
265         print('\n')
266         print('请等待...')
267 
268         time.sleep(info_time_interval)
269         frequency = frequency + 1
270 
271     b = time.clock()
272     print('运行时间:' + timetochina(b - a))
273     input('请关闭窗口')  ##防止运行完毕后窗口直接关闭而看不到运行时间

 

  

  

 

posted on 2016-07-29 19:58  TTyb  阅读(2744)  评论(0编辑  收藏  举报

导航


不用多久

我就会升职加薪

当上总经理

出任CEO

迎娶白富美

走上人生巅峰

Pulpit rock