一只初学者级别的京东商城商品爬虫(爬取索尼微单的参数信息)

近期对摄影产生一些兴趣,所以就自己爬了一下京东商城上Canon微单的数据。爬虫爬取了商品价格以及详细参数信息。作为一个初学者,幸运或者不幸的是,由于爬虫性能较差,在以下的代码中我并没有用到反爬虫的问题,只熟悉Python下载与安装的朋友也可以放心食用这篇文章。

以下我记下了完整详细的爬虫制作过程,供新手朋友参考、高端玩家指正。



一、开发前的准备

开发环境:Python3.6+Jupyter notebook

爬取过程使用的库:requests+re+BeautifulSoup

数据存取以及清洗过程使用的库:pandas+matplotlib

对这些库不熟悉的可以查阅官方文档。搜索引擎搜一下就好。

另外,记得爬取前在浏览器输入https://www.jd.com/robots.txt查看爬虫协议。我们用的是requests库,这种爬虫很小,对网站很友好(一张网页一张网页的爬,效率低下),一般不会违法爬虫协议。

二、编写爬取某商品详细信息的函数

先附代码证明我不是在骗人。另外相信有经验的伙伴应该能感觉到这段代码的性能似乎有些问题。代码后是详细的分析过程。

 1 import requests
 2 from bs4 import BeautifulSoup
 3 import re
 4
 5 def get_canon_details(uid):
 6     ‘‘‘函数返回一个列表,各数据依次为[‘价格‘, ‘上市时间‘,‘商品产地‘, ‘类型‘,
 7     ‘商品毛重(kg)‘, ‘画幅‘, ‘用途‘, ‘品牌‘, ‘型号‘, ‘机身重量(g)‘, ‘尺寸(mm)‘,
 8     ‘有效像素‘, ‘传感器类型‘, ‘传感器尺寸‘, ‘对焦系统‘, ‘高清摄像‘, ‘语言‘, ‘液晶屏尺寸‘,
 9     ‘液晶屏像素‘, ‘液晶屏类型‘, ‘取景器类型‘, ‘滤镜直径‘, ‘最大光圈‘, ‘白平衡模式‘, ‘ISO感光度‘,
10     ‘场景模式‘, ‘机身闪光灯‘, ‘外接闪光灯‘, ‘自拍‘, ‘连拍速度‘, ‘机身防抖‘, ‘延时拍摄‘,
11     ‘遥控拍摄‘, ‘存储介质‘, ‘机身内存‘, ‘WiFi连接‘, ‘NFC‘, ‘蓝牙传输‘, ‘HDMI接口‘, ‘其它接口‘,
12     ‘电池型号‘, ‘电池类型‘, ‘电池续航时间‘, ‘外接电源‘]:‘‘‘
13     #根据网页URL获得对应商品的UID并尽可能抓取信息。此处仅得到商品的品牌信息
14     #测试用例为url = "https://item.jd.com/4691332.html?dist=jd"
15
16     #获取商品的价格
https://p.3.cn/prices/mgets?callback=jQuery8921309&type=1&area=1_72_2799_0&pdtk=&pduid=1532358136269191914663&pdpin=&pin=null&pdbp=0&skuIds=J_"+uid
18     price_text = requests.get(price_url)
19     PRICE = eval(re.compile(‘p":"(.*?)"‘).findall(price_text.text)[1])
20
21     #获取商品参数信息
22     introduction_url = "https://item.jd.com/"+uid+".html?dist=jd"
23     introduction = requests.get(introduction_url)
24     introduction = BeautifulSoup(introduction.text,‘lxml‘)
25     parameter = []
26     for k in range(0,len(introduction.find_all(‘dt‘,class_ = None))):
27         if introduction.find_all(‘dt‘,class_ = None)[k].i == None:
28             parameter.append(introduction.find_all(‘dt‘,class_=None)[k].text)
29
30     value = []
31     for k in range(0,len(introduction.find_all(‘dd‘,class_ = None))):
32         if introduction.find_all(‘dd‘,class_=None)[k].a == None:
33             value.append(introduction.find_all(‘dd‘,class_=None)[k].text)
34     value = value[:len(parameter)-len(value)]
35     Para_Val = dict()
36     for i,j in zip(parameter,value):
37         Para_Val[i] = j
38
39     Para_Val[‘价格‘] = PRICE
40     ANSER = []
41     for i in[‘价格‘, ‘上市时间‘,‘商品产地‘, ‘类型‘, ‘商品毛重(kg)‘, ‘画幅‘, ‘用途‘, ‘品牌‘, ‘型号‘, ‘机身重量(g)‘, ‘尺寸(mm)‘, ‘有效像素‘, ‘传感器类型‘, ‘传感器尺寸‘, ‘对焦系统‘, ‘高清摄像‘, ‘语言‘, ‘液晶屏尺寸‘, ‘液晶屏像素‘, ‘液晶屏类型‘, ‘取景器类型‘, ‘滤镜直径‘, ‘最大光圈‘, ‘白平衡模式‘, ‘ISO感光度‘, ‘场景模式‘, ‘机身闪光灯‘, ‘外接闪光灯‘, ‘自拍‘, ‘连拍速度‘, ‘机身防抖‘, ‘延时拍摄‘, ‘遥控拍摄‘, ‘存储介质‘, ‘机身内存‘, ‘WiFi连接‘, ‘NFC‘, ‘蓝牙传输‘, ‘HDMI接口‘, ‘其它接口‘, ‘电池型号‘, ‘电池类型‘, ‘电池续航时间‘, ‘外接电源‘]:
42         if i in Para_Val:
43             ANSER.append(Para_Val[i])
44         else:
45             ANSER.append(None)
46     return ANSER

首先明确这一阶段的目标。我希望可以获取京东商城上某一个商品的详细信息,包括相机的价格以及详细参数(参见代码中三引号里的内容)。完成这个过程后,再将它包装成一个函数。

2.1、获取商品价格信息。

首先分析一下京东售卖页面的结构。在Chrome中打开京东,搜索微单,点进某一个具体商品的页面。按F12进入开发者模式。之后的操作见以下的GIF。

这是我们发现价格在网页源码中对应的部分后面有“== $ 0”,不祥的预感在我心头萦绕。果然,价格信息使用的方式是异步加载,也就是说,利用requests库获得的url为"https://item.jd.com/4691332.html?dist=jd"中,并不含有我们所需要的价格信息,价格信息隐藏在另外一个url里。如何找到这个url呢?看下面这个动图。

这时需要一点耐心,输入3399并搜索(动图中输入框里直接有3399,是因为我之前输入过),在结果中找到价格存放的真正位置。就是动图最后我要复制的部分。url为:https://p.3.cn/prices/mgets?callback=jQuery6781865&type=1&area=1&pdtk=&pduid=1532358136269191914663&pdpin=&pin=null&pdbp=0&skuIds=J_4691332%2CJ_1596435%2CJ_4843047%2CJ_4682641%2CJ_1070080%2CJ_7361135%2CJ_1225383%2CJ_3576104%2CJ_5268940%2CJ_2342146&ext=11100000&source=item-pc

有点长,可见应当是可以删去一部分修饰的。注意到商品网址里有一串数字“4691332”,可以猜测这段数字是和商品一一对应的,所以而上面这段代码也有“4691332”,那么这串字符后面的都删掉。得到url:"https://p.3.cn/prices/mgets?callback=jQuery8921309&type=1&area=1_72_2799_0&pdtk=&pduid=1532358136269191914663&pdpin=&pin=null&pdbp=0&skuIds=J_4691332"。输入浏览器里看一眼,确实有价格信息。怎么取出来呢?先用requests库的get方法获得这个url里的信息并且存入price_text中,再用.text取出price_text中的文本信息,最后用正则表达式匹配出价格,再用eval函数把价格数据类型由字符型改为数值型即可。对应代码在第16~19行。

2.2、获取商品的参数信息。

用上面第二张动图类似的方法,在输入框输入“基本参数”并搜索,找到商品详细参数对应的url:"https://item.jd.com/4691332.html?dist=jd"。用requests.get把它的信息读下来,再用BeautifulSoup把它整理一下并存入变量introduction中。在jupyter中看一看结果。看图:↓↓↓可以认为<dt>标签里存放参数名称,<dd>标签里存放参数值。

考验BeautifulSoup技能熟练度的时刻到了,不会的去查文档哈,好像中文版挺多的。

这里我们遇到的麻烦在于,<dt>标签包含的不仅只有参数名称,还有其它乱七八糟的东西。我的解决方法是加限制限制要找的信息必须满足没有class且不含<i>标签;对<dd>要麻烦一丢丢,限制不含class且不含<a>标签后,发现最后总是有一项多余数据在列表尾部,将最后一项去除。这时我们就可以得到两个列表,我把它们拼成字典。(“这样一来取用比较方便,只需要规定键的列表,就可以规定得到返回值的顺序”)

2.3把上面的内容整理成函数。

经过上面两个步骤,函数主体成型了。输入参数选择什么呢?我们回顾一下用到的两个url:

‘https://item.jd.com/4691332.html?dist=jd‘

‘https://p.3.cn/prices/mgets?callback=jQuery8921309&type=1&area=1_72_2799_0&pdtk=&pduid=1532358136269191914663&pdpin=&pin=null&pdbp=0&skuIds=J_4691332‘

稍微测试就可以发现,对于别的商品,只要将上面两个url中的数字串改成商品对应的数字串,就能得到对应结果。因此我们选择输入参数为该数字串,命名为uid。至此,我们就完成了根据商品uid获取商品价格及参数信息的函数。只需要再获取大量的商品url(或uid),就可以大量爬取商品详细信息。

三、批量获取商品url

在京东上搜索佳能微单,发现有47页的商品,用下面的代码批量爬下来~

 1 import requests
 2 import re
 3 from bs4 import BeautifulSoup
 4 from get_details import get_canon_details
 5 def get_canon_url(k):
 6     res = requests.get("https://list.jd.com/list.html?cat=652,654,5012&ev=exbrand_8983&page="+str(k))
 7     soup = BeautifulSoup(res.text,‘lxml‘)
 8     url_set = set()
 9     for i in range(1,len(soup.find_all("ul",class_  ="gl-warp clearfix")[0].select(‘a[target]‘))):
10         url_set.add(soup.find_all("ul",class_  ="gl-warp clearfix")[0].select(‘a[target]‘)[i].get(‘href‘))
11     return list(url_set)
12
13 url_list = []
14 for k in range(1,48):
15     url_list.extend(get_canon_url(k))

用这段代码,跑一会等结果。中间还可以打个小游戏啥的。不详细解释了,思路和用到的方法都跟上面差不多。(主要是博主写累了233)

四、爬取并存盘

全部怕下来之前,先看看效率。如下图,效率很低。两千多条数据全部下载大概需要两个小时。可以通过改读入的url_list长度改变下载数据的数目。

 1 %%time
 2
 3 camera = []
 4 for item in url_list[1:10]:
 5     uid = re.compile(".com/(.*?).html").findall(item)
 6     if uid:
 7         all_information = [item]
 8         all_information.extend(get_canon_details(uid[0]))
 9         camera.append(all_information)
10     else:
11         continue
12
13 #Wall time: 25.6 s

接下来要把文件下载到本地,不然每次都爬实在太麻烦。代码:

1 import pandas
2 df = pandas.DataFrame(camera,columns = [‘网址‘,‘价格‘, ‘上市时间‘,‘商品产地‘, ‘类型‘, ‘商品毛重(kg)‘, ‘画幅‘, ‘用途‘, ‘品牌‘, ‘型号‘, ‘机身重量(g)‘, ‘尺寸(mm)‘, ‘有效像素‘, ‘传感器类型‘, ‘传感器尺寸‘, ‘对焦系统‘, ‘高清摄像‘, ‘语言‘, ‘液晶屏尺寸‘, ‘液晶屏像素‘, ‘液晶屏类型‘, ‘取景器类型‘, ‘滤镜直径‘, ‘最大光圈‘, ‘白平衡模式‘, ‘ISO感光度‘, ‘场景模式‘, ‘机身闪光灯‘, ‘外接闪光灯‘, ‘自拍‘, ‘连拍速度‘, ‘机身防抖‘, ‘延时拍摄‘, ‘遥控拍摄‘, ‘存储介质‘, ‘机身内存‘, ‘WiFi连接‘, ‘NFC‘, ‘蓝牙传输‘, ‘HDMI接口‘, ‘其它接口‘, ‘电池型号‘, ‘电池类型‘, ‘电池续航时间‘, ‘外接电源‘])
3 df["网址"]="https:"+df["网址"]
4
5 df = df[df["价格"]>1000]
6 #之所以加这一条,是因为京东页面里会有大量的配件(价格一般小于1000)我们把它去掉
7
8 df.to_excel("camera.xlsx", merge_cells=False)

五、基本的数据整理

现在我们从下载的本地文件里读入数据:

# -*- coding=gbk -*-
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
data = pd.read_csv("camera.csv",engine=‘python‘)
del data["Unnamed: 0"]

画价格分布图:

 1 %matplotlib inline
 2 import matplotlib.pyplot as plt
 3 from pylab import *
 4 mpl.rcParams[‘font.sans-serif‘] = [‘SimHei‘]
 5 fig = plt.figure()
 6 price = fig.add_subplot(111)
 7 price.hist(data[data["价格"]<10000]["价格"])
 8 plt.xlabel("价格")
 9 plt.ylabel("数目")
10 plt.title("CANON万元以下微单价格分布图(数据来源:京东)")

将像素数据改为数值型并处理缺失值:(这里弹出一个警告,博主没有能够解决)

1 import re
2 for i in range(0,len(data["有效像素"])):
3     if type(data["有效像素"][i]) == str:
4         if len(re.findall("\d+",data["有效像素"][i])):
5             data["有效像素"][i] = eval(re.findall("\d+",data["有效像素"][i])[0])
6         else:
7             data["有效像素"][i] = 0

好啦,我我爬取京东微单的经历和经验就分享到这里,希望一起入坑Python的朋友能看的顺利,一起加油吧!

原文地址:https://www.cnblogs.com/Reader-Yu/p/9357307.html

时间: 2024-10-28 16:23:05

一只初学者级别的京东商城商品爬虫(爬取索尼微单的参数信息)的相关文章

Scrapy实战---Scrapy对接selenium爬取京东商城商品数据

本篇目标:我们以爬取京东商城商品数据为例,展示Scrapy框架对接selenium爬取京东商城商品数据. 背景: 京东商城页面为js动态加载页面,直接使用request请求,无法得到我们想要的商品数据,故需要借助于selenium模拟人的行为发起请求,输出源代码,然后解析源代码,得到我们想要的数据. 第一步:设置我们需要提取的字段,也就是在Scrapy框架中设置Item.py文件. class ProductItem(scrapy.Item): # define the fields for y

jQuery制作仿京东商城-商品列表商品筛选功能

这次使用jquery来实现一个仿京东商城-商品列表商品筛选的功能 一.html代码 <!DOCTYPE html> <html> <head> <title></title> <link rel="stylesheet" type="text/css" href="css/style.css"> </head> <body> <div class

python制作爬虫爬取京东商品评论教程

作者:蓝鲸 类型:转载 本文是继前2篇Python爬虫系列文章的后续篇,给大家介绍的是如何使用Python爬取京东商品评论信息的方法,并根据数据绘制成各种统计图表,非常的细致,有需要的小伙伴可以参考下 本篇文章是python爬虫系列的第三篇,介绍如何抓取京东商城商品评论信息,并对这些评论信息进行分析和可视化.下面是要抓取的商品信息,一款女士文胸.这个商品共有红色,黑色和肤色三种颜色, 70B到90D共18个尺寸,以及超过700条的购买评论. 京东商品评论信息是由JS动态加载的,所以直接抓取商品详

Java爬虫爬取 天猫 淘宝 京东 搜索页和 商品详情

Java爬虫爬取 天猫 淘宝 京东 搜索页和 商品详情 先识别商品url,区分平台提取商品编号,再根据平台带着商品编号爬取数据. 1.导包 <!-- 爬虫相关Jar包依赖 --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>3.10-FINAL</version> </

京东商城大规模爬虫的开发

先说下这个网站,首先在首页随便输入一个想爬取的商品类别,观察到一般商品数目都是100页的,除非有些比较稀少的商品,如图 小编整理一套Python资料,有需要Python学习资料可以加学习群:923414804 ,在这寒冷的冬天,泡一壶热茶,看书学习,岂不快哉. 介 绍一下网站的分析过程,默认情况下在首页输入一件商品时,出来的搜索页面是只有30件商品的,屏幕的右侧下拉框拉到下面会触发一个ajax的请求,把剩下 的30个商品渲染出来,一般每页60个商品里面是有三个左右是广告的,也就是有效商品一般是5

c# 爬虫爬取京东所有商品信息

在一个小项目中,需要用到京东的所有商品ID,因此就用c#写了个简单的爬虫. 在解析HTML中没有使用正则表达式,而是借助开源项目HtmlAgilityPack解析HTML. 一.下载网页HTML 首先我们写一个公共方法用来下载网页的HTML. 在写下载HTML方法之前,我们需要去查看京东网页请求头的相关信息,在发送请求时需要用到. public static string DownloadHtml(string url, Encoding encode) { string html = stri

Python3爬虫爬取淘宝商品数据

这次的主要的目的是从淘宝的搜索页面获取商品的信息.其实分析页面找到信息很容易,页面信息的存放都是以静态的方式直接嵌套的页面上的,很容易找到.主要困难是将信息从HTML源码中剥离出来,数据和网页源码结合的很紧密,剥离数据有一定的难度. 然后将获取的信息写入excel表格保存起来,这次只爬取了前面10页 的内容.在运行代码的过程中发现,30页后面的数据有问题,出现了手机价格为0的情况,这是不符合实际的,码也没有写错误处理的代码. 这次先写个粗略的,有点凌乱的感觉,下次有时间再系统的整理整理吧. im

利用Python爬虫爬取淘宝商品做数据挖掘分析实战篇,超详细教程

项目内容 本案例选择>> 商品类目:沙发: 数量:共100页  4400个商品: 筛选条件:天猫.销量从高到低.价格500元以上. 项目目的 1. 对商品标题进行文本分析 词云可视化 2. 不同关键词word对应的sales的统计分析 3. 商品的价格分布情况分析 4. 商品的销量分布情况分析 5. 不同价格区间的商品的平均销量分布 6. 商品价格对销量的影响分析 7. 商品价格对销售额的影响分析 8. 不同省份或城市的商品数量分布 9.不同省份的商品平均销量分布 注:本项目仅以以上几项分析为

爬虫 爬取天猫商品的封面信息

# 爬取搜索字段的封面信息 ''' q : 搜索的类型 可以识别中文 天猫控制登录字段: sort: 排序 s:起始第几个商品 问题1: 把s删除以后,虽说可以跳过登陆,但是只能访问第一页了,何解? 解决: 多次点击页面后发现,淘宝测试不完全,在点击跳转页面后,将其的url后的参数只保留 q totalPage jumpto 三个字段后,就可以通过修改jumpto字段的值 来跳转到其他的页面 问题2: 解决登陆问题后,发现无法提前知道totalpage的总页数 解决:只要页面有显示,那我们就能拿