一、环境准备

  • python3.8.3
  • pycharm
  • 项目所需第三方包
pip install scrapy fake-useragent requests selenium virtualenv -i https://pypi.douban.com/simple

1.1 创建虚拟环境

切换到指定目录创建

virtualenv .venv

创建完记得激活虚拟环境

1.2 创建项目

scrapy startproject 项目名称

1.3 使用pycharm打开项目,将创建的虚拟环境配置到项目中来
1.4 创建京东spider

scrapy genspider 爬虫名称 url

1.5 修改允许访问的域名,删除https:

二、问题分析

爬取数据的思路是先获取乐虎体育的基本信息,在获取详情页商品详细信息;爬取京东数据时,只返回40条数据,这里,作者使用selenium,在scrapy框架中编写下载器中间件,返回页面所有数据。
爬取的字段分别是:

商品价格

商品评数

商品店家

商品SKU(京东可直接搜索到对应的产品)

商品标题

商品详细信息

三、spider

import re
import scrapy


from lianjia.items import jd_detailItem


class JiComputerDetailSpider(scrapy.Spider):
    name = 'ji_computer_detail'
    allowed_domains = ['search.jd.com', 'item.jd.com']
    start_urls = [
        'https://search.jd.com/Search?keyword=%E7%AC%94%E8%AE%B0%E6%9C%AC%E7%94%B5%E8%84%91&suggest=1.def.0.base&wq=%E7%AC%94%E8%AE%B0%E6%9C%AC%E7%94%B5%E8%84%91&page=1&s=1&click=0']

    def parse(self, response):
        lls = response.xpath('//ul[@class="gl-warp clearfix"]/li')
        for ll in lls:
            item = jd_detailItem()
            computer_price = ll.xpath('.//div[@class="p-price"]/strong/i/text()').extract_first()
            computer_commit = ll.xpath('.//div[@class="p-commit"]/strong/a/text()').extract_first()
            computer_p_shop = ll.xpath('.//div[@class="p-shop"]/span/a/text()').extract_first()
            item['computer_price'] = computer_price
            item['computer_commit'] = computer_commit
            item['computer_p_shop'] = computer_p_shop
            meta = {
                'item': item
            }
            shop_detail_url = ll.xpath('.//div[@class="p-img"]/a/@href').extract_first()
            shop_detail_url = 'https:' + shop_detail_url
            yield scrapy.Request(url=shop_detail_url, callback=self.detail_parse, meta=meta)
        for i in range(2, 200, 2):
            next_page_url = f'https://search.jd.com/Search?keyword=%E7%AC%94%E8%AE%B0%E6%9C%AC%E7%94%B5%E8%84%91&suggest=1.def.0.base&wq=%E7%AC%94%E8%AE%B0%E6%9C%AC%E7%94%B5%E8%84%91&page={i}&s=116&click=0'
            yield scrapy.Request(url=next_page_url, callback=self.parse)

    def detail_parse(self, response):
        item = response.meta.get('item')
        computer_sku = response.xpath('//a[@class="notice J-notify-sale"]/@data-sku').extract_first()
        item['computer_sku'] = computer_sku
        computer_title = response.xpath('//div[@class="sku-name"]/text()').extract_first().strip()
        computer_title = ''.join(re.findall('\S', computer_title))
        item['computer_title'] = computer_title
        computer_detail = response.xpath('string(//ul[@class="parameter2 p-parameter-list"])').extract_first().strip()
        computer_detail = ''.join(re.findall('\S', computer_detail))
        item['computer_detail'] = computer_detail
        yield item


四、item

class jd_detailItem(scrapy.Item):
    # define the fields for your item here like:
    computer_sku = scrapy.Field()
    computer_price = scrapy.Field()
    computer_title = scrapy.Field()
    computer_commit = scrapy.Field()
    computer_p_shop = scrapy.Field()
    computer_detail = scrapy.Field()

五、setting

import random


