Python爬取京东笔记本电脑,来看看那个牌子最棒

一、前言

二、知识要求三、过程分析1.观察主页面和每个电脑界面的网址2.寻找每个电脑的id3.找到存放电脑的价格和评论数的信息4.爬取信息的思路四、urllib模块爬取京东笔记本电脑的数据、并对其做一个可视化实战五、可视化结果1.运行结果2.可视化结果

//

本文作者

王豪:行路难,多歧路,今安在,埋头苦改bug会有时,直到bug改完才吃饭。

//

阅读文本大概需要 5 分钟。

一、前言

作为一个程序员,笔记本电脑是必不可少的,我这里对京东上的前2页的笔记本的好评论数,价格,店铺等信息进行爬取,并做一个可视化,根据可视化的图,大家可以清晰的做出预测,方便大家购买划算的电脑。当然,我这里前2页的数据是远远不够的,如果大家想要预测的更精准一些,可以改一下数字,获取更多页面的数据,这样,预测结果会更精确。

二、知识要求

三、过程分析

1.观察主页面和每个电脑界面的网址

(1)观察具体界面的网址,我们可以猜测,具体每个界面都有一个id,通过构造网址https://item.jd.com/【id】.html,就可以得到具体每个界面的网址。 (2)观察主界面的网址,我们发现page=的属性值就是具体的页码数,通过构造page的值,我们可以实现自动翻页爬取信息。对主界面网址一些不必要的信息剔除,最后得到主界面翻页的网址规律https://list.jd.com/list.html?cat=670,671,672&page=【页码数】

同过以上的分析,我们可以看见,获取信息的关键就是每个电脑的具体id代号,接下来,我们的任务就是要找到每个电脑的id。

2.寻找每个电脑的id

(1)首先,看看网页源代码中是否会有每个电脑的id

在这里插入图片描述

我们再进入到刚刚搜索的哪个电脑名称的具体界面,发现,确实是他的id

(3)根据id附件的一些属性值,唯一确定所有电脑id 根据class="gl-i-wrap j-sku-item"属性值定位,发现,唯一确定60个id,数了一下界面上的电脑,一页确实是60个电脑,所以,电脑的id获取到了。

(4)同理,根据<div class="p-name">属性值获取具体每个电脑的网址和电脑名,这样我们连具体每个电脑的网址都不用构造了,直接可以获取。

3.找到存放电脑的价格和评论数的信息

(1)通过到网页源代码中去找,发现完全找不到,所以,我猜测这些信息隐藏在js包中。 (2)打开fiddler抓包工具,进行抓包分析。

可以看见,这些信息确实是在js包里面,复制该js包的网址,然后分析。 (3)分析有如下结论:

这里,我也抓到了存放店铺的js包,但是,这个js包的地址每次有一部分是随机生成的,所以,获取不到每台的电脑的店铺名。但是,我有每台电脑的具体网址,而该界面里面有该电脑的店铺,所以,我可以访问每台电脑的具体界面去获取到店铺消息。

4.爬取信息的思路

(1)先爬每页的信息 (2)再爬每页中每台电脑的价格、电脑名和评论数,以及每台电脑的网址 (3)爬取每台电脑的页面,获取店铺信息 (4)获取完所有页面信息后,做一个可视化

四、urllib模块爬取京东笔记本电脑的数据、并对其做一个可视化实战

爬虫文件:(建议大家边看边敲一遍,更加有利于学习)

# -*- coding: utf-8 -*-
import random
import urllib.request
import re
import time
from lxml import etree
from pyecharts import Bar
from pyecharts import Pie


