Python爬虫_案例分析(一)

Python爬虫_案例分析(一)

一、爬取数据

# dang.py
import scrapy
class DangSpider(scrapy.Spider):
    name = 'dang'
    allowed_domains = ['category.dangdang.com/cp01.01.02.00.00.00.html']
    start_urls = ['http://category.dangdang.com/cp01.01.02.00.00.00.html']

    def parse(self, response):
        # pipelines 下载数据
        # items 定义数据结构
        # src = '//ul[@id="component_59"]/li//img/@src'
        # title = '//ul[@id="component_59"]/li//img/@alt'
        # price = '//ul[@id="component_59"]/li//p[@class="price"]/span[1]/text()'
        # 所有的seletor对象都可以再次调用xpath方法
        li_list = response.xpath('//ul[@id="component_59"]/li')
        for li in li_list:
            src = li.xpath('.//img/@data-original').extract_first()
            # 网站有懒加载机制,故图片路径不是src采用data-original;
            # 同时第一张图片没有data-original,要用src
            if src:
                src = src
            else:
                src = li.xpath('.//img/@src').extract_first()
            title = li.xpath('.//img/@alt').extract_first()
            price = li.xpath('.//p[@class="price"]/span[1]/text()').extract_first()
            print(src,title,price)
# items.py
# Define here the models for your scraped items
#
# See documentation in:
# https://docs.scrapy.org/en/latest/topics/items.html
import scrapy
class ScrapyDangdangItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    # 图片
    src = scrapy.Field()
    # 名字
    name = scrapy.Field()
    # 价格
    price = scrapy.Fiele()

在这里插入图片描述

二、管道封装

import scrapy
from scrapy_dangdang.items import ScrapyDangdangItem
class DangSpider(scrapy.Spider):
    name = 'dang'
    allowed_domains = ['category.dangdang.com/cp01.01.02.00.00.00.html']
    start_urls = ['http://category.dangdang.com/cp01.01.02.00.00.00.html']

    def parse(self, response):
        # pipelines 下载数据
        # items 定义数据结构
        # src = '//ul[@id="component_59"]/li//img/@src'
        # title = '//ul[@id="component_59"]/li//img/@alt'
        # price = '//ul[@id="component_59"]/li//p[@class="price"]/span[1]/text()'
        # 所有的seletor对象都可以再次调用xpath方法
        li_list = response.xpath('//ul[@id="component_59"]/li')
        for li in li_list:
            src = li.xpath('.//img/@data-original').extract_first()
            # 网站有懒加载机制,故图片路径不是src采用data-original;
            # 同时第一张图片没有data-original,要用src
            if src:
                src = src
            else:
                src = li.xpath('.//img/@src').extract_first()
            title = li.xpath('.//img/@alt').extract_first()
            price = li.xpath('.//p[@class="price"]/span[1]/text()').extract_first()
            book = ScrapyDangdangItem(src=src,title=title,price=price)
            # 获取一个book,就将book交给pipelines
            yield book
from itemadapter import ItemAdapter
# 如果想要使用管道,则必须在settings中开启管道
class ScrapyDangdangPipeline:
    # item是yield后面的book对象
    def process_item(self, item, spider):
        # 下载数据  这种模式不推荐,每传递一个文件对象就打开一次文件,对文件操作过于频繁

        # (1)write方法必须要写一个字符串,而不能是其他对象
        # (2)w模式,会每一次对象都打开一次文件,覆盖掉之前的文件内容
        with open('book.json','a',encoding='utf-8')as fp:
            fp.write(str(item))
        return item

在这里插入图片描述
上述这种模式不推荐,每传递一个文件对象就打开一次文件,对文件操作过于频繁。
案例改进:

from itemadapter import ItemAdapter
# 如果想要使用管道,则必须在settings中开启管道
class ScrapyDangdangPipeline:
    # 在爬虫文件执行前执行
    def open_spider(self,spider):
        self.fp = open('book.json','w',encoding='utf-8')
    # item是yield后面的book对象
    def process_item(self, item, spider):
        # 下载数据  这种模式不推荐,每传递一个文件对象就打开一次文件,对文件操作过于频繁
        # (1)write方法必须要写一个字符串,而不能是其他对象
        # (2)w模式,会每一次对象都打开一次文件,覆盖掉之前的文件内容
        # with open('book.json','a',encoding='utf-8')as fp:
        #     fp.write(str(item))
        self.fp.write(str(item))
        return item
    # 在爬虫文件执行完之后执行
    def close_spider(self,spider):
        self.fp.close()

