【Python爬虫】按时爬取京东几类自营手机型号价格参数并存入数据库

news/2024/11/20 13:31:54/

一、最近刚好想换手机,然后就想知道京东上心仪的手机价格如何,对比手机价格如何,以及相应的历史价格,然后就用Python requests+MySQLdb+smtplib爬取相关的数据

二、关于实现的主要步骤:
1、根据京东搜索页面,搜索某型号(如小米手机)的自营手机,得出该型号在京东自营上的链接url
2、根据该url,将小米手机的京东自营的所有种类的url均爬取下来,存在列表或者字典里
3、根据找到的所有商品的url,爬取商品对应的价格,商品的简介
4、将以上相关信息插入数据库,并根据数据库下一条目与上一条目的价格对比,若产品降价了,则发相关email到指定用户进行通知

三、Python实现

1、如何获得京东自营的某型号手机的大类url:

首先,在京东自营上搜索某手机时,出现的结果列表并不会显示该品牌手机的所有型号手机,如可能会显示小米5 黑色32G,但可能不会显示小米5 白色 32G这一型号,这一型号在我们点击小米5 黑色32G链接进入下一级页面后会有相应的链接,所以我们第一步先要爬出所有该品牌的大类链接,再由大类链接去找到所有的该品牌的所有机型。

脚本实现如下:调用webdriver的PhantonJS, 进行JS渲染,从而得到页面的html,再运用正则判断商店名是否为该品牌的自营手机店,从而确定抓取哪些url

 def get_href_list(self, search_url, shop_name):'''得到京东某品牌自营的各种乐视手机的型号大类的url列表'''dv = webdriver.PhantomJS()a = search_urldv.get(a)time.sleep(4)html = dv.execute_script("return document.documentElement.outerHTML")aa = open('tey.txt','w+')aa.write(html)aa.close()bb = open('tey.txt' , 'r+')bbb = bb.read()bb.close()re_cmp = re.compile('<li class="gl-item" data-sku="(.*?)"', re.S)re_cmp_shop = re.compile('<div class="p-shop"(.*?)</div>', re.S)re_cmp_shop2 = re.compile('<a.*?>(.*?)</a>', re.S)cc = re.findall(re_cmp , bbb)aa = open('tey_1.txt','w+')for i in cc:aa.write(i + '\n')aa.close()return_href_list = []dd= re.findall(re_cmp_shop, bbb)aa = open('tey_2.txt','w+')print 'url is %s, shop name is %s'%(search_url,shop_name)for jj in range(len(dd)):ddd = re.findall(re_cmp_shop2, dd[jj])if len(ddd) !=0 and ddd[0] == shop_name :return_href_list.append('https://item.jd.com/' + cc[jj] + '.html')aa.write(ddd[0] + '\n' + 'https://item.jd.com/' + cc[jj] + '.html' + '\n\n')aa.close()self.return_list = return_href_listreturn return_href_list

2、抓到大类url后,需要进一步根据大类url,抓取该品牌所以机型Url,及相应的价格,简介等。首先也是对大类中的每个url进行JS渲染,再根据正则表达式抓取相应的简介,价格是抓包发现由特定的url进行交互实现的价格数值的传递,因此对该url进行调用即可得到特定机型的价格,(参数为特定机型的京东item id),最后将所有的信息存入一个列表中。
def get_href_info(self, href_list):

    '''用来根据给定的大类url来找出相对应的所有不同型号的乐视手机的url及对应的规格说明及相应的价格'''final_href = []final_return_result = []count = 0for single_href_list in href_list:count += 1try:dv = webdriver.PhantomJS()a = single_href_listdv.get(a)time.sleep(4)html = dv.execute_script("return document.documentElement.outerHTML")aa = open('leshi_%s.txt'%count,'w+')aa.write(html)aa.close()re_compile_info = re.compile('<div class="sku-name">(.*?)</div>', re.S)full_info = re.findall(re_compile_info, html)[0]re_compile = re.compile('colorSize: (.*?)],', re.S)cc = re.findall(re_compile, html)[0]except:dv = webdriver.PhantomJS()a = single_href_listdv.get(a)time.sleep(4)html = dv.execute_script("return document.documentElement.outerHTML")aa = open('leshi_%s.txt'%count,'w+')aa.write(html)aa.close()re_compile_info = re.compile('<div class="sku-name">(.*?)</div>', re.S)full_info = re.findall(re_compile_info, html)[0]re_compile = re.compile('colorSize: (.*?)],', re.S)cc = re.findall(re_compile, html)[0]re_compile1 = re.compile('{(.*?)}', re.S)ccc = re.findall(re_compile1, cc)if len(ccc[0]) == 0:info_list = []info_list.append(full_info)info_list.append(re.findall(re.compile('.com/(.*?).html' ,re.S), a)[0])final_href.append(info_list)else:re_item_id_compile = re.compile('"SkuId":(.*?),', re.S)for i in ccc:item_id = re.findall(re_item_id_compile, i)[0]re_compile_info = re.compile('<div class="sku-name">(.*?)</div>', re.S)html = urllib.urlopen('https://item.jd.com/' + item_id + '.html')html = html.read()full_info = re.findall(re_compile_info, html)[0]info_string = full_infoinfo_list = []info_list.append(info_string)info_list.append(item_id)final_href.append(info_list)aa = open('leshi.txt','w+')for kk in final_href:hhhh = []print kk[0]print kk[1]try_time = 10while try_time>0:try:a = ['https://p.3.cn/prices/mgets?type=1&pduid=1557983493&pdpin=&pdbp=0&skuIds=J_','https://p.3.cn/prices/mgets?type=1&pduid=1557983493&pdbp=0&skuIds=J_', 'https://p.3.cn/prices/mgets?type=1&pduid=1557983493&skuIds=J_', 'https://p.3.cn/prices/mgets?type=1&area=1_72_4137_0&pdtk=&pduid=1557983493&pdpin=&pdbp=0&skuIds=J_']aaa = a[random.randint(0,4)] + str(kk[1])b=urllib.urlopen(aaa)c=b.read()d=eval(c)kk.append(d[0]['p'])breakexcept:try_time = try_time - 1print 'fail %s time in href %s'%((10 -try_time), str(kk[1]))time.sleep(random.randint(1,3))if len(kk) == 2:kk.append('Not captured')aa.write(kk[0] + '  ' + 'https://item.jd.com/' + str(kk[1]) + '.html' + '   ' + kk[2])aa.write('\n\n')hhhh.append(str(kk[1]))hhhh.append(kk[0])hhhh.append(kk[2])hhhh.append('https://item.jd.com/' + str(kk[1]) + '.html')hhhh.append( time.strftime("%Y-%m-%d,%H:%M:%p", time.localtime()))final_return_result.append(hhhh)aa.close()self.return_list = final_return_resultreturn final_return_result

