【Scrapy框架之请求传参案例】 -- 2019-08-08 20:40:13

原文: http://106.13.73.98/__/141/

在某些情况下,我们爬取的数据不在同一个页面。

例如下面的案例1,我们要爬取一个电影网站,电影的排名、名称、主演分在一页,而其它的信息分在二级子页面中。这时,我们就需要用到请求传参。

案例1:爬取97电影网中所有热门电影的详细信息



97电影网热门电影URL:http://www.55xia.com/movie/hotest/

第一步,爬虫文件:

# -*- coding: utf-8 -*-
import scrapy
from Test.items import TestItem

# 请求传参
class Test01Spider(scrapy.Spider):
    name = 'test01'
    start_urls = ['http://www.55xia.com/movie/hotest/']  # 97电影网热门电影

    def parse(self, response):
        # 获取所有电影的div
        div_list = response.xpath('//div[@class="container-fluid"]/div[@class="media"]')
        for div in div_list:
            # 准备item对象
            item = TestItem()
            item['ranking'] = div.xpath('.//a[2]/text()').extract_first().strip()  # 排行
            item['title'] = div.xpath('.//div[@class="media-body"]/div[2]/dl/dt/h4//text()').extract_first().strip()  # 名称
            starring_list = div.xpath('.//div[@class="media-body"]/div[2]/dl/dd/ul/li[2]//text()')  # 主演列表
            # 格式转换
            for index, starring in enumerate(starring_list):
                starring_list[index] = starring.extract().strip()
            item['starring'] = ' '.join(starring_list)  # 所有主演

            # 获取电影详情的url
            detail_page = div.xpath('.//div[@class="media-body"]/div[2]/dl/dt/h4/a/@href').extract_first()

            # 有的电影没有详情页面,没有的则不再获取其详情
            if detail_page:
                # 开始拼接电影详情页面的url
                detail_url = 'http://www.55xia.com' + detail_page
                # 手动发起请求
                yield scrapy.Request(url=detail_url, callback=self.get_detail_page, meta={'item': item})   # ??
                # callback:指定回调函数,即解析的方法
                # meta={'item': item}:实现请求传参,??
            # 没有详情页面的直接提交给管道
            else:
                yield item

        # 递归获取所有页面的内容
        page_url = 'http://www.55xia.com/movie/hotest?page=%d'
        for i in range(2, 6):
            url = format(page_url % i)
            yield scrapy.Request(url=url, callback=self.parse)

    # 自己定义的解析方法,用于解析新页面中电影的详情
    def get_detail_page(self, response):
        item = response.meta['item']
        item['director'] = > response.xpath('/html/body/div[1]/div/div/div[1]/div[1]/div[2]/table/tbody/tr[1]/td[2]/a/text()').extract_first()  # 导演
        item['writers'] = response.xpath('/html/body/div[1]/div/div/div[1]/div[1]/div[2]/table/tbody/tr[2]/td[2]/a/text()').extract_first()  # 编剧
        item['type'] = response.xpath('/html/body/div[1]/div/div/div[1]/div[1]/div[2]/table/tbody/tr[3]/td[2]/a/text()').extract_first()  # 类型
        item['region'] = response.xpath('/html/body/div[1]/div/div/div[1]/div[1]/div[2]/table/tbody/tr[4]/td[2]/a/text()').extract_first()  # 地区
        item['language'] = response.xpath('/html/body/div[1]/div/div/div[1]/div[1]/div[2]/table/tbody/tr[5]/td[2]/text()').extract_first()  # 语言
        item['release_time'] = response.xpath('/html/body/div[1]/div/div/div[1]/div[1]/div[2]/table/tbody/tr[6]/td[2]/text()').extract_first()  # 上映时间
        # 提交给管道
        yield item

第二步,数据结构模板文件:

import scrapy

class TestItem(scrapy.Item):
    # define the fields for your item here like:
    ranking = scrapy.Field()  # 排行
    title = scrapy.Field()  # 名称
    starring = scrapy.Field()  # 主演
    director = scrapy.Field()  # 导演
    writers = scrapy.Field()  # 编剧
    type = scrapy.Field()  # 类型
    region = scrapy.Field()  # 地区
    language = scrapy.Field()  # 语言
    release_time = scrapy.Field()  # 上映时间