headers = [
    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; AcooBrowser; .NET CLR 1.1.4322; .NET CLR 2.0.50727)",
    "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Acoo Browser; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.0.04506)",
    "Mozilla/4.0 (compatible; MSIE 7.0; AOL 9.5; AOLBuild 4337.35; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)",
    "Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US)",
    "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 2.0.50727; Media Center PC 6.0)",
    "Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 1.0.3705; .NET CLR 1.1.4322)",
    "Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.2; .NET CLR 3.0.04506.30)",
    "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN) AppleWebKit/523.15 (KHTML, like Gecko, Safari/419.3) Arora/0.3 (Change: 287 c9dfb30)",
    "Mozilla/5.0 (X11; U; Linux; en-US) AppleWebKit/527+ (KHTML, like Gecko, Safari/419.3) Arora/0.6",
    "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.2pre) Gecko/20070215 K-Ninja/2.1.1",
    "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9) Gecko/20080705 Firefox/3.0 Kapiko/3.0",
    "Mozilla/5.0 (X11; Linux i686; U;) Gecko/20070322 Kazehakase/0.4.5",
    "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.8) Gecko Fedora/1.9.0.8-1.fc10 Kazehakase/0.5.6",
    "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11",
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/535.20 (KHTML, like Gecko) Chrome/19.0.1036.7 Safari/535.20",
    "Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; fr) Presto/2.9.168 Version/11.52",
    "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.11 TaoBrowser/2.0 Safari/536.11",
    "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.71 Safari/537.1 LBBROWSER",
    "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; LBBROWSER)",
    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E; LBBROWSER)",
    "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.84 Safari/535.11 LBBROWSER",
    "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)",
    "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; QQBrowser/7.0.3698.400)",
    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E)",
    "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; SV1; QQDownload 732; .NET4.0C; .NET4.0E; 360SE)",
    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E)",
    "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)",
    "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.89 Safari/537.1",
    "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.89 Safari/537.1",
    "Mozilla/5.0 (iPad; U; CPU OS 4_2_1 like Mac OS X; zh-cn) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148 Safari/6533.18.5",
    "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:2.0b13pre) Gecko/20110307 Firefox/4.0b13pre",
    "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:16.0) Gecko/20100101 Firefox/16.0",
    "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11",
    "Mozilla/5.0 (X11; U; Linux x86_64; zh-CN; rv:1.9.2.10) Gecko/20100922 Ubuntu/10.10 (maverick) Firefox/3.6.10"
]

def main():
    # 用来存放所有的电脑数据
    allNames = []
    allCommentNums = {}
    allPrices = {}
    allShops = {}

    # 爬取前2页的所有笔记本电脑
    for i in range(0, 1):
        # 每页地址规律:https://list.jd.com/list.html?cat=670,671,672&page=【页码】
        print('正在爬取第'+str(i+1)+'页的信息...')
        url = 'https://list.jd.com/list.html?cat=670,671,672&page='+str(i+1)
        get_page_data(url, allNames, allCommentNums, allPrices, allShops)

    # 以上为获取信息,以下为数据的可视化
    names = allNames
    commentNums = []
    for name in names:
        if allCommentNums[name] == None:
            commentNums.append(0)
        else:
            commentNums.append(eval(allCommentNums[name]))
    prices = []
    for name in names:
        if allPrices[name] == None:
            prices.append(0)
        else:
            prices.append(eval(allPrices[name]))
    shops = []
    for name in names:
        if allShops[name] != None:
            shops.append(allShops[name])
    for i in range(0, len(names)):
        print(names[i])
        print(commentNums[i])
        print(prices[i])
        print(shops[i])
    # 将其评论数进行条形统计图可视化
    tiaoxing(names, prices)

    # 将其店铺进行饼图可视化
    # 先需要统计每个店铺的个数
    shopNames = list(set(shops))
    nums = []
    for i in range(0, len(shopNames)):
        nums.append(0)
    for shop in shops:
        for i in range(0, len(shopNames)):
            if shop == shopNames[i]:
                nums[i] += 1
    bingtu(shopNames, nums)


