使用Python将淘宝网“拍卖商品”按拍卖“剩余时间”排序
2011-09-11 23:11
323 查看
问题描述:
在淘宝网(www.taobao.com)中搜索商品时,比如搜索“诺基亚5230”在搜索结果的“交易”中可以选择“拍卖”。
之后得到的结果列出来的是一个商品列表,它可以按以下项目升序或降序排列:
点击列表中某个项目后,打开的页面一个商品的详细信息,由于当前交易为“拍卖”,所以得到的信息中会有“剩余时间”:
注意剩余时间不是在搜索结果同一个页面中显示的,而是在点开具体商品的链接之后才能获取到的。现在有一些用户有比较特殊的需求,他们希望搜索到的商品能按照拍卖剩余时间排序,而淘宝网并没有提供这样的功能。而用户只需要得到一张按照剩余时间排序的列表,上面有对应商品项目的地址,以便能及时知道拍卖剩余时间最短的商品项目。
解决方案:
由于要求只是一个商品项目列表,尽量用简单办法处理,所以选择用python脚本去解决这个问题。
由于淘宝数据库并非公开,所以只能通过下载页面去获取相关的信息。从商品项目搜索结果的URL(由用户输入)载入搜索结果的页面,然后由那个页面获取对应商品项目的页面列表,然后从那些页面列表中读取出剩余时间的数据。最后用剩余时间作比较,对商品项目进行排序,排序后的页面列表。
中间遇到的问题:
获取商品项目的URL列表部分很顺利地完成,使用的是正则表达式提取我们需要的URL,然而按获取的URL列表各个地址载入商品详细信息后,却发现该页面显示商品拍卖“剩余时间”的部分并不是由html直接显示的,它使用了Javascript动态显示该页面。而python的urllib包没有提供解析Javascript的功能。这对信息读取造成了阻碍。
如何解决新的问题:
显然,如果又大费周折去编写模块解析Javascript肯定不合算。而且由于剩余时间是动态的信息,随时间而变,Javascript在页面中运行时肯定需要读取载入的html中的变量值,Javascript内容可能存放在另外一个URL中,但是变量值应该在html中也有。要寻找变量值的位置。但是这个变量又放在html页面的哪个部分呢?
经过尝试,我决定两次下载同一个商品的html页面。由于下载时间是不同的,同一个页面的内容也是不同的(里面Javascript的变量值不同)。我只需要找出两个页面的不同之处就能找到表示剩余时间的变量了。
使用fc.exe,下载两次的页面分别为1.htm、2.htm,使用fc 1.htm 2.htm后得到了以下结果:(在此仅展示找到时间部分)
***** 1.htm
"apiItemCollects": "http://count.taobao.com/counter2?keys=ICCP_1_13202536163",
"valTimeLeft": "546816",
"apiItemDesc":"http://dsc.taobaocdn.com/i1/130/020/13202536163/T1.ZinXopZXXXXXXXX.desc%7Cvar%5Edesc%3Bsign%5Ed58a63bb0a20e89994
***** 2.htm
"apiItemCollects": "http://count.taobao.com/counter2?keys=ICCP_1_13202536163",
"valTimeLeft": "546794",
"apiItemDesc":"http://dsc.taobaocdn.com/i1/130/020/13202536163/T1.ZinXopZXXXXXXXX.desc%7Cvar%5Edesc%3Bsign%5Ed58a63bb0a20e89994
*****
经过检验,html中的valTimeLeft这个变量即为拍卖剩余时间的秒数,html中并没有计算并显示“剩余 ? 天 ? 小时”的Javascript,它应该是被放在了不同的URL中,不过现在有了valTimeLeft已经足够了,直接通过正则表达式提取读出它后面那个数的数值就行了。最后对其进行排序。
程序的优化:
由于单线程下载处理速度过慢,多个商品项目将花费很长时间才能完成排序,因为访问的页面量非常大。故使用多线程同时下载多个页面提取信息,当然当中的同步又花费了一翻功夫,不过以前做过,还算轻车熟路。
代码实现:
GetUrlList.py --> 读入 UrlIn.txt中用户保存的搜索结果所在的URL(若有多个页面,则一行一个URL)
GetUrlList.py获取了所有搜索结果中商品的页面地址,并以一行一个URL的格式写入到了UrlOut.txt中。
getExpireTime.py从UrlOut.txt中每个URL页面获取对应商品的“剩余时间”,并将排序后的结果输出到result.htm中,同时把控制台输出保存一份到log.txt中。
使用程序时,用户将搜索结果的URL按一行一个的方式复制到UrlIn.txt中并保存,然后先后运行GetUrlList.py和getExpireTime.py,输出的result.htm则是按拍卖剩余时间排序结果。
在淘宝网(www.taobao.com)中搜索商品时,比如搜索“诺基亚5230”在搜索结果的“交易”中可以选择“拍卖”。
之后得到的结果列出来的是一个商品列表,它可以按以下项目升序或降序排列:
点击列表中某个项目后,打开的页面一个商品的详细信息,由于当前交易为“拍卖”,所以得到的信息中会有“剩余时间”:
注意剩余时间不是在搜索结果同一个页面中显示的,而是在点开具体商品的链接之后才能获取到的。现在有一些用户有比较特殊的需求,他们希望搜索到的商品能按照拍卖剩余时间排序,而淘宝网并没有提供这样的功能。而用户只需要得到一张按照剩余时间排序的列表,上面有对应商品项目的地址,以便能及时知道拍卖剩余时间最短的商品项目。
解决方案:
由于要求只是一个商品项目列表,尽量用简单办法处理,所以选择用python脚本去解决这个问题。
由于淘宝数据库并非公开,所以只能通过下载页面去获取相关的信息。从商品项目搜索结果的URL(由用户输入)载入搜索结果的页面,然后由那个页面获取对应商品项目的页面列表,然后从那些页面列表中读取出剩余时间的数据。最后用剩余时间作比较,对商品项目进行排序,排序后的页面列表。
中间遇到的问题:
获取商品项目的URL列表部分很顺利地完成,使用的是正则表达式提取我们需要的URL,然而按获取的URL列表各个地址载入商品详细信息后,却发现该页面显示商品拍卖“剩余时间”的部分并不是由html直接显示的,它使用了Javascript动态显示该页面。而python的urllib包没有提供解析Javascript的功能。这对信息读取造成了阻碍。
如何解决新的问题:
显然,如果又大费周折去编写模块解析Javascript肯定不合算。而且由于剩余时间是动态的信息,随时间而变,Javascript在页面中运行时肯定需要读取载入的html中的变量值,Javascript内容可能存放在另外一个URL中,但是变量值应该在html中也有。要寻找变量值的位置。但是这个变量又放在html页面的哪个部分呢?
经过尝试,我决定两次下载同一个商品的html页面。由于下载时间是不同的,同一个页面的内容也是不同的(里面Javascript的变量值不同)。我只需要找出两个页面的不同之处就能找到表示剩余时间的变量了。
使用fc.exe,下载两次的页面分别为1.htm、2.htm,使用fc 1.htm 2.htm后得到了以下结果:(在此仅展示找到时间部分)
***** 1.htm
"apiItemCollects": "http://count.taobao.com/counter2?keys=ICCP_1_13202536163",
"valTimeLeft": "546816",
"apiItemDesc":"http://dsc.taobaocdn.com/i1/130/020/13202536163/T1.ZinXopZXXXXXXXX.desc%7Cvar%5Edesc%3Bsign%5Ed58a63bb0a20e89994
***** 2.htm
"apiItemCollects": "http://count.taobao.com/counter2?keys=ICCP_1_13202536163",
"valTimeLeft": "546794",
"apiItemDesc":"http://dsc.taobaocdn.com/i1/130/020/13202536163/T1.ZinXopZXXXXXXXX.desc%7Cvar%5Edesc%3Bsign%5Ed58a63bb0a20e89994
*****
经过检验,html中的valTimeLeft这个变量即为拍卖剩余时间的秒数,html中并没有计算并显示“剩余 ? 天 ? 小时”的Javascript,它应该是被放在了不同的URL中,不过现在有了valTimeLeft已经足够了,直接通过正则表达式提取读出它后面那个数的数值就行了。最后对其进行排序。
程序的优化:
由于单线程下载处理速度过慢,多个商品项目将花费很长时间才能完成排序,因为访问的页面量非常大。故使用多线程同时下载多个页面提取信息,当然当中的同步又花费了一翻功夫,不过以前做过,还算轻车熟路。
代码实现:
GetUrlList.py --> 读入 UrlIn.txt中用户保存的搜索结果所在的URL(若有多个页面,则一行一个URL)
# -*- coding: cp936 -*- import urllib import re import os # 获取有效页面URL的正则表达式 strRe = r'<a stat=".*" +href ?= ?"(http://.+)" target="_blank" class="EventCanSelect" title="' # 入口Url列表文件 fin = file('UrlIn.txt') # 输出Url列表文件 fout = file('UrlOut.txt', 'w') def getUrlList(strPage): return re.findall(strRe, strPage) def getPage(strUrl): try: f = urllib.urlopen(strUrl) s = f.read() f.close() return s except: print 'Failed Searching Page: ' + strUrl return '' if __name__ == '__main__': for i in fin.xreadlines(): url = i[:-1] # 去掉换行 print 'Searching Page: ' + url strPage = getPage(url) for item in getUrlList(strPage): fout.write(item + '\n') print 'Task Finished!' fout.close() os.system('pause')
GetUrlList.py获取了所有搜索结果中商品的页面地址,并以一行一个URL的格式写入到了UrlOut.txt中。
getExpireTime.py从UrlOut.txt中每个URL页面获取对应商品的“剩余时间”,并将排序后的结果输出到result.htm中,同时把控制台输出保存一份到log.txt中。
# -*- coding: cp936 -*- import urllib import re import os import threading import time # 获取剩余时间的正则表达式 strReTime = r'"valTimeLeft": "([0-9]+)"' # 从该文件中读入URL列表 fin = file('UrlOut.txt') # 最大线程数 nMaxThread = 5 def getExpireTime(strPage): try: return int(re.search(strReTime, strPage).group(1)) except: return -1 def getPage(strUrl): try: f = urllib.urlopen(strUrl) s = f.read() f.close() return s except: print 'Failed Getting Page: ' + strUrl return '' # 限制线程数量的信号量 semaphore = threading.Semaphore(nMaxThread) # 同步输出的锁 lockPrint = threading.Lock() # 同步提交到链表的锁 lockCommit = threading.Lock() # 用于排序并输出的链表 listItem = [] logOutPut = file('log.txt', 'w') resOutPut = file('result.htm', 'w') def safe_Print(strContent): """同步打印""" lockPrint.acquire() print strContent logOutPut.write(strContent + '\n') lockPrint.release() def safe_Commit(tp): """同步提交到链表""" lockCommit.acquire() listItem.append(tp) lockCommit.release() class dlThread(threading.Thread): def __init__(self, url): threading.Thread.__init__(self) self.url = url def run(self): strPage = getPage(self.url) expireTime = getExpireTime(strPage) safe_Print(str(expireTime) + '\t' + self.url) safe_Commit((expireTime, self.url)) semaphore.release() if __name__ == '__main__': try: nInitActiveCount = threading.active_count() # print nInitActiveCount # >>>1 for i in fin.xreadlines(): url = i[:-1] th = dlThread(url) semaphore.acquire() th.start() print '正在获取' + url while threading.active_count() > nInitActiveCount: time.sleep(1) # 等待所有子线程退出 listItem.sort() for item in listItem: print str(item[0]) + ' ' + item[1] resOutPut.write(str(item[0]) + ' ' + item[1] + '<br/>') except: print '运行过程发生异常!提前终止' finally: logOutPut.close() resOutPut.close() os.system('pause')
使用程序时,用户将搜索结果的URL按一行一个的方式复制到UrlIn.txt中并保存,然后先后运行GetUrlList.py和getExpireTime.py,输出的result.htm则是按拍卖剩余时间排序结果。
相关文章推荐
- 使用python获取51CTO博客列表按时间倒序排序
- Python爬虫——4.6使用requests和正则表达式、随机代理爬取淘宝网商品信息
- python中关于操作时间的方法(一):使用time模块
- Python 使用 sorted( ) 排序
- [置顶] [爬虫]使用python抓取京东全站数据(商品,店铺,分类,评论)
- python使用time模块格式化时间
- Python网页信息采集:使用PhantomJS采集淘宝天猫商品内容
- python使用 Timer 间隔一定时间爬取(BeautifulSoup)csdn的访问量
- 使用python计算夏普比率与最大回撤和最大回撤时间的程序
- Python 日期,时间和函数的使用
- android电池剩余使用时间
- python按时间排序目录下的文件实现方法
- python按综合、销量排序抓取100页的淘宝商品列表信息
- python中redis查看剩余过期时间及用正则通配符批量删除key的方法
- hadoop平台使用python编写mapreduce二次排序小程序
- 使用memory_profiler 与 cProfile ,line_profiler 优化Python程序运行时间和内存消耗实例
- Python日期/时间操作方法使用
- windows下使用Python来修改文件时间戳
- Python使用sorted排序的方法小结
- Python使用pycurl获取http的响应时间