from fake_useragent import UserAgent
ua = UserAgent()
USER_AGENT = ua.random
ROBOTSTXT_OBEY = False
DOWNLOAD_DELAY = random.uniform(0.5, 1)
DOWNLOADER_MIDDLEWARES = {
    'lianjia.middlewares.jdDownloaderMiddleware': 543
}
ITEM_PIPELINES = {
    'lianjia.pipelines.jd_csv_Pipeline': 300
}

六、pipelines

class jd_csv_Pipeline:
    # def process_item(self, item, spider):
    #     return item
    def open_spider(self, spider):
        self.fp = open('./jd_computer_message.xlsx', mode='w+', encoding='utf-8')
        self.fp.write('computer_sku\tcomputer_title\tcomputer_p_shop\tcomputer_price\tcomputer_commit\tcomputer_detail\n')

    def process_item(self, item, spider):
        # 写入文件
        try:
            line = '\t'.join(list(item.values())) + '\n'
            self.fp.write(line)
            return item
        except:
            pass

    def close_spider(self, spider):
        # 关闭文件
        self.fp.close()

七、middlewares

class jdDownloaderMiddleware:
    def process_request(self, request, spider):
        # 判断是否是ji_computer_detail的爬虫
        # 判断是否是乐虎体育
        if spider.name == 'ji_computer_detail' and re.findall(f'.*(item.jd.com).*', request.url) == []:
            options = ChromeOptions()
            options.add_argument("--headless")
            driver = webdriver.Chrome(options=options)
            driver.get(request.url)
            for i in range(0, 15000, 5000):
                driver.execute_script(f'window.scrollTo(0, {i})')
                time.sleep(0.5)
            body = driver.page_source.encode()
            time.sleep(1)
            return HtmlResponse(url=request.url, body=body, request=request)
        return None

八、使用jupyter进行简单的处理和分析

其他文件:百度停用词库、简体字文件
下载第三方包

!pip install seaborn jieba wordcloud PIL  -i https://pypi.douban.com/simple

8.1导入第三方包

import re
import os
import jieba
import wordcloud
import pandas as pd
import numpy as np
from PIL import Image
import seaborn as sns
from docx import Document
from docx.shared import Inches
import matplotlib.pyplot as plt
from pandas import DataFrame,Series

8.2设置可视化的默认字体和seaborn的样式

sns.set_style('darkgrid')
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

8.3读取数据

df_jp = pd.read_excel('./jd_shop.xlsx')

8.4筛选Inteli5、i7、i9处理器数据

def convert_one(s):
    if re.findall(f'.*?(i5).*', str(s)) != []:
        return re.findall(f'.*?(i5).*', str(s))[0]
    elif re.findall(f'.*?(i7).*', str(s)) != []:
        return re.findall(f'.*?(i7).*', str(s))[0]
    elif re.findall(f'.*?(i9).*', str(s)) != []:
        return re.findall(f'.*?(i9).*', str(s))[0]
df_jp['computer_intel'] = df_jp['computer_detail'].map(convert_one)

8.5筛选笔记本电脑的屏幕尺寸范围

def convert_two(s):
    if re.findall(f'.*?(\d+\.\d+英寸-\d+\.\d+英寸).*', str(s)) != []:
        return re.findall(f'.*?(\d+\.\d+英寸-\d+\.\d+英寸).*', str(s))[0]
df_jp['computer_in'] = df_jp['computer_detail'].map(convert_two)

8.6将评论数转化为整形

def convert_three(s):
    if re.findall(f'(\d+)万+', str(s)) != []:
        number = int(re.findall(f'(\d+)万+', str(s))[0]) * 10000
        return number
    elif re.findall(f'(\d+)+', str(s)) != []:
        number = re.findall(f'(\d+)+', str(s))[0]
        return number
df_jp['computer_commit'] = df_jp['computer_commit'].map(convert_three)

8.7筛选出需要分析的品牌

