04--定义item,使用meta在不同解析函数之间传递参数

本文通过实例介绍了如何使用爬虫抓取阳光政务平台的数据。首先,创建项目并设置文件结构,然后在item.py中定义所需字段。在yg.py中,通过meta传递参数,确保数据在不同解析函数间的传递。接着,处理抓取的数据,去除不必要字段,这部分工作在pipelines.py的私有函数中完成。最后,别忘了在settings中启用自定义的user_agent和设置log_level。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

使用爬阳光政务平台的例子

创建项目

scrapy startproject yg
scrapy genspider yguang wz.sun0769.com

文件结构

在这里插入图片描述

定义item

到item.py中
只有在item.py中定义的字段才能在yg.py中使用

# -*- coding: utf-8 -*-

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

import scrapy


class SunshineItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    title = scrapy.Field()
    href = scrapy.Field()
    publish_date = scrapy.Field()
    content_img = scrapy.Field()
    content = scrapy.Field()

yg.py

注意定义meta的方式,在不同的parse之间传递item需要定义meta

# -*- coding: utf-8 -*-
import scrapy
from sunshine.items import SunshineItem

class YgSpider(scrapy.Spider):
    name = 'yg'
    allowed_domains = ['sun0769.com']
    start_urls = ['http://wz.sun0769.com/index.php/question/questionType?type=4&page=0']

    def parse(self, response):# 处理列表页
        # 分组
        tr_list = response.xpath("//div[@class='greyframe']/table[2]/tr/td/table/tr")
        for tr in tr_list:
            item = SunshineItem()
            item['title'] = tr.xpath("./td[2]/a[2]/@title").extract_first()
            item['href'] = tr.xpath("./td[2]/a[2]/@href").extract_first()
            item['publish_date'] = tr.xpath("./td[last()]/text()").extract_first()

            # 到详情页里面去
            yield scrapy.Request(
                item['href'],
                callback = self.parse_detail,
                meta={"item":item} # 提取的数据不完全,给到callback函数继续处理
            )
        # 翻页
        next = response.xpath("//a[text()]='>'/@href").extract_first()
        if next is not None:
            yield scrapy.Request(
                next,
                callback=self.parse
            )

    def parse_detail(self,response): # 处理详情页
        item = response.meta['item']
        # extract()提取列表,extract_first()提取第一个
        item['content'] = response.xpath("//td[@class='txt16_3']//text()").extract()
        item['content_img'] = response.xpath("//td[@class='txt16_3']//img/@src").extract()
        item['content_img'] = ["http://wz.sun0769.com"+i for i  in item['content_img']]
        # print(item)
        yield item


处理数据

因为爬到的数据content中有一些我们不需要的字段,我们需要删除
到管道piplines.py中

# -*- coding: utf-8 -*-

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

class SunshinePipeline(object):
    def process_item(self, item, spider):
        item['content'] = self.process_codntent(item['content'])
        print(item)
        return item

    def process_codntent(self,content):
        content = [re.sub("\xa0|\s","",i)for i in content]
        content = [i for i in content if len(i)>0] # 去除列表中空字符串
        return content

第一个私有函数调用第二个处理字符串的私有函数

注意

使用管道的时候需要在setting中把管道解开
在这里插入图片描述
定义log_level,以及把user_agent改成自己的