第三步,管道文件:

import json

class TestPipeline(object):
    # fp = None  # 用于文件操作符

    # 重写父类方法,用于打开文件
    def open_spider(self, spider):
        """此方法在运行爬虫文件时自动执行,注意:只会执行一次"""
        self.fp = open('./text.txt', 'w', encoding='utf-8')

    def process_item(self, item, spider):
        # 开始写入文件
        self.fp.write(json.dumps(item.__dict__['_values'], ensure_ascii=False) + '\n')
        # ensure_ascii=False 这样可使数据显示的为中文
        return item  # 如果你还有其它的(优先级低的)管道类,那么你一定要返回item

    # 重写父类方法,用于关闭文件
    def close_spider(self, spider):
        """此方法在结束爬虫文件时自动执行,注意:只会执行一次"""
        self.fp.flush()
        self.fp.close()

第四步,配置文件:

# 开启管道类
ITEM_PIPELINES = {
   'Test.pipelines.TestPipeline': 300,
}

展示效果图:

案例2:爬取彼岸图网的所有图片



第一步,爬虫文件:

# -*- coding: utf-8 -*-
import scrapy
from Test.items import TestItem

class Test01Spider(scrapy.Spider):
    name = 'test01'
    start_urls = ['http://pic.netbian.com/']  # 彼岸图网

    max_page = 100  # 你想要下载多少页图片
    present_page = 2  # 用于标识当前所在的页面
    url = 'http://pic.netbian.com/index_%d.html'  # 用于定位页面的url

    def parse(self, response):
        # 获取每张图片所在的li
        li_list = response.xpath('//ul[@class="clearfix"]/li')

        # 开始解析数据:
        for li in li_list:
            img_src = li.xpath('.//a//img/@src').extract_first()  # type: str  # 获取所有每张图片的路径
            item = TestItem()
            item['name'] = img_src.split('/')[-1]  # 保存图片名称
            img_url = self.start_urls[0] + img_src  # 每张图片的链接
            # 手动向每张图片链接发起请求
            yield scrapy.Request(img_url, callback=self.get_img, meta={'item': item})  # !
            # callback:指定回调函数,即解析的方法
            # meta={'item': item}:请求传参

        # 递归解析所有页面数据
        if self.present_page <= self.max_page:
            url = format(self.url % self.present_page)
            yield scrapy.Request(url, callback=self.parse)
            self.present_page += 1

    def get_img(self, response):
        item = response.meta['item']  # 提取传过来的参数
        item['img_data'] = response.body  # 获取图片bytes数据
        yield item  # 提交给管道

第二步,数据结构模板文件:

import scrapy

class TestItem(scrapy.Item):
    # define the fields for your item here like:
    name = scrapy.Field()  # 图片名称
    img_data = scrapy.Field()  # 图片bytes数据

第三步,管道文件:

import os

class TestPipeline(object):
    def open_spider(self, spider):
        # 定义好用于保存文件的路径
        self.dirname = r'C:\Users\zyg\Desktop\彼岸花\\'
        # 如果不存在此文件夹,则创建
        if not os.path.exists(self.dirname):
            os.mkdir(self.dirname)

    def process_item(self, item, spider):
        img_path = self.dirname + item['name']
        with open(img_path, 'wb') as fp:
            fp.write(item['img_data'])
        return item

第四步,配置文件:

# 开启管道类
ITEM_PIPELINES = {
   'Test.pipelines.TestPipeline': 300,
}

# 下载量较大,所以我们这里将开启的线程数加大
CONCURRENT_REQUESTS = 200

展示效果图:

原文: http://106.13.73.98/__/141/

原文地址:https://www.cnblogs.com/gqy02/p/11323701.html

时间: 2024-10-09 01:42:50

【Scrapy框架之请求传参案例】 -- 2019-08-08 20:40:13的相关文章

scrapy入门(二)请求传参和中间件

scrapy的请求传参 作用 : 实现深度爬取 使用场景 : 爬取的数据没有在同一张页面 例如, 爬取电影首页全部电影的详情页信息 #请求传参: 让Request将一个数据值(字典)传递给回调函数 #在第一页中将item对象的第一个属性赋值,然后通过请求传参将item对象传过去 #手动发送get请求: model_index = [3,4,6,7,8] for index in model_list: li =li_list[index] model_url = li.xpath('xxxxxx