3、调用Mysql数据库将相关数据插入数据库:
使用的MySQLdb数据库,需要注意以下几点:
(1)、注意数据库的编码,默认为latin编码,这对中文编码是会存在异常的,需要将其修改为utf-8编码,具体修改是在MYSQL的配置文件里,就不赘述了;
(2)、MYSQL插入表时不支持变量插入,需要自己实现做好处理,表名的各事业有相关要求
(3)、执行语句时,如插入语句,对变量的格式(带”的字符创或不带”的整型)需要自己多留意

def connect_sql(self, data_list, databse_name,):'''将爬到的相关数据插入数据库'''conn = MySQLdb.connect(host = 'localhost', user = 'root', passwd = '', charset = 'utf8')cur = conn.cursor()database_create = 'create database if not exists %s'%databse_namecur.execute(database_create)conn.select_db(databse_name)table_name = 'price_' + time.strftime("%Y_%m_%d_%H_%M_%p", time.localtime())cur.execute('create table %s (item_id varchar(20) primary key not null, machine_name varchar(100),machine_price varchar(50),item_url varchar(50), time varchar(50))'%table_name)conn.commit()for ii in data_list:try:insert_sql = 'insert ignore %s values(\'%s\',\'%s\',\'%s\',\'%s\',\'%s\')'%(table_name, ii[0], ii[1].decode('gbk').encode('utf-8'), ii[2], ii[3], ii[4])cur.execute(insert_sql)except:insert_sql = 'insert ignore %s values(\'%s\',\'%s\',\'%s\',\'%s\',\'%s\')'%(table_name, ii[0], ii[1].encode('utf-8'), ii[2], ii[3], ii[4])cur.execute(insert_sql)conn.commit()cur.close()conn.close()

4、邮件通知事件:
从数据库的表中select数据,得到价格,与之前时间的价格对比,若有降价,发送email
msg = MIMEMultipart()
msg[‘from’] = ‘**@163.com’
msg[‘to’] = ‘***@qq.com’
email_info = u’%s 降价了,现在价格是%s 元,速速买’%(name, aaa[0][0])
msg[‘subject’] = Header(email_info,’utf-8’)
server = smtplib.SMTP(‘smtp.163.com’)
server.login(‘@163.com’,’***’)
error=server.sendmail(msg[‘from’], msg[‘to’],msg.as_string())
server.close

5、之后的定时爬取价格:
第一次完成爬取数据后,之后需要定时的爬取价格,由于手机型号,url,简介等都在第一次已经确定了,故而之后只需要根据这些信息去爬取可能会变化的价格就OK了,所以写了个函数实现价格爬取
根据爬去的商品的京东id,去调用京东的特定url,返回价格,并在数据库建立新表,插入数据库,其他的插入项如id等则等同于之前。