<think>我们通常将`active-class`添加到`router-link`组件上,而不是直接添加到`li`标签。但是,我们可以通过以下两种方式实现将激活类名应用到`li`标签:###方法一:利用Vue Router的默认行为Vue Router会将激活类名(`active-class`指定的类名或默认的`router-link-active`)添加到`router-link`组件渲染的`<a>`标签上。我们可以通过CSS选择器来设置父元素`li`的样式。```html<template><ulclass="header-menu"><liv-for="(v,i) inheadlist" :key="i"><router-link:to="v.path"active-class="active-link"><span>{{v.title}}</span></router-link></li></ul> </template><style scoped>/*当router-link被激活时,我们设置其父元素li的样式 */li>a.active-link {/*这里设置a标签激活时的样式 */} /*如果希望激活时改变整个li的样式,可以使用以下方式 */li:has(> a.active-link) {background-color:#f0f7ff;border-bottom:2pxsolid #1890ff;} </style>``` 注意:`:has()`选择器是一个CSS4选择器,目前已被现代浏览器支持,但在一些旧版本浏览器(如Firefox旧版)可能不支持。如果考虑兼容性,可以使用方法二。 ###方法二:将激活类名传递给父元素(推荐)我们可以在`router-link`激活时,通过事件或类名传递,将激活状态传递给父元素`li`。这里我们使用在`li`上绑定类名的方式,根据子元素`router-link`的激活状态来动态添加类名。```html<template><ul class="header-menu"><liv-for="(v,i) inheadlist":key="i":class="{'active-link-parent': activeLinks[i]}"><router-link:to="v.path"active-class="active-link"@click="setActive(i)"><span>{{v.title}}</span></router-link></li></ul> </template><script setup> import{ ref} from'vue'; constactiveLinks= ref([]);//用于记录每个菜单的激活状态//初始化activeLinks,根据菜单项数量初始化//这里假设headlist已经在组件中定义activeLinks.value= newArray(headlist.length).fill(false);//设置激活状态const setActive =(index) =>{//先重置所有状态activeLinks.value=activeLinks.value.map(() =>false);//设置当前激活activeLinks.value[index] =true;}; </script><style scoped>.active-link-parent {background-color:#f0f7ff;border-bottom:2pxsolid #1890ff;} </style>``` 但是,上述方法需要手动管理激活状态,而且可能和路由的激活状态不同步。因此,更推荐使用路由信息来动态设置`li`的类名。 ###方法三:使用计算属性(最佳实践)我们可以利用`useRoute`获取当前路由,然后判断每个菜单项的路由是否匹配当前路由,从而动态设置`li`的类名。```html<template><ul class="header-menu"><liv-for="(v,i)in headlist":key="i":class="{ 'active-nav': isActive(v.path)}"><router-link:to="v.path"><span>{{v.title}}</span></router-link></li></ul></template> <scriptsetup>import {useRoute} from'vue-router';import {computed }from 'vue';constroute =useRoute(); constheadlist= [{title:'首页', path: '/'},{ title: '产品',path:'/products' },{title:'关于', path: '/about'} ];//判断当前菜单是否激活const isActive =(path) =>{//如果是根路径,需要精确匹配if(path=== '/') {returnroute.path=== path;}//其他路径,只要当前路由以该路径开头即可(或者根据需求调整)return route.path.startsWith(path); };</script> <stylescoped> .active-nav {background-color:#f0f7ff;border-bottom:2pxsolid #1890ff;} </style>``` ###总结-直接给`li`标签添加`active-class`属性是不行的,因为`active-class`是`router-link`组件的属性。 -推荐使用CSS选择器(如果支持`:has()`)或方法三(计算属性)来实现将激活样式应用到`li`标签。###注意事项-方法三中的`isActive`函数需要根据实际路由结构设计,比如嵌套路由的情况下,可能需要更复杂的匹配逻辑。 -如果使用嵌套路由,父级菜单的路径可能不是精确匹配,所以通常使用`startsWith`或包含匹配。§§相关问题§§:1.在Vue Router中如何实现嵌套路由的激活状态样式? 2.如何使用Vue Router的路由元信息(meta)来控制导航菜单的激活状态?3.在Vue3中,如何实现导航菜单的权限控制?4.如何为VueRouter的导航菜单添加滑动指示条效果?</think>在 Vue Router 中,`active-class="active-link"` 属性**不能直接添加到 `<li>` 标签上**。这个属性是专门为 `<router-link>` 组件设计的,用于控制导航链接本身的激活状态样式。以下是详细解释和解决方案: ### 为什么不能直接用在 `<li>` 上 1. **属性作用对象**: - `active-class` 是 `<router-link>` 组件的专属属性 - 它会被解析为 `<a>` 标签的类名(因为 `<router-link>` 默认渲染为 `<a>` 标签) - 直接用在 `<li>` 上会被忽略,不会产生任何效果 2. **渲染结果**: ```html <!-- 原始代码 --> <li> <router-link active-class="active-link" to="/home">首页</router-link> </li> <!-- 渲染结果 --> <li> <a href="/home" class="active-link">首页</a> <!-- 类名在 <a> 上 --> </li> ``` ### 正确实现方法 #### 方法 1:使用 CSS 继承(推荐) 通过 CSS 让父元素继承子元素的激活状态: ```html <template> <ul class="header-menu"> <li v-for="(v,i) in headlist" :key="i"> <router-link :to="v.path" active-class="active-link" > <span>{{v.title}}</span> </router-link> </li> </ul> </template> <style scoped> /* 当 <a> 有 active-link 类时,设置其父元素 <li> 的样式 */ li:has(> a.active-link) { background-color: #1890ff; border-radius: 4px; } /* 激活链接本身的样式 */ a.active-link span { color: white; font-weight: bold; } </style> ``` #### 方法 2:动态绑定类名(灵活控制) 使用 Vue 的响应式系统动态控制 `<li>` 的类名: ```html <template> <ul class="header-menu"> <li v-for="(v,i) in headlist" :key="i" :class="{ 'active-item': isActive(v.path) }" <!-- 动态绑定 --> > <router-link :to="v.path"> <span>{{v.title}}</span> </router-link> </li> </ul> </template> <script setup> import { useRoute } from 'vue-router'; import { computed } from 'vue'; const route = useRoute(); const headlist = [ { title: '首页', path: '/' }, { title: '产品', path: '/products' }, { title: '关于', path: '/about' } ]; const isActive = (path) => { // 精确匹配逻辑 if (path === '/') return route.path === path; // 包含匹配(用于嵌套路由) return route.path.startsWith(path); }; </script> <style scoped> .active-item { position: relative; background-color: #e6f7ff; } .active-item::after { content: ""; position: absolute; bottom: 0; left: 10%; width: 80%; height: 3px; background: #1890ff; border-radius: 2px; } </style> ``` ### 关键区别说明 | 方法 | 优点 | 缺点 | |--------------------|-------------------------------|-------------------------------| | CSS 继承 (`:has()`) | 简洁,无额外JS逻辑 | 浏览器兼容性要求(新版浏览器)| | 动态类名绑定 | 完全控制,兼容性好 | 需要额外JS逻辑 | | 直接加在 `<li>` | ❌ 无效 | ❌ 无效 | ### 浏览器兼容性解决方案 如果需支持旧版浏览器(不支持 `:has()` 选择器),使用动态类名绑定方法,并添加回退样式: ```css /* 现代浏览器 */ li:has(> a.active-link) { background: #e6f7ff; } /* 旧版浏览器回退 */ li.active-item-fallback { background: #e6f7ff; } ``` ```js // 在动态绑定中添加回退类 :class="{ 'active-item': isActive(v.path), 'active-item-fallback': isActive(v.path) }" ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值