def find_computer(name, s):
    sr = re.findall(f'.*({name}).*', str(s))[0]
    return sr
def convert(s):
    if re.findall(f'.*(联想).*', str(s)) != []:
        return find_computer('联想', s)
    elif re.findall(f'.*(惠普).*', str(s)) != []:
        return find_computer('惠普', s)
    elif re.findall(f'.*(华为).*', str(s)) != []:
        return find_computer('华为', s)
    elif re.findall(f'.*(戴尔).*', str(s)) != []:
        return find_computer('戴尔', s)
    elif re.findall(f'.*(华硕).*', str(s)) != []:
        return find_computer('华硕', s)
    elif re.findall(f'.*(小米).*', str(s)) != []:
        return find_computer('小米', s)
    elif re.findall(f'.*(荣耀).*', str(s)) != []:
        return find_computer('荣耀', s)
    elif re.findall(f'.*(神舟).*', str(s)) != []:
        return find_computer('神舟', s)
    elif re.findall(f'.*(外星人).*', str(s)) != []:
        return find_computer('外星人', s)
df_jp['computer_p_shop'] = df_jp['computer_p_shop'].map(convert)

8.8删除指定字段为空值的数据

for n in ['computer_price', 'computer_commit', 'computer_p_shop', 'computer_sku', 'computer_detail', 'computer_intel', 'computer_in']:
    index_ls = df_jp[df_jp[[n]].isnull().any(axis=1)==True].index
    df_jp.drop(index=index_ls, inplace=True)

8.9查看各品牌的平均价格

plt.figure(figsize=(10, 8), dpi=100)
ax = sns.barplot(x='computer_p_shop', y='computer_price', data=df_jp.groupby(by='computer_p_shop')[['computer_price']].mean().reset_index())
for index,row in df_jp.groupby(by='computer_p_shop')[['computer_price']].mean().reset_index().iterrows():
    ax.text(row.name,row['computer_price'] + 2,round(row['computer_price'],2),color="black",ha="center")
ax.set_xlabel('品牌')
ax.set_ylabel('平均价格')
ax.set_title('各品牌平均价格')
boxplot_fig = ax.get_figure()
boxplot_fig.savefig('各品牌平均价格.png', dpi=400)

8.10 查看各品牌的价格区间

plt.figure(figsize=(10, 8), dpi=100)
ax = sns.boxenplot(x='computer_p_shop', y='computer_price', data=df_jp.query('computer_price>500'))
ax.set_xlabel('品牌')
ax.set_ylabel('价格区间')
ax.set_title('各品牌价格区间')
boxplot_fig = ax.get_figure()
boxplot_fig.savefig('各品牌价格区间.png', dpi=400)

8.11 查看价格与评论数的关系

df_jp['computer_commit'] = df_jp['computer_commit'].astype('int64')
ax = sns.jointplot(x="computer_commit", y="computer_price", data=df_jp, kind="reg", truncate=False,color="m", height=10)
ax.fig.savefig('评论数与价格的关系.png')

8.12 查看商品标题里出现的关键词

import imageio

# 将特征转换为列表
ls = df_jp['computer_title'].to_list()
# 替换非中英文的字符
feature_points = [re.sub(r'[^a-zA-Z\u4E00-\u9FA5]+',' ',str(feature)) for feature in ls]
# 读取停用词
stop_world = list(pd.read_csv('./百度停用词表.txt', engine='python', encoding='utf-8', names=['stopwords'])['stopwords'])
feature_points2 = []
for feature in feature_points:  # 遍历每一条评论
    words = jieba.lcut(feature) # 精确模式,没有冗余.对每一条评论进行jieba分词
    ind1 = np.array([len(word) > 1 for word in words])  # 判断每个分词的长度是否大于1
    ser1 = pd.Series(words)
    ser2 = ser1[ind1] # 筛选分词长度大于1的分词留下
    ind2 = ~ser2.isin(stop_world)  # 注意取反负号
    ser3 = ser2[ind2].unique()  # 筛选出不在停用词表的分词留下,并去重
    if len(ser3) > 0:
        feature_points2.append(list(ser3))