scrapy框架的日志等级和请求传参, 优化效率

目录 scrapy框架的日志等级和请求传参, 优化效率 Scrapy的日志等级 请求传参 如何提高scripy的爬取效率 scrapy框架的日志等级和请求传参, 优化效率 Scrapy的日志等级 在使用scrapy crawl spiderFileName运行程序时,在终端里打印输出的就是scrapy的日志信息. 日志信息的种类: ERROR : 一般错误 WARNING : 警告 INFO : 一般的信息 DEBUG : 调试信息 设置日志信息指定输出: 在settings.py配置文件中,加

python爬虫---scrapy框架爬取图片,scrapy手动发送请求,发送post请求,提升爬取效率,请求传参(meta),五大核心组件,中间件

# settings 配置 UA USER_AGENT = 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36' 一丶scrapy的图片数据爬取(流数据的爬取) ? scrapy中封装好了一个管道类(ImagesPipeline),基于该管道类可以实现图片资源的请求和持久化存储 编码流程: 爬虫文件中解析出图片的地址 将

爬虫5 scrapy框架2 全站爬取cnblogs, scarpy请求传参, 提高爬取效率, 下载中间件, 集成selenium, fake-useragent, 去重源码分析, 布隆过滤器, 分布式爬虫, java等语言概念补充, bilibili爬视频参考

1 全站爬取cnblogs # 1 scrapy startproject cnblogs_crawl # 2 scrapy genspider cnblogs www.cnblogs.com 示例: # cnblogs_crawl/cnblogs_crawl/spiders/cnblogs.py import scrapy from cnblogs_crawl.items import CnblogsCrawlItem from scrapy.http import Request class

scrapy框架之日志等级和请求传参

一.Scrapy的日志等级 - 在使用scrapy crawl spiderFileName运行程序时,在终端里打印输出的就是scrapy的日志信息. - 日志信息的种类: ERROR : 一般错误 WARNING : 警告 INFO : 一般的信息 DEBUG : 调试信息 默认的显示级别是DEBUG - 设置日志信息指定输出: 在settings.py配置文件中,加入LOG_LEVEL = ‘指定日志信息种类’即可.LOG_FILE = 'log.txt'则表示将日志信息写入到指定文件中进行

爬虫scrapy组件 请求传参,post请求,中间件

post请求 在scrapy组件使用post请求需要调用 def start_requests(self): 进行传参再回到 yield scrapy.FormRequest(url=url,formdata=data,callback=self.parse)进行post请求 其中FormRequest()为post 请求方式 import scrapy class PostSpider(scrapy.Spider): name = 'post' # allowed_domains = ['ww

scrapy请求传参,提高爬取效率,fake-useragent

scrapy请求传参 """ # 1 传参 :yield Request(url,callback=self.parser_detail,meta={'item':item}) # 2 取参:response.meta.get('item') """ 提高爬取效率的方式 """ - 在配置文件中进行相关的配置即可:(默认还有一套setting) #1 增加并发: 默认scrapy开启的并发线程为32个,可以适当进行增

11-scrapy(递归解析,post请求,日志等级,请求传参)

一.递归解析: 需求:将投诉_阳光热线问政平台中的投诉标题和状态网友以及时间爬取下来永久储存在数据库中 url:http://wz.sun0769.com/index.php/question/questionType?type=4&page= 需求分析:每一个页面对应的是一个url,scrapy框架发起请求对一个url进行解析,解析完后又对另一个url发起请求进行解析. 实现方案: 1.可以将每一个页面的url放在爬虫程序中的start_urls中请求.(不推荐,累死人) 2.另一种请求使用R

日志等级与请求传参

日志等级: ERROR : 一般错误 WARNING : 警告 INFO : 一般的信息 DEBUG : 调试信息 默认的显示级别是DEBUG 可以在配置文件中settings中进行日志信息的指定输出:#指定日志信息的输出#LOG_LEVEL = 'DEBUG' #将日志信息写入到文件中进行存储LOG_FILE = 'log.txt' 二.请求传参 - 在某些情况下,我们爬取的数据不在同一个页面中,例如,我们爬取一个电影网站,电影的名称,评分在一级页面,而要爬取的其他电影详情在其二级子页面中.这