def get_price(self, all_info_list,databse_name):'''根据数据库已有的一个表数据来爬下一个时间的商品价格'''cur_time = time.strftime("%Y_%m_%d_%H_%M_%p", time.localtime())agen_list = ['Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0', 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0','Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/535.11 (KHTML, like Gecko)', 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:45.0) Gecko/20100101 Firefox/45.0']hea ={'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:45.0) Gecko/20100101 Firefox/45.0','Host':'p.3.cn','Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8','Accept-Language':'zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3','Accept-Encoding':'gzip, deflate','Content-Length':'94'}for i in all_info_list:item_id = i[0]try_time = 10while try_time>0:try:a = ['https://p.3.cn/prices/mgets?type=1&pduid=1557983493&pdpin=&pdbp=0&skuIds=J_','https://p.3.cn/prices/mgets?type=1&pduid=1557983493&pdbp=0&skuIds=J_', 'https://p.3.cn/prices/mgets?type=1&pduid=1557983493&skuIds=J_', 'https://p.3.cn/prices/mgets?type=1&area=1_72_4137_0&pdtk=&pduid=1557983493&pdpin=&pdbp=0&skuIds=J_']aa = a[random.randint(0,4)] + str(item_id)hea['User-Agent'] = agen_list[random.randint(0,4)]b=requests.get(aa, headers=hea)c=b.textd=eval(c)i[2] = d[0]['p']i[4] = cur_timebreakexcept:try_time = try_time - 1time.sleep(random.randint(1,3))print 'fail %s time in href %s'%((10 - try_time),i[3])if try_time == 0:i[2] = 'Not captured'self.connect_sql(all_info_list,databse_name)   

http://www.ppmy.cn/news/225127.html

相关文章

爬取淘宝手机数据,并进行清洗,并可视化展示

爬取所需环境 selnium安装 WinR输入cmd敲回车进入到cmd窗口&#xff1b;输入“pip3 install selenium -i https://pypi.tuna.tsinghua.edu.cn/simple”或“pip install selenium”敲回车&#xff0c;等待&#xff0c;就安装好了&#xff08;附加莫管&#xff1a;输入“pip un…

el-table 分页跨页默认选中全部

需求&#xff1a;使用el-table&#xff0c;分页从服务端请求数据&#xff0c;默认选中全部分页勾选项。 一、在此之前&#xff0c;实现选中当前页全部勾选项 方式一&#xff1a;请求数据之后&#xff0c;toggleAllSelection 方式二&#xff1a;请求数据之后&#xff0c;togg…

SVN搭建ubuntu服务器过程(图文超详细)

目录 步骤0&#xff1a;搭建环境&#xff1a; 步骤一&#xff1a;下载subversion安装包 步骤二&#xff1a;创建版本库目录 步骤三&#xff1a;创建版本库 步骤四&#xff1a;修改SVN配置 步骤五&#xff1a;重启SVN服务 步骤0&#xff1a;搭建环境&#xff1a; 在ubuntu…

yolov8模型训练结果分析以及如何评估yolov8模型训练的效果

1.运行结果目录 一、 confusion_matrix_normalized.png和confusion_matrix.png 混淆矩阵 混淆矩阵以矩阵形式将数据集中的记录按照真实的类别与分类模型预测的类别判断两个标准进行汇总。其中矩阵的行表示真实值&#xff0c;矩阵的列表示预测值。 TP&#xff08;True Positiv…

RPC接口测试技术-Tcp 协议的接口测试

【摘要】 首先明确 Tcp 的概念&#xff0c;针对 Tcp 协议进行接口测试&#xff0c;是指基于 Tcp 协议的上层协议比如 Http &#xff0c;串口&#xff0c;网口&#xff0c; Socket 等。这些协议与 Http 测试方法类似&#xff08;具体查看接口自动化测试章节&#xff09;&#xf…

python接口自动化 —— 什么是接口、接口优势、类型(详解)

简介 经常听别人说接口测试&#xff0c;接口测试自动化&#xff0c;但是你对接口&#xff0c;有多少了解和认识&#xff0c;知道什么是接口吗&#xff1f;它是用来做什么的&#xff0c;测试时候要注意什么&#xff1f;坦白的说&#xff0c;笔者之前也不是很清楚。接下来先看一下…

相机的一些基本概念 曝光/f值/焦距/光圈/景深

1.对于某个固定的镜头来说 焦距 焦点都是固定的 2.对于变焦相机来说&#xff0c;是一组镜头&#xff0c;这一组镜头是可以组成可变焦的镜头组 3.近景深(前景深)是同一概念&#xff0c;远景深和后景深是一个概念 凸透镜成像规律_百度百科凸透镜成像规律是一种光学定律。在光学…

Jetson 系列(二十八) Milvus

环境 Jetpack 4.4.1TensorRT 7.1python 3.6.8必备安装 docker-compose:参考 一、Milvus 官方:git 地址 / gitee 地址 milvus v2.1.1:地址 二、下载 YAML文件 单机版-v2.1.1: wget https://github.com/milvus-io/milvus/releases/download/v2.1.1/milvus-standalone-dock…