# 将所有分词存储到一个列表中
wordlist = [word for feature in feature_points2 for word in feature]
# 将列表中所有的分词拼接成一个字符串
feature_str =  ' '.join(wordlist)   
# 标题分析
font_path = r'./simhei.ttf'
shoes_box_jpg = imageio.imread('./home.jpg')
wc=wordcloud.WordCloud(
    background_color='black',
    mask=shoes_box_jpg,
    font_path = font_path,
    min_font_size=5,
    max_font_size=50,
    width=260,
    height=260,
)
wc.generate(feature_str)
plt.figure(figsize=(10, 8), dpi=100)
plt.imshow(wc)
plt.axis('off')
plt.savefig('标题提取关键词')

8.13 筛选价格在4000到5000,联想品牌、处理器是i5、屏幕大小在15寸以上的数据并查看价格

df_jd_query = df_jp.loc[(df_jp['computer_price'] <=5000) & (df_jp['computer_price']>=4000) & (df_jp['computer_p_shop']=="联想") & (df_jp['computer_intel']=="i5") & (df_jp['computer_in']=="15.0英寸-15.9英寸"), :].copy()
plt.figure(figsize=(20, 10), dpi=100)
ax = sns.barplot(x='computer_sku', y='computer_price', data=df_jd_query)
ax.set_xlabel('联想品牌SKU')
ax.set_ylabel('价格')
ax.set_title('酷睿i5处理器屏幕15寸以上各SKU的价格')
boxplot_fig = ax.get_figure()
boxplot_fig.savefig('酷睿i5处理器屏幕15寸以上各SKU的价格.png', dpi=400)

8.14 筛选价格在4000到5000,戴尔品牌、处理器是i7、屏幕大小在15寸以上的数据并查看价格

df_jp_daier = df_jp.loc[(df_jp['computer_price'] <=5000) & (df_jp['computer_price']>=4000) & (df_jp['computer_p_shop']=="戴尔") & (df_jp['computer_intel']=="i7") & (df_jp['computer_in']=="15.0英寸-15.9英寸"), :].copy()
plt.figure(figsize=(10, 8), dpi=100)
ax = sns.barplot(x='computer_sku', y='computer_price', data=df_jp_daier)
ax.set_xlabel('戴尔品牌SKU')
ax.set_ylabel('价格')
ax.set_title('酷睿i7处理器屏幕15寸以上各SKU的价格')
boxplot_fig = ax.get_figure()
boxplot_fig.savefig('酷睿i7处理器屏幕15寸以上各SKU的价格.png', dpi=400)

8.15 不同Intel处理器品牌的价格

plt.figure(figsize=(10, 8), dpi=100)
ax = sns.barplot(x='computer_p_shop', y='computer_price', data=df_jp, hue='computer_intel')
ax.set_xlabel('品牌')
ax.set_ylabel('价格')
ax.set_title('不同酷睿处理器品牌的价格')
boxplot_fig = ax.get_figure()
boxplot_fig.savefig('不同酷睿处理器品牌的价格.png', dpi=400)

8.16 不同尺寸品牌的价格

plt.figure(figsize=(10, 8), dpi=100)
ax = sns.barplot(x='computer_p_shop', y='computer_price', data=df_jp, hue='computer_in')
ax.set_xlabel('品牌')
ax.set_ylabel('价格')
ax.set_title('不同尺寸品牌的价格')
boxplot_fig = ax.get_figure()
boxplot_fig.savefig('不同尺寸品牌的价格.png', dpi=400)

以上就是python基于scrapy爬取京东笔记本电脑数据并进行简单处理和分析的详细内容,更多关于python 爬取京东数据的资料请关注程序员的世界其它相关文章!

