用python爬京东商品(一)

##用python爬京东商品(一)

一、环境准备
python3.7 + scrapy1.5

  1. 安装Anaconda(里面包含python,安装过程略)
  2. 从conda-forge安装scrapy(可以减少相应的包依赖的问题)
    conda install -c conda-forge scrapy
  3. 安装ide,这里推荐pyCharm

二、总体流程

  1. 创建项目
    命令行终端,进入一个目录,使用scrapy命令创建项目jdproject,
    scrapy startproject jdproject
  2. pyCharm配置环境
    进入Preferences -> Project -> Project interpreter,选择Anaconda下的python版本(/anaconda3/bin/python3.7)
    在这里插入图片描述
  3. 目录结构
    jdproject/spiders 这个文件夹是用来放具体执行爬虫程序的
    jdproject/items.py 这个文件用来定义返回item实体,例如商品product的name,id和price等
    jdproject/middlewares.py 这个文件用来放中间件处理类,例如downloaderMiddlewares和spiderMiddlewares
    jdproject/pipelines.py 这个文件里定义处理item的类,例如将item写入数据库
    jdproject/settings.py 这个文件里设置了项目的一些参数,例如开启商品管道pipline:ITEM_PIPELINES = { ‘jdproject.pipelines.JdProductPipeline’: 300 }
    在这里插入图片描述
  4. scrapy组件和工作流程
    组件component:
    Scrapy Engine:负责控制系统中所有组件的数据流,当某个action发生时触发事件
    Scheduler:接受来之于Engine的请求并且给他们排队,并进行调度
    Downloader:负责抓取网页上的数据
    Spiders:用户解析响应(然后封装item)的自定义classes
    Item Pipeline:负责处理用户封装好item,典型的任务包括清理、验证和持久化(将数据写入mongo)
    Downloader middlewares:位于Engine和Downloader的中间件,可以在请求从Engine发送到Downloader时处理请求、可以在响应数据返回到Downloader时处理,还可以干很多事
    例如偷偷的更换一个请求等
    Spider middlewares:位于Engine和Spiders的中间件,后处理callback,新增,修改和删除请求和item,或者处理一些spider的异常
    工作流程work flow:
    1⃣Spiders发送原生的请求到Engine
    2⃣Engine将请求交给Scheduler进行调度
    3⃣Scheduler将要执行的请求返回给Engine
    4⃣Engine拿到这个请求发送给Downloader去抓去网页数据,这个过程要经过中组件Downloader middlewares的处理(重写middlewares.py对应的类里的proess_request方法)
    5⃣当Downloader下载完数据后产生一个响应返回给Engine,这个过程要经过中组件Downloader middlewares的处理(重写middlewares.py对应的类里的proess_response方法)
    6⃣Engine将拿到的数据返回给Spiders的parse进行处理,这个过程要经过中组件Spider middlewares的处理(重写middlewares.py对应的类里的process_spider_input方法)
    7⃣spiders处理完并生成对应的item发送给Engine,这个过程要经过中组件Spider middlewares的处理(重写middlewares.py对应的类里的process_spider_output方法)
    8⃣Engine将处理完的item发送给Item Pipeline,并且告诉Scheduler执行下一个crawl请求
    9⃣重复执行上述步骤,直到Scheduler没有可执行的请求
    在这里插入图片描述

三、代码实现
有了上面的介绍,相信大家对具体的流程有了一定的了解,这里先爬一个简单的商品类别,包括id,pid,name,url

  1. 编写productType_spiders.py
    response.css(‘div.category-item’) 查找class = category-item的div
    pta.css(‘div.mt span::text’).extract_first() 提取div下 第一个span标签的value
    具体用法可以参考官方文档,类似的还有xpath和正则
    核心代码:
class JDProductTypeSpider(scrapy.Spider):
    name = 'jdpt'

    start_urls = [
        'https://www.jd.com/allSort.aspx'
    ]

    def parse(self, response):
        ptItem1 = ProductTypeItem()
        ptItem2 = ProductTypeItem()
        ptItem3 = ProductTypeItem()
        # 一级类别
        for pta in response.css('div.category-item'):
            ptItem1['name'] = pta.css('div.mt span::text').extract_first()
            ptItem1url = pta.css('div.items .clearfix dt a::attr(href)').extract_first()
            ptItem1['pid'] = 0
            ptItem1['id'] = ptItem1url.split('/')[-1].split('.')[0].split('-')[0]
            # print(ptItem1)
            # 二级类别
            for ptb in pta.css('div.items .clearfix'):
                ptItem2['name'] = ptb.css('dt a::text').extract_first()
                ptItem2url = ptb.css('dt a::attr(href)').extract_first()
                ptItem2['url'] = ptItem2url
                # print(ptItem2)
                # 三级类别
                for ptc in ptb.css('dd a'):
                    ptItem3['name'] = ptc.xpath('text()').extract_first()
                    ptItem3url = ptc.xpath("@href").extract_first()
                    ptItem3['url'] = ptItem3url
                    try:
                        if ptItem3url.count('?') > 0:
                            ppids = ptItem3url.split('?')[-1].split('=')[-1].split(',')
                            if len(ppids) == 3:
                                ptItem3['id'] = ppids[2]
                                ptItem3['pid'] = ppids[1]
                                ptItem2['id'] = ppids[1]
                                ptItem2['pid'] = ppids[0]
                                ptItem1['id'] = ppids[0]
                            elif len(ppids) == 2:
                                #print(ppids)
                                ptItem2['id'] = ppids[1]
                                ptItem2['pid'] = ppids[0]
                                ptItem1['id'] = ppids[0]
                            else:
                                #print(ptItem3url)
                                if ptItem3url.count('&'):
                                    ttids = ptItem3url.split('&')[0].split('?')[-1].split('=')[-1].split(',')
                                    if len(ttids) == 2:
                                        # print(ttids)
                                        ptItem2['id'] = ttids[1]
                                        ptItem2['pid'] = ttids[0]
                                        ptItem1['id'] = ttids[0]
                        else:
                            #print(ptItem3url)
                            if ptItem3url.count('-') > 0:
                                ptItem2['id'] = ptItem3url.split('/')[-1].split('.')[0].split('-')[1]
                                ptItem2['pid'] = ptItem3url.split('/')[-1].split('.')[0].split('-')[0]
                                ptItem1['id'] = ptItem3url.split('/')[-1].split('.')[0].split('-')[0]

                    except Exception:
                        #print(ptItem3url)
                        pass

                    print(ptItem3)
                    yield ptItem3
                print("----------------")
                print(ptItem2)
                yield ptItem2
            print("++++++++++++++++++++++++++++++++++")
            print(ptItem1)
            yield ptItem1
  1. 编写items.py
    核心代码:
class ProductTypeItem(scrapy.Item):
    id = scrapy.Field()
    pid = scrapy.Field()
    name = scrapy.Field()
    url = scrapy.Field()
    pass
  1. 编写pipelines.py 将items数据入库
    需要安装pymongo
    pip install pymongo
    核心代码:
class JdprojectPipeline(object):

    def __init__(self):
        client = pymongo.MongoClient('127.0.0.1', 27017)
        db = client['jd']
        self.post = db['category']

    def process_item(self, item, spider):
        if isinstance(item, ProductTypeItem):
            postItem = dict(item)
            self.post.insert(postItem)
            print("jdpt")
        else:
            print("other")
        return item
  1. 编写settings.py
    开启上述几项配置开启上述几项配置
ITEM_PIPELINES = {
    'jdproject.pipelines.JdprojectPipeline': 300,
}
  1. 执行代码
    进入项目根目录: cd ./jdproject
    执行crawl命令:scrapy crawl jdpt (这里的jdpt对应为类JDProductTypeSpider里的name)
    在pyCharm调试和执行配置:
    右上角 -> Edit configurations
    在这里插入图片描述

四、代码链接
https://github.com/jieYW/jdproject
五、官方文档
https://docs.scrapy.org/en/latest/

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值