三、多条管道下载

import urllib.request
# 多条管道开启
# (1) 定义管道类
# (2) 在settings中开启多条管道 :  'scrapy_dangdang.pipelines.DangDangDownloadPipeline':301
class DangDangDownloadPipeline:
    def process_item(self, item, spider):
        url = 'http:' + item.get('src')
        filename = './books/'+ item.get('title') + '.jpg'
        urllib.request.urlretrieve(url=url,filename=filename)
        return item

四、多页下载

1.dang.py

import scrapy
from scrapy_dangdang.items import ScrapyDangdangItem
class DangSpider(scrapy.Spider):
    name = 'dang'
    #如果是多页下载,必须要调整allowed_domains的范围,一般情况下只写域名
    allowed_domains = ['category.dangdang.com']
    start_urls = ['http://category.dangdang.com/cp01.01.02.00.00.00.html']
    base_url = 'http://category.dangdang.com/pg'
    page = 1
    def parse(self, response):
        # pipelines 下载数据
        # items 定义数据结构
        # src = '//ul[@id="component_59"]/li//img/@src'
        # title = '//ul[@id="component_59"]/li//img/@alt'
        # price = '//ul[@id="component_59"]/li//p[@class="price"]/span[1]/text()'
        # 所有的seletor对象都可以再次调用xpath方法
        li_list = response.xpath('//ul[@id="component_59"]/li')
        for li in li_list:
            src = li.xpath('.//img/@data-original').extract_first()
            # 网站有懒加载机制,故图片路径不是src采用data-original;
            # 同时第一张图片没有data-original,要用src
            if src:
                src = src
            else:
                src = li.xpath('.//img/@src').extract_first()
            title = li.xpath('.//img/@alt').extract_first()
            price = li.xpath('.//p[@class="price"]/span[1]/text()').extract_first()
            book = ScrapyDangdangItem(src=src,title=title,price=price)
            # 获取一个book,就将book交给pipelines
            yield book
            # 每一页爬取的业务逻辑全都是一样的,只需要将执行的请求再次调用parse方法
            # http://category.dangdang.com/pg2-cp01.01.02.00.00.00.html
            # http://category.dangdang.com/pg3-cp01.01.02.00.00.00.html
            if self.page < 100 :
                self.page = self.page + 1
                url = self.base_url + str(self.page) + '-cp01.01.02.00.00.00.html'
                # 如何调用parse方法
                # scrapy.Request就是scrapy的get请求; url就是请求地址; callback是需要执行的函数,不需要加()
                yield scrapy.Request(url=url,callback=self.parse)

2.items.py

import scrapy
class ScrapyDangdangItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    # 图片
    src = scrapy.Field()
    # 名字
    title = scrapy.Field()
    # 价格
    price = scrapy.Field()

3.settings.py

ITEM_PIPELINES = {
    
    
    # 管道可以有很多,而管道具有优先级,优先级的范围是1~1000,值越小,优先级越高
   'scrapy_dangdang.pipelines.ScrapyDangdangPipeline': 300,
   # DangDangDownloadPipeline
   'scrapy_dangdang.pipelines.DangDangDownloadPipeline':301
}

4.Pipelines.py

from itemadapter import ItemAdapter
# 如果想要使用管道,则必须在settings中开启管道
class ScrapyDangdangPipeline:
    # 在爬虫文件执行前执行
    def open_spider(self,spider):
        self.fp = open('book.json','w',encoding='utf-8')

    # item是yield后面的book对象
    def process_item(self, item, spider):
        # 下载数据  这种模式不推荐,每传递一个文件对象就打开一次文件,对文件操作过于频繁

        # (1)write方法必须要写一个字符串,而不能是其他对象
        # (2)w模式,会每一次对象都打开一次文件,覆盖掉之前的文件内容
        # with open('book.json','a',encoding='utf-8')as fp:
        #     fp.write(str(item))
        self.fp.write(str(item))
        return item
    # 在爬虫文件执行完之后执行
    def close_spider(self,spider):
        self.fp.close()
import urllib.request
# 多条管道开启
# (1) 定义管道类
# (2) 在settings中开启多条管道 :  'scrapy_dangdang.pipelines.DangDangDownloadPipeline':301
class DangDangDownloadPipeline:
    def process_item(self, item, spider):
        url = 'http:' + item.get('src')
        filename = './books/'+ item.get('title') + '.jpg'
        urllib.request.urlretrieve(url=url,filename=filename)
        return item

在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_45556665/article/details/125481458