之前买东西都是在用一款叫慢慢买的软件,每天一闲下来就会打开慢慢买,在慢慢买购买了很多很实惠的东西,在买东西的时候遇到了最头疼的问题就是要花很长时间去找最划算的东西,尤其是京东的满减活动,要动脑还要动手才能计算出哪件最划算,我就这样靠着一点点的Excel知识,不厌其烦的计算,已经两三年了,我觉得这样下去不是办法,因为京东商品筛选里并不能提供我想要的筛选,比如一个满减活动里有什么活动是还提供优惠券的,比如如何在活动里筛选出500g或500ml单价进行排列的,这些都是没有的,要怎样才能做到这些筛选,我想到的办法就是把商品名称和商品单价,商品活动全部提取出来,输入Excel,但是一个活动就有几千件商品,想想都怕,百度了几天发现了世界上竟然还有网络爬虫这种东西,就像那谁谁发现了新大陆一样高兴,又百度了几天发现这东西没有一个能用在京东活动上的,于是只好自己花时间自己搞一个,用了两个星期,从从来没有听过python(听说这可是比C++还是VBA还要牛逼的编程环境),从不会编程全靠看教程,从来没有安装过什么叫开发环境的东西的人,竟然给我捣鼓出来了我想要的结果.当然个中的心酸我就不唠叨了,有什么困难就百度吧,你遇到什么困难也别问我了,你现在叫我重新安装一次开发环境我可能还要重来一个星期才能搞定,我什么都是用百度搜索学到的东西,在此我很感谢度娘,虽然我已经屏蔽了百度的所有广告及搜索推广,但是我依然用的很安心,就像李某人说的中国人可以为了方便而舍弃自己的隐私一样的安心.
代码分两个文件,第一个是爬取京东活动商品的,在代码下面输入活动ID(HDid),活动ID在浏览器的网址信息activity_id=里查看,还有页码YM,就是本活动一共有多少页的商品,就可以开始爬取了,京东反爬还是比较宽松的,在代码中间加了每页休息3秒加载下半部分,休息5秒转到下一页,可以顺利全部爬取,否则会被服务器拒绝访问,爬取100页只要10分钟不到,cookie中可能包含了我的一些信息,所以在此不提供,请大虾自行复制自己浏览器里的cookie,然后填入cookieA=的单引号里.第二个代码是将爬到的商品根据商品名称提取重量或者容量信息的,稍微改一下文件EXCEL地址就可以使用.1分钟不到可提取6000条商品信息,本来可以整合成一个文件代码的,不过我还是比较懒,我可以用就行了,有心的朋友可以自己去做吧.(声明:请经过csdn同意并注明作者.谢谢)
大家看图片效果.别费话了现在在送上原码,想或者愿意自己动手找到划算商品的买家也可以动手去做了,看到这样粗矿的原码大虾还请多指教别见笑,我也想写出既精简又强悍的代码,但是我只是个自学了两个星期编程的菜鸟.
京东活动爬虫原码:
import requests
from lxml import etree
import time
import csv
def DQYM(r): #读取页面信息
r.encoding = 'utf-8'
html1 = etree.HTML(r.text)
# 定位到每一个商品标签li
datas = html1.xpath('//li[contains(@class,"gl-item")]')
# 将抓取的结果保存到本地CSV文件中
with open('JD_Phone.csv', 'a', newline='',encoding='gb18030')as f:
write = csv.writer(f)
for data in datas:
p_name = data.xpath('div/div[@class="p-name p-name-type-2"]/a/em')
p_name = p_name[0].xpath('string(.)')
p_price = data.xpath('div/div[@class="p-price"]/strong/i/text()')
if not p_price:
p_price =0
else:
p_price=p_price[0]
href = data.xpath('div/div[@class="p-name p-name-type-2"]/a/@href')
p_icons1 = data.xpath('div/div[@class="p-icons"]/i[1]/text()')
p_icons2=0
p_icons3=0
if not p_icons1:
p_icons1 =0
else:
p_icons1=p_icons1[0]
if p_icons1!='自营' and p_icons1!='放心购' and p_icons1!='京东物流':
p_icons2=p_icons1;p_icons1=0
for cs in range(1, 5):
if p_icons2 == 0:
DZ='div/div[@class="p-icons"]/i['+str(cs+1)+']/text()'
p_icons2 = data.xpath(DZ)
if not p_icons2:
p_icons2 = 0
break
else:
p_icons2 = p_icons2[0]
zjs = p_icons2.find('满')
if zjs >=0:break
else:p_icons2 = 0
for cs in range(1, 5):
if p_icons3 == 0:
DZ='div/div[@class="p-icons"]/i['+str(cs+1)+']/text()'
p_icons3 = data.xpath(DZ)
if not p_icons3:
p_icons3 = 0
break
else:
p_icons3 = p_icons3[0]
zjs = p_icons3.find('券')
if zjs >=0:break
else:
zjs = p_icons3.find('折')
if zjs >=0:break
else:
zjs = p_icons3.find('秒')
if zjs >= 0:break
else:
zjs = p_icons3.find('闪')
if zjs >= 0:break
else:p_icons3 = 0
# xpath('string(.)')用来解析混夹在几个标签中的文本
write.writerow([p_name, p_price, p_icons1, p_icons2, p_icons3, href[0]])
# try:
# SFYC = 1
# write.writerow([p_name, p_price, p_icons1, p_icons2, p_icons3, href[0]])
# SFYC = 0
# except:
# if SFYC is 1:
# print('出现异常:' + str(SFYC))
f.close()
def HD(HDLX,HDid,YM): # HDMC活动名称,YM页码
cookieA='xtest=3945.cf6b6759; ipLoc-djd=1-72-2799-0; __jdv=122270672|direct|-|none|-|1547035089167; __jdu=15470350891632017527891; shshshfpa=6c4915f2-84fb-1a39-cef4-de0091af375a-1547035090; user-key=da3bfa7c-cdea-4b77-a2d5-ec1cf9d31626; PCSYCityID=1643; shshshfpb=mtm%200nOhnIqzLpmHXRkGYzA%3D%3D; pinId=1HLfn7EvEWU; pin=hxcy08; unick=%E8%8A%B1%E4%B8%8B%E5%A4%A7%E4%BA%BA; _tp=KpfAdkk7q%2FYw76DsuEHW3Q%3D%3D; _pst=hxcy08; shshshfp=2845d22efeb34c5e215b3928c0414b34; qrsc=3; __jdc=122270672; TrackID=105YHXJ6Gvhpayzb3OivenrbTL9QwLNLVxbprfiQxIPmPj3N8drf_kca11wJq9UkYrnva6fhe7KR0HEiiGxSj2xiT6W2Va9zVLf2ra1nIxQo; cn=8; 3AB9D23F7A4B3C9B=PRU4G2HS6WTJNCJJM2Q3QS25H7AYZEDGERJN7MHZ5AIGYFQ7T4IC2TFJ2JOSIJSMLFJ4UEK6PLPYWZ2JWL4TP7CJQ4; wlfstk_smdl=ztwfawabj4z5cxbaiespqwx2yys11el1; __jda=122270672.15470350891632017527891.1547035089.1547269774.1547274216.6; __jdb=122270672.1.15470350891632017527891|6.1547274216; shshshsID=0216236e9ed0033ce02cbdeb90218a36_1_1547274216703'
if HDLX=='MJ':
HDLX='activity_id='
elif HDLX=='YHQ':
HDLX = 'coupon_batch='
for n in range(1, YM+1):
print('第' + str(n) + '页')
# 下面的print函数主要是为了方便查看当前抓到第几页了
# 定义函数抓取每页前30条商品信息
# 构造每一页的url变化
urlA = 'https://search.jd.com/Search?'+HDLX+HDid+'&psort=2&stock=1&page=' + str(2 * n - 1)
url = urlA
head = {'authority': 'search.jd.com',
'method': 'POST',
'path': '/attrlog.php',
'scheme': 'https',
'accept': '*/*',
'accept-encoding': 'gzip, deflate, br',
'accept-language': 'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7',
'content-type': 'application/x-www-form-urlencoded',
'cookie':cookieA,
'user-agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36',
'x-requested-with': 'XMLHttpRequest'
}
r = requests.get(url, headers=head)
# print(url)
# 指定编码方式,不然会出现乱码
DQYM(r)
time.sleep(3)
# 定义函数抓取每页后30条商品信息
# 获取当前的Unix时间戳,并且保留小数点后5位
a = time.time()
b = '%.5f' % a
urlB = '/s_new.php?'+HDLX+HDid+'&psort=2&stock=1&page=' + str(2 * n) + '&s=' + str(48 * n - 20) + '&scrolling=y&log_id=' + str(b)
url = 'https://search.jd.com' + urlB
head = {'authority': 'search.jd.com',
'method': 'GET',
'path': urlB,
'scheme': 'https',
'accept': '*/*',
'accept-encoding': 'gzip, deflate, br',
'accept-language': 'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7',
'cookie': cookieA,
'referer': urlA,
'user-agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36',
'x-requested-with': 'XMLHttpRequest'
}
r = requests.get(url, headers=head)
# print(url)
DQYM(r)
time.sleep(5)
HDLX='MJ' # 这里填写活动类型,优惠券活动填写YHQ,满减活动填写MJ
HDid='50000115035' # 这里填写活动ID,活动ID浏览器的网址信息里查看,满减活动看activity_id=,优惠券活动看coupon_batch=
YM=98 # 这里填写活动的页码,有多少页就填写多少页
HD(HDLX,HDid,YM)
提取商品信息原码:
import re
from openpyxl import load_workbook
def DQSPMC(YHHD,HDYHL):
global SPMC
HS=2
while len(SPMC)>0:
HS=HS+1
SPMC = ws['A' + str(HS)].value # 读取单元格
if not SPMC:
wb.save(r'E:\downloads\购物'+WJM+'.xlsx') # 保存
break
else:
print(str(HS) + ' ' + SPMC)
jssl(HS)
HD1 = ws['D' + str(HS)].value # 读取活动单元格
JH = str(HD1).find('-') # 检查有没有减号
if JH > 0:
HDa = re.findall(r"\d+\.?\d*", HD1[0:JH])
HDb = re.findall(r"\d+\.?\d*", HD1[JH:])
HDYHLb=(int(HDa[0]) - int(HDb[0])) / int(HDa[0])
if YHHD == 1 and HDYHL > HDYHLb or YHHD == 2:
ws['J' + str(HS)] = HDYHLb # 写入率
elif YHHD == 1:
ws['J' + str(HS)] = HDYHL
else:
ws['J' + str(HS)] = 1
elif YHHD == 1:
ws['J' + str(HS)] = HDYHL
else:
ws['J' + str(HS)] = 1
HD1 = ws['E' + str(HS)].value # 读取活动单元格
JH = str(HD1).find('-') # 检查有没有减号
if JH > 0:
HDa = re.findall(r"\d+\.?\d*", HD1[0:JH])
HDb = re.findall(r"\d+\.?\d*", HD1[JH:])
HDYHLb=(int(HDa[0]) - int(HDb[0])) / int(HDa[0])
if YHHD == 2 and HDYHL > HDYHLb or YHHD == 1:
ws['K' + str(HS)] = HDYHLb # 写入率
elif YHHD == 2:
ws['K' + str(HS)] = HDYHL
else:
ws['K' + str(HS)] = 1
elif YHHD == 2:
ws['K' + str(HS)] = HDYHL
else:
ws['K' + str(HS)] = 1
def jssl(HS): # jssl计算数量,cs次数,range范围,zjs找到的字节数就是关键字的位置,
global SPMC
GJZ = 'KkGgg克MmLl' # GJZ关键字,SPMC商品名称
cs =-1
TQSZa=''
while cs+1<len(GJZ) and len(TQSZa)<=0:
cs=cs+1
GJZa = GJZ[cs:cs + 1]
zjs = SPMC.find(GJZa)
if zjs > 0:
# GJZzc截取关键字位置前面的字串,TQSZ提取数字
GJZzc = SPMC[zjs - 5:zjs]
TQSZa = re.findall(r"\d+\.?\d*", GJZzc)
if len(TQSZa) > 0:
TQSZ = float(TQSZa[0])
ws['G' + str(HS)] = TQSZ # 写入量
ws['H' + str(HS)] = GJZa # 写入单位
print(TQSZ)
if len(SPMC) - zjs > 3:
# 开始检查有没有乘法数量,cffh乘法符号,ch乘号,chzj乘号字节数,chzc乘号字串,cs乘数
chzc = SPMC[zjs:zjs + 5]
cffh = '*Xx'
CSb=0
for CSb in range(0, len(cffh) + 1):
ch = cffh[CSb:CSb + 1]
chzj = chzc.find(ch)
if chzj > 0:
csA = re.findall(r"\d+\.?\d*", chzc)
if len(csA) > 0:
csB = float(csA[0])
ws['I' + str(HS)] = csB # 写入量
elif CSb+1==len(cffh):
ws['I' + str(HS)] = 1 # 写入量
else:
ws['I' + str(HS)] = 1 # 写入量
else:
if len(SPMC)-zjs>3:
# print('检查此关键字的下一个关键字')
SPMC = SPMC[zjs + 1:]
# print(SPMC)
cs = -1
else:
break
elif cs+1==len(GJZ):
ws['G' + str(HS)] = 0 # 写入量
ws['H' + str(HS)] = 0 # 写入单位
ws['I' + str(HS)] = 0 # 写入量
WJM='\Book1'
wb = load_workbook(r'E:\downloads\购物'+WJM+'.xlsx')
sheet_names = wb.sheetnames
ws = wb[sheet_names[0]]
SPMC='1'
YHHD=1 #设置是满减活动(1),还是优惠券活动(2)
HDYHL=(99-50)/99 #设置优惠率
DQSPMC(YHHD,HDYHL)