首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Scrapy实战:爬取一个百度权重为7的化妆品站点

Scrapy实战:爬取一个百度权重为7的化妆品站点

作者头像
禹都一只猫olei
发布2018-05-25 11:39:46
7610
发布2018-05-25 11:39:46
举报

网站为OnlyLady:http://hzp.onlylady.com/brand.html

创建

  • 创建项目
$ scrapy startproject onlylady
  • 创建爬虫
$ cd onlylady
$ scrapy genspider ol hzp.onlylady.com

结构如下:

├── onlylady
│   ├── __init__.py
│   ├── items.py
│   ├── middlewares.py
│   ├── pipelines.py
│   ├── settings.py
│   └── spiders
│       ├── __init__.py
│       └── ol.py
└── scrapy.cfg

需要爬取的信息

  • 获取所有品牌
Scrapy实战:爬取一个百度权重为7的化妆品站点
Scrapy实战:爬取一个百度权重为7的化妆品站点

如图,该页面有所有的品牌,我们按照字母排序开始,获取到所有的品牌链接,并进入

  • 获取某一个品牌所有的商品链接
Scrapy实战:爬取一个百度权重为7的化妆品站点
Scrapy实战:爬取一个百度权重为7的化妆品站点

如果红色框所示,该链接点击进入可以到达所有商品的页面

  • 所有商品的页面之后,进入每个商品的详情页面
Scrapy实战:爬取一个百度权重为7的化妆品站点
Scrapy实战:爬取一个百度权重为7的化妆品站点

获取到所有商品详情页的链接并进入,有一个信息我们要在这个页面爬取,就是商品展示的图片,还有注意还要处理分页的内容

  • 进入详情页
Scrapy实战:爬取一个百度权重为7的化妆品站点
Scrapy实战:爬取一个百度权重为7的化妆品站点

这个页面我们需要商品名、所属品牌名,所属分类、价格(只取第一个)

  • 综上,我们需要商品的

商品名、所属品牌名,所属分类、价格(只取第一个)、商品展示的图片

编写代码逻辑

  • items.py文件,编写的内容就是我们需要获取的信息
# -*- coding: utf-8 -*-

# Define here the models for your scraped items
#
# See documentation in:
# http://doc.scrapy.org/en/latest/topics/items.html

import scrapy

class OnlyLadyItem(scrapy.Item):
    zh_name = scrapy.Field()
    type = scrapy.Field()
    brand = scrapy.Field()
    price = scrapy.Field()
    image_url = scrapy.Field()
  • spider文件夹中的ol.py,也就是爬虫的逻辑文件,获取网页的css标签不做截图说明,自己去网页中查看
# -*- coding: utf-8 -*-
import scrapy

from onlylady.items import OnlyLadyItem


class OlSpider(scrapy.Spider):
    name = 'ol'  # 爬虫名称
    allowed_domains = ['hzp.onlylady.com']  # 允许这个爬虫爬取的域名
    start_urls = ['http://hzp.onlylady.com/brand.html']  # 起始的页面
    headers = {
        "HOST": "hzp.onlylady.com",
        "Referer": "http://hzp.onlylady.com/cosmetics.html",
        "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36"
    }

    # 设置headers,下面的每一个如果要接着爬取的时候,写进入

    def parse(self, response):
        # 获取所有品牌的链接
        brand_urls = response.css('#sortByLetter .brandsWraper a::attr(href)').extract()
        for brand_url in set(brand_urls):
            yield scrapy.Request(brand_url, headers=self.headers, callback=self.more)

    def more(self, response):
        # 进入某个品牌链接之后,获取进入所有商品的链接
        more_url = response.css('.more::attr(href)').extract_first('')
        yield scrapy.Request(more_url, headers=self.headers, callback=self.goods)

    def goods(self, response):
        # 进入所有商品的链接之后,获取商品的详情链接,以及图片链接
        goods_nodes = response.css('.commentItem .left .imgWraper a')
        for goods_node in goods_nodes:
            goods_url = goods_node.css('::attr(href)').extract_first('')  # 获取商品详情页链接
            image_url = goods_node.css('img::attr(src)').extract_first('')  # 获取商品展示图片的连接
            yield scrapy.Request(goods_url, headers=self.headers, meta={"image_url": image_url}, callback=self.detail)
            # meta表示把图片的url暂时存起来,下面的一些函数可以来meta来接收这个参数

        # 获取下一页的信息,处理分页的逻辑
        next_url = response.css('.comment_bar .page .next::attr(href)').extract_first('')
        if next_url:
            yield scrapy.Request(next_url, headers=self.headers, callback=self.goods)

    def detail(self, response):
        # 到达详情页之后,获取详情页中的一些参数,并提交到我们编写的OnlyLadyItem()中,记得要import进来,yield提交items
        zh_name = response.css('.detail_pro .detail_l .p_r .name h2::text').extract_first('')
        type = response.css('.detail_pro .detail_l .p_r dl')[0].css('dd a::attr(title)')[0].extract()
        brand = \
            response.css('.detail_pro .detail_l .p_r dl')[0].css('dd')[1].css('a::attr(title)').extract_first('').split(
                ' ')[0]
        try:
            price = response.css('.price::text').extract_first('').split('¥')[-1]
        except:
            price = ""
        image_url = response.meta.get('image_url', 'image_url')  # 通过response.meta.get来接收上个函数存储的meta中的image_url
        items = OnlyLadyItem()
        items['zh_name'] = zh_name
        items['type'] = type
        items['brand'] = brand
        items['price'] = price
        items['image_url'] = image_url
        yield items