python基于scrapy爬取京东笔记本电脑数据并进行简单处理和分析的更多相关文章

  1. python中用ggplot绘制画图实例讲解

    Python的绘图库也允许用户创建优雅的图形,本章给大家介绍的是关于ggplot绘制画图的技巧,ggplot2建立在grid系统上,这个系统不支持纹理。需要额外创建一堆数据,再基于这些数据构建一个geom_path图层,盖在柱图上才可以进行各种绘制,下面给大家详细讲解下怎么使用ggplot绘图。简介......

  2. 爬虫-urllib3模块的使用

    urllib3是一个功能强大,对SAP健全的 HTTP客户端,许多Python生态系统已经使用了urllib3。一、安装sudo pips install urllib3二、创建PoolManager对象通过urllib3访问网页,首先需要构造一个PoolManager实例对象用于处理与线程池的连接......

  3. Python 使用dict实现switch的操作

    Python3还是没有switch,可以利用if-else来实现,但是非常不方便。使用dict来实现会比较简洁优雅。# -*- coding: utf-8 -*-"""Python利用dict实现switch""" def add(x, y......

  4. python中温度单位转换的实例方法

    温度有摄氏度和华氏度两个单位,我们通常使用的是摄氏度,对于转换成华氏度,很多小伙伴记不住公式。作为万能的计算机,它是可以帮助我们解决温度单位转换的问题。本文主要演示python中进行温度单位转换的代码过程,具体请看本文。一、问题温度有摄氏度(Celsius)和华氏度(Fabrenheit)两个不同的......

  5. python 调用js的四种方式

    1. 前言日常 Web 端爬虫过程中,经常会遇到参数被加密的场景,因此,我们需要分析网页源代码通过调式,一层层剥离出关键的 JS 代码,使用 Python 去执行这段代码,得出参数加密前后的 Python 实现本文将聊聊利用 Python 调用 JS 的4种方式2. 准备以一段简单的 ......

  6. Python实现贪心算法的示例

    今天一个研究生同学问我一个问题,问题如下:超市有m个顾客要结账,每个顾客结账的时间为Ti( i取值从1到m)。超市有n个结账出口,请问全部顾客怎么选择出口,可以最早完成全部顾客的结账,并用代码实现。其实利用的就是贪心算法来解决这个问题,那么,什么是贪心算法?怎么用贪心算法解决这个问题?让我一一道来。......

  7. Python中使用Lambda函数的5种用法

    引言Lambda 函数(也称为匿名函数)是函数式编程中的核心概念之一。支持多编程范例的 Python 也提供了一种简单的方法来定义 lambda 函数。用 Python 编写 lambda 函数的模板是:lambda arguments : expression它包括三个部分:· Lamb......

  8. 用python60行代码写一个简单的笔趣阁爬虫

    系列文章目录python爬虫实战——爬取淘宝商品信息并导入EXCEL表格(超详细)python多线程爬取壁纸 妈妈再也不担心我没壁纸了!.python爬虫爬取虎牙数据(简单利用requests库以及Beautifulsoup).python爬虫之爬取壁纸(新手入门级).python爬虫实战——爬取猫......

  9. 五分钟学会怎么用Pygame做一个简单的贪吃蛇

    Pygame 是一组用来开发游戏软件的 Python 程序模块,基于 SDL 库的基础上开发。我们今天将利用它来制作一款大家基本都玩过的小游戏——贪吃蛇。一、需要导入的包?123import pygameimport timeimport randompygame:获取图形组件构建游戏time:主要......

  10. pytorch单维筛选 相乘

    m需要和筛选的结果维度相同>0.5运行的结果与原来维度相同,结果是 0 1,0代不符合,1代表符合。import torchm=torch.Tensor([0.1,0.2,0.3]).cuda()iou=torch.Tensor([0.5,0.6,0.7])x= m * ((iou > ......

随机推荐

  1. 详解Redis 分布式锁遇到的序列化问题

    场景描述最近使用 Redis 遇到了一个类似分布式锁的场景,跟 Redis 实现分布式锁类比一下,就是释放锁失败,也就是缓存删不掉。又踩了一个 Redis 的坑……这是什么个情况、又是怎样排查的呢?本文主要对此做个复盘。问题排查既然是释放锁有问题,那就先看看释放锁的代码吧。释放锁释放锁使用了 Lua......

  2. 透过现象看本质:Java类动态加载和热替换

    摘要:本文主要介绍类加载器、自定义类加载器及类的加载和卸载等内容,并举例介绍了Java类的热替换。最近,遇到了两个和Java类的加载和卸载相关的问题:1) 是一道关于Java的判断题:一个类被首次加载后,会长期留驻JVM,直到JVM退出。这个说法,是不是正确的?2) 在开发的一个集成平台中,需要集成......

  3. Python opencv操作深入详解

    直接读取图片def display_img(file="p.jpeg"):img = cv.imread(file)print (img.shape)cv.imshow('image',img)cv.waitKey(0)cv.destroyAllWindows()读取灰度图片de......

  4. 一个非常棒的Go-Json解析库

    json是一种数据格式,经常被用作数据交换,页面展示,序列化等场景,基本每种语言都有对应的json解析框架,Go语言也不例外,并且内置了json库,基本能够满足一些普通开发场景,但有些复杂场景下就不太理想了,因此找一个好用的开源的json库就非常有必要了,先放地址https://github.com......

  5. C# 合并和拆分PDF文件

    一、合并和拆分PDF文件的方式 PDF文件使用了工业标准的压缩算法,易于传输与储存。它还是页独立的,一个PDF文件包含一个或多个“页“,可以单独处理各页,特别适合多处理器系统的工作。PDF文件结构主要可以分为四个部分:首部、文件体、交叉引用表、尾部。PDF操作类库非常多,如下图所示,常用的类库有:S......

  6. MySQL中外键的创建、约束以及删除

    前言在MySQL 3.23.44版本后,InnoDB引擎类型的表支持了外键约束。外键的使用条件:1.两个表必须是InnoDB表,MyISAM表暂时不支持外键(据说以后的版本有可能支持,但至少目前不支持);2.外键列必须建立了索引,MySQL 4.1.2以后的版本在建立外键时会自动创建索引,但如果在较......

  7. Java序列化

    1.什么是序列化Java序列化是指把Java对象转换为字节序列的过程,而Java反序列化是指把字节序列恢复为Java对象的过程:序列化:对象序列化的最主要的用处就是在传递和保存对象的时候,保证对象的完整性和可传递性。序列化是把对象转换成有序字节流,以便在网络上传输或者保存在本地文件中。核心作用是对象......

  8. Java中Jackson快速入门

    Java生态圈中有很多处理JSON和XML格式化的类库,Jackson是其中比较著名的一个。虽然JDK自带了XML处理类库,但是相对来说比较低级,使用本文介绍的Jackson等高级类库处理起来会方便很多。引入类库由于Jackson相关类库按照功能分为几个相对独立的,所以需要同时引入多个类库,为了方便......

  9. 通过js正则表达式实例学习正则表达式基本语法

    正则表达式对于初学者来说是一个比较难理解的知识点,本文主要以实例来讲解正则表达式应该怎么样使用,希望对读者有所帮助正则表达式又叫规则表达式,一般用来检查字符串中是否有与规则相匹配的子串,达到可以对匹配的子串进行提取、删除、替换等操作的目的。先了解有哪些方法可以使用正则对字符串来实现这些操作:RegE......

  10. python 如何用map()函数创建多线程任务

    对于多线程的使用,我们经常是用thread来创建,比较繁琐. 在Python中,可以使用map函数简化代码。map可以实现多任务的并发简单说明map()实现多线程原理:task = [‘任务1', ‘任务2', ‘任务3', …]map 函数一手包办了序列操作、参数传递和结果保存等一系列的操作,ma......