def get_page_data(url, allNames, allCommentNums, allPrices, allShops):
    # 爬取该页内所有电脑的id、电脑名称和该电脑的具体网址
    response = urllib.request.Request(url)
    response.add_header('User-Agent', random.choice(headers))
    data = urllib.request.urlopen(response, timeout=1).read().decode('utf-8', 'ignore')
    data = etree.HTML(data)
    ids = data.xpath('//a[@class="p-o-btn contrast J_contrast contrast-hide"]/@data-sku')
    names = data.xpath('//div[@class="p-name"]/a/em/text()')
    hrefs = data.xpath('//div[@class="p-name"]/a/@href')
    # 去掉重复的网址
    print(len(hrefs))
    hrefs = list(set(hrefs))
    print(len(hrefs))
    # 将每个电脑的网址构造完全,加上'https:'
    for i in range(0, len(hrefs)):
        hrefs[i] = 'https:'+hrefs[i]

    # 根据id构造存放每台电脑评论数的js包的地址
    # 其网址格式为:https://club.jd.com/comment/productCommentSummaries.action?my=pinglun&referenceIds=100000323510,100002368328&callback=jQuery5043746
    str = ''
    for id in ids:
        str = str + id + ','
    commentJS_url = 'https://club.jd.com/comment/productCommentSummaries.action?my=pinglun&referenceIds='+str[:-1]+'&callback=jQuery5043746'
    # 爬取该js包,获取每台电脑的评论数
    response2 = urllib.request.Request(commentJS_url)
    response2.add_header('User-Agent', random.choice(headers))
    data = urllib.request.urlopen(response2, timeout=1).read().decode('utf-8', 'ignore')
    pat = '{(.*?)}'
    commentStr = re.compile(pat).findall(data)  # commentStr用来存放每个商品的关于评论数方面的所有信息
    comments = {}
    for id in ids:
        for str in commentStr:
            if id in str:
                pat2 = '"CommentCount":(.*?),'
                comments[id] = re.compile(pat2).findall(str)[0]
    print("ids为:", len(ids),ids)
    print("name为:", len(names), names)
    print("评论数为:", len(comments), comments)

    # 根据id构造存放每台电脑价格的js包的地址
    # 其网址格式为:https://p.3.cn/prices/mgets?callback=jQuery1702366&type=1&skuIds=J_7512626%2CJ_44354035037%2CJ_100003302532
    str = ''
    for i in range(0, len(ids)):
        if i == 0:
            str = str + 'J_' + ids[i] + '%'
        else:
            str = str + '2CJ_' + ids[i] + '%'
    priceJS_url = 'https://p.3.cn/prices/mgets?callback=jQuery1702366&type=1&skuIds=' + str[:-1]
    # 爬取该js包,获取每台电脑的价格
    response3 = urllib.request.Request(priceJS_url)
    response3.add_header('User-Agent', random.choice(headers))
    data = urllib.request.urlopen(response3, timeout=1).read().decode('utf-8', 'ignore')
    priceStr = re.compile(pat).findall(data)  # priceStr用来存放每个商品关于价格方面的信息
    prices = {}
    for id in ids:
        for str in priceStr:
            if id in str:
                pat3 = '"p":"(.*?)"'
                prices[id] = re.compile(pat3).findall(str)[0]
    print("价格为:", prices)

    # 爬取每个商品的店铺,需要进入到对应的每个电脑的页面去爬取店铺信息
    shops = {}
    for id in ids:
        for href in hrefs:
            if id in href:
                try:
                    response4 = urllib.request.Request(href)
                    response4.add_header('User-Agent', random.choice(headers))
                    data = urllib.request.urlopen(response4, timeout=1).read().decode('gbk', 'ignore')
                    shop = etree.HTML(data).xpath('//*[@id="crumb-wrap"]/div/div[2]/div[2]/div[1]/div/a/@title')
                    print(shop)
                    if shop == []:
                        shops[id] = None
                    else:
                        shops[id] = shop[0]
                    time.sleep(2)
                except Exception as e:
                    print(e)
    # 先去掉电脑名两边的空格和换行符
    [name.strip() for name in names]
    # 将数据分别添加到item中
    for name in names:
        allNames.append(name)
    # 名字对应评论数的字典形式
    for i in range(0, len(ids)):
        if comments[ids[i]] == '':
            allCommentNums[names[i]] = None
        else:
            allCommentNums[names[i]] = comments[ids[i]]
    # 名字与价格对应起来
    for i in range(0, len(ids)):
        if prices[ids[i]] == '':
            allPrices[names[i]] = None
        else:
            allPrices[names[i]] = prices[ids[i]]
    # 名字与店铺对应起来
    for i in range(0, len(ids)):
        allShops[names[i]] = shops[ids[i]]



def tiaoxing(names, prices):
    bar = Bar("笔记本电脑价格图", "X-电脑名,Y-价格")
    bar.add("笔记本电脑", names, prices)
    bar.show_config()
    bar.render("D:\\scrapy\\jingdong\\prices.html")


def bingtu(shopNames, nums):
    attr = shopNames
    v1 = nums
    pie = Pie("笔记本店铺饼图展示")
    pie.add("", attr, v1, is_label_show=True)
    pie.show_config()
    pie.render("D:\\scrapy\\jingdong\\shops.html")


if __name__ == '__main__':
    main()

五、可视化结果

1.运行结果

2.可视化结果

评论数条形统计图:

店铺扇形统计图:

可以看见联想的电脑买的最好。

本文分享自微信公众号 - 小詹学Python(xiaoxiaozhantongxue)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-09-26

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏腾讯高校合作

腾讯网络安全T-Star高校挑战赛 正式启动!!!

? ? T-Star大赛简介 ? “腾讯网络安全T-star高校挑战赛”由腾讯安全应急响应中心(TSRC)与腾讯高校合作联合发起,覆盖全国二十余所高等院校的...

43220
来自专栏FreeBuf

开源软件的供应链安全吗?黑客正在利用源代码传播恶意软件

过去一年里,发生了一连串开源软件遭受供应链攻击的事件,并且态势愈演愈烈。就在最近,甚至发现2个独立的后门漏洞进入了数十万服务器管理员下载的库中。

13120
来自专栏FreeBuf

从Youtube的视频ID和频道ID中发现漏洞

大家好,今天分享这篇Writeup是关于Youtube的两个漏洞,确切来说,是Youtube Studio平台(https://studio.youtube.c...

35630
来自专栏奔跑的人生

XSS漏洞

坚决不要相信任何用户输入并过滤所有特殊字符。这样既可消灭绝大部分的XSS攻击。另一个建议是输出页面时将 < 和 > 变换成 < 和 >。要记住,XSS漏洞极具破...

12810
来自专栏姚红专栏

SELinux深入理解

SELinux带给Linux的主要价值是:提供了一个灵活的,可配置的MAC机制。

20330
来自专栏FreeBuf

通过购物车参数篡改实现低价免费购买商品

本文分享的Writeup是某流行电子商务购物网站的一个参数篡改漏洞(Parameter Tampering),作者利用该漏洞可以更改购物车中商品数量为负数,通过...

10930
来自专栏FreeBuf

梦里参加攻防演习活动的过程分享(上)

随着国家对网络安全的进一步重视,攻防演练活动变得越来越重要,规模也更大。高强度的演习让无论是蓝方还是红方都变得精疲力竭,借用朋友圈里一位大佬的一句话:活动结束的...

12040
来自专栏FreeBuf

威胁预警 | 蠕虫级漏洞BlueKeep(CVE-2019-0708) EXP被公布

Metasploit 在博客和推特上相继发布消息称,Metasploit正式集成针对CVE-2019-0708(也称为BlueKeep)的漏洞利用模块,虽然目前...

21740
来自专栏授客的专栏

安全测试 一次会话安全测试漏洞实例总结

步骤1.按场景所述,打开找回密码页,输入账户(假设账户1)的手机号,验证手机号,然后进入重置密码页面,但是不提交

8120
来自专栏后端开发随笔

细说RESTful API安全之防止重放攻击

百科对重放攻击的描述:https://zh.wikipedia.org/wiki/%E9%87%8D%E6%94%BE%E6%94%BB%E5%87%BB

14430

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励