这个爬取逻辑采用的是css选择器来做的,xpath也可以,使用的是response.xpath,标签定位不做说明,我习惯使用css选择器

  • 管道pipelines.py编写,我们获取图片下载,然后其余的东西写到一个txt文件当中
# -*- coding: utf-8 -*-

# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: http://doc.scrapy.org/en/latest/topics/item-pipeline.html

from onlylady.items import OnlyLadyItem
import requests
import os

class IntoTextPipeline(object):
    def process_item(self, item, spider):
        image_path = os.path.join(os.path.dirname(__file__),"onlylady")
        if not os.path.exists(image_path):
            os.makedirs(image_path)
        image_url = item['image_url']
        i = len(os.listdir('onlylady')) + 1
        # file_name = image_path + '/' + 'onlylady_' + str(i) + '.jpg'
        try:
            pic = requests.get(image_url,timeout=10)
        except:
            print("无法下载图片!")
        file_name = image_path + '/' + 'onlylady_' + str(i) + '.jpg'
        f = open(file_name,"wb")
        f.write(pic.content)
        f.close()
        image_name = file_name.split('/')[-1]
        a = [item['zh_name'], item['brand'], item['type'], item['price'], image_name]
        result = ','.join(a)
        with open("onlylady.txt","a") as t:
            t.write(result + "\n")
            t.close()

        return item

TXT文件,一行一个,各个参数用,隔开,最后一个参数是图片名,每个商品与下载的商品图片名一致,便于对应

  • 设置setting.py文件,开启管道,去掉如下注释,添加我们编写的那个pipeline的class名字
ITEM_PIPELINES = {
   # 'onlylady.pipelines.OnlyladyPipeline': 300,
    'onlylady.pipelines.IntoTextPipeline' : 300,
}

300表示先后顺序,越小越优先执行

  • 编写run.py

在项目目录下创建run.py的文件,一键执行爬取操作

# conding:utf8

from scrapy.cmdline import execute

import sys
import os


sys.path.append(os.path.dirname(os.path.abspath(__file__)))
execute(["scrapy", "crawl", "ol"]) # 多个爬取可以写多个这个东西

这样就开始爬取了,因为商品很多,再加上要下载图片,我本地爬取大概用了45分钟左右爬取完毕,总共25535张图片

结束语

  • Scrapy的爬取效率还是很高的
  • 该项目开源。开源地址如下:
  1. github:https://github.com/liwg1995/scrapy_get_cosmetics.git
  2. gitee:https://gitee.com/olei_admin/scrapy_get_cosmetics.git
  3. coding:https://git.coding.net/olei_me/scrapy_get_cosmetics.git
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018-05-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 创建
  • 需要爬取的信息
  • 编写代码逻辑
  • 结束语
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档