『scrapy爬虫』10. 实战爬取自己的csdn信息(详细注释步骤)

news2024/11/13 9:56:07

目录

    • 1. 数据库建表
    • 2. 搭建项目环境
      • 创建项目
      • 新建爬虫
      • 虚拟环境中安装库
    • 定义数据类型(item.py)
    • 爬虫(spiders/csdn.py)
    • 管道(pipelines.py)
    • 中间件(middlewares.py)
    • 项目设置(setting.py)
    • 运行测试
    • 总结


欢迎关注 『scrapy爬虫』 专栏,持续更新中
欢迎关注 『scrapy爬虫』 专栏,持续更新中

看完01-09的内容,实战一下,获取自己文章的访问量 收藏 点赞 数据信息

1. 数据库建表

标题字段2000,因为有些标题和符号确实长~

USE scrapy_csdn;

DROP TABLE IF EXISTS csdn_article;

CREATE TABLE csdn_article (
    `id` INT UNSIGNED AUTO_INCREMENT COMMENT '编号',
    `title` VARCHAR(2000) NOT NULL COMMENT '标题',
	`views` int not null  COMMENT '阅读量',
	`star` int not null  COMMENT '收藏',
	`likes` int not null  COMMENT '点赞数',
    PRIMARY KEY (`id`)
) ENGINE=InnoDB COMMENT='文章信息';

在这里插入图片描述


2. 搭建项目环境

创建项目

创建一个名为csdn_scrapy的scrapy项目
scrapy startproject csdn_scrapy

在这里插入图片描述

新建爬虫

新建名为csdn的spider

cd csdn_scrapy
scrapy genspider csdn blog.csdn.net

在这里插入图片描述
搭建成功
在这里插入图片描述

虚拟环境中安装库

import scrapy
import openpyxl
import pymysql

定义数据类型(item.py)

import scrapy

class CsdnScrapyItem(scrapy.Item):
   title = scrapy.Field()
   views = scrapy.Field()
   star = scrapy.Field()
   likes = scrapy.Field()

爬虫(spiders/csdn.py)

import scrapy

from scrapy import Selector,Request
from csdn_scrapy.items import CsdnScrapyItem

class CsdnSpider(scrapy.Spider):
    name = "csdn"
    allowed_domains = ["blog.csdn.net"]
    start_urls = ["http://blog.csdn.net/"]

    def start_requests(self) :
        yield Request(
            url=f'https://blog.csdn.net/u011027547',
            # meta={'proxy':"socket5://127.0.0.1:1086"},#socket5代理
            # meta={'proxy':"http://127.0.0.1:1086"}#购买的商业代理一般是http给一个api接口
            callback=self.parse# 这一行是系统默认带有的,你不写也是默认这样
        )

    def parse(self,response, **kwargs):
        myselector=Selector(text=response.text)
        # 单个文章的选择器
        # #userSkin > div.user-profile-body > div > div.user-profile-body-right > div.navList-box > div.mainContent > div > div > div:nth-child(1) > article
        #拿到了所有文章div组成的list
        list_items=myselector.css("#userSkin > div.user-profile-body > div > div.user-profile-body-right > div.navList-box > div.mainContent > div > div > div> article")
        for list_item in list_items:
            article_item=CsdnScrapyItem()#新建类的对象

            # userSkin > div.user-profile-body > div > div.user-profile-body-right > div.navList-box > div.mainContent > div > div > div:nth-child(1) > article > a > div.list-box-cont > div:nth-child(1) > div.blog-list-box-top > h4

            article_item['title'] = list_item.css("div.blog-list-box-top > h4::text").extract_first()
            #标题会带有这些特殊符号导致异常,所以要进行数据清洗.strip() 是一个字符串方法,用于去除字符串开头和结尾的空格(包括空格、制表符和换行符等)
            article_item['title']=article_item['title'].strip()
            print(article_item['title'])

            # 阅读
            # <span data-v-6fe2b6a7="" class="view-num">385<span data-v-6fe2b6a7="" class="two-px">&nbsp;阅读&nbsp;·</span></span>
            # 拿到类名是"view-num"的span标签的text文本
            article_item['views']=list_item.css('span[class="view-num"]::text').extract_first()
            print(article_item['views'])

            # 收藏
            # <span data-v-6fe2b6a7="" class="comment-num">21<span data-v-6fe2b6a7="" class="two-px">&nbsp;收藏</span></span>
            article_item['star']=list_item.css('span[class="comment-num"]::text').extract_first()
            print(article_item['star'])

            # 点赞
            # <span data-v-6fe2b6a7="" class="give-like-num">11<span data-v-6fe2b6a7="" class="two-px">&nbsp;点赞&nbsp;·</span></span>
            article_item['likes']=list_item.css('span[class="give-like-num"]::text').extract_first()
            print(article_item['likes'])

            yield article_item#把整理得到的数据给管道


管道(pipelines.py)

对数据进行处理,上传数据到mysql和保存本地excel

import openpyxl
import pymysql
#用于将数据存入mysql的类
class DBPipeline:
    # 初始化
    def __init__(self):
        self.conn=pymysql.connect(host='127.0.0.1',port=3306,
                                  user='root',passwd='123456',database='scrapy_csdn',charset='utf8mb4')
        self.cursor=self.conn.cursor()

        self.data=[]#准备一个存放数据的容器

    # 开始爬虫时候要进行的操作
    def open_spider(self, spider):
        pass

    # 处理爬取到的数据并进行后续处理
    def process_item(self, item, spider):
        title=item.get('title',0)
        views=item.get('views',0)#如果没有获取到评价默认0 因为我们数据是 int
        star=item.get('star',0)#如果没有获取到评价默认0 因为我们数据是 int
        likes=item.get('likes',0)#如果没有获取到评价默认0 因为我们数据是 int
        self.data.append((title,views,star,likes)) #将得到的一行的电影相关数据放入列表
        if len(self.data)>=5:
            self._write_to_db()

        return item #为什么是return? 我们要让这个管道先,return会把item数据传递给下一个管道用于保存excel的

    def _write_to_db(self):
        # execute->改为了 executemany  支持多条数据批量传入数据库
        self.cursor.executemany(
            'insert into csdn_article(title,views,star,likes) values (%s,%s,%s,%s)', self.data
        )
        self.conn.commit()  # 把数据缓冲区的数据提交到数据库
        self.data.clear()  # 每次添加后清空data 避免重复添加数据

    # 关闭爬虫时候要进行的操作
    def close_spider(self, spider):
        if len(self.data) >= 0:#如果还有残留的数据,但是因为不满100条没有传到数据库也要做好处理
            self._write_to_db()
        self.conn.close()


# 用于将数据存入excel的类
class CsdnScrapyPipeline:
    # 初始化我们的excel文件
    def __init__(self):
        self.wb=openpyxl.Workbook()
        self.ws=self.wb.active #拿到默认的被激活的工作表
        self.ws.title="文章信息" #工作表的名字
        self.ws.append(("文章标题","阅读量","收藏量",'点赞量')) #增加表头

    # 开始爬虫时候要进行的操作
    def open_spider(self,spider):
        pass
    # 关闭爬虫时候要进行的操作
    def close_spider(self,spider):
        #保存Excel文件
        self.wb.save("文章信息.xlsx")
        #关闭工作簿(Workbook)和工作表(Worksheet)
        self.wb.close()

    # 处理爬取到的数据 item是我们前面yeild返回的数据
    def process_item(self, item, spider):
        title=item.get('title',0)
        views=item.get('views',0)#如果没有获取到评价默认0 因为我们数据是 int
        star=item.get('star',0)#如果没有获取到评价默认0 因为我们数据是 int
        likes=item.get('likes',0)#如果没有获取到评价默认0 因为我们数据是 int
        self.ws.append((title,views,star,likes))#将得到的数据一行写入excel,注意这里一行是一个元组
        return item

中间件(middlewares.py)

载入cookie,配置代理等等(这里没用代理)


from scrapy import signals

# useful for handling different item types with a single interface
from itemadapter import is_item, ItemAdapter


def get_cookies_dict():
    # cookie字符串转为字典并返回
    cookies_str=''
    cookies_dict={}
    for item in cookies_str.split('; '):# 用 "; "作为分隔符,分割字符串得到列表,比如说列表第一项 ll="118174
        key,vlaue=item.split('=',maxsplit=1)# 用 "="作为分隔符,分割"ll="118174",得到的key和value分别是 li 和 118174
        cookies_dict[key]=vlaue
    return cookies_dict

COOKIES_DICT=get_cookies_dict #全局变量cookie字典


class CsdnScrapySpiderMiddleware:
    # Not all methods need to be defined. If a method is not defined,
    # scrapy acts as if the spider middleware does not modify the
    # passed objects.

    @classmethod
    def from_crawler(cls, crawler):
        # This method is used by Scrapy to create your spiders.
        s = cls()
        crawler.signals.connect(s.spider_opened, signal=signals.spider_opened)
        return s

    def process_spider_input(self, response, spider):
        # Called for each response that goes through the spider
        # middleware and into the spider.

        # Should return None or raise an exception.
        return None

    def process_spider_output(self, response, result, spider):
        # Called with the results returned from the Spider, after
        # it has processed the response.

        # Must return an iterable of Request, or item objects.
        for i in result:
            yield i

    def process_spider_exception(self, response, exception, spider):
        # Called when a spider or process_spider_input() method
        # (from other spider middleware) raises an exception.

        # Should return either None or an iterable of Request or item objects.
        pass

    def process_start_requests(self, start_requests, spider):
        # Called with the start requests of the spider, and works
        # similarly to the process_spider_output() method, except
        # that it doesn’t have a response associated.

        # Must return only requests (not items).
        for r in start_requests:
            yield r

    def spider_opened(self, spider):
        spider.logger.info("Spider opened: %s" % spider.name)


class CsdnScrapyDownloaderMiddleware:

    @classmethod
    def from_crawler(cls, crawler):
        # This method is used by Scrapy to create your spiders.
        s = cls()
        crawler.signals.connect(s.spider_opened, signal=signals.spider_opened)
        return s

    # 下载请求前的操作
    def process_request(self, request, spider):
        # request.meta={'proxy':"socket5://127.0.0.1:1086"}#在中间件中请求前拦截请求 添加代理
        request.cookie=COOKIES_DICT #设置cookie
        return None

    def process_response(self, request, response, spider):
        # Called with the response returned from the downloader.

        # Must either;
        # - return a Response object
        # - return a Request object
        # - or raise IgnoreRequest
        return response

    def process_exception(self, request, exception, spider):
        # Called when a download handler or a process_request()
        # (from other downloader middleware) raises an exception.

        # Must either:
        # - return None: continue processing this exception
        # - return a Response object: stops process_exception() chain
        # - return a Request object: stops process_exception() chain
        pass

    def spider_opened(self, spider):
        spider.logger.info("Spider opened: %s" % spider.name)


项目设置(setting.py)

基本的日志,随机等待延时,编码,请求头,并发数量,配置启用管道和中间件.

BOT_NAME = "csdn_scrapy"

SPIDER_MODULES = ["csdn_scrapy.spiders"]
NEWSPIDER_MODULE = "csdn_scrapy.spiders"
# USER_AGENT = "myscrapy (+http://www.yourdomain.com)"#告诉网站 我是爬虫,马上被枪毙~
USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"


# 是否遵守爬虫协议
ROBOTSTXT_OBEY = True

#设置 Scrapy 引擎同时处理的并发请求数量。 少设置一点不要给网站太大压力! (default: 16)
CONCURRENT_REQUESTS = 8

# 随机下载延迟
RANDOMIZE_DOWNLOAD_DELAY = True
#随机延时
DOWNLOAD_DELAY = 3

#配置日志
LOG_ENABLED = True #开启日志

LOG_LEVEL = 'DEBUG'#设置日志级别。例如,要将日志级别设置为输出所有信息,可以这样配置:通过将日志级别设置为 DEBUG,你可以获取爬虫程序执行过程中的所有详细信息,包括请求、响应、数据处理等各个环节的日志输出。当然,如果你只想获取部分信息,比如只关注警告和错误信息,也可以将日志级别设置为 WARNING 或 ERROR。在运行爬虫时,Scrapy 默认会将日志输出到控制台。如果你希望将日志保存到文件中,还可以设置 LOG_FILE 配置选项,例如:
LOG_FILE = None#设置日志none
# LOG_FILE = 'scrapy.log'#设置日志文件名字 上述配置会将日志输出到名为 scrapy.log 的文件中。

FEED_EXPORT_ENCODING = "utf-8"#通用编码
FEED_EXPORT_ENCODING = "gbk"#中文编码
FEED_OVERWRITE = True # 是否覆盖上次的数据,如果为false每次都是默认的在上次的csv文件后继续写入新的数据

# 配置数据管道
ITEM_PIPELINES = {
    'csdn_scrapy.pipelines.DBPipeline': 200, #数据库管道
    "csdn_scrapy.pipelines.CsdnScrapyPipeline": 300, #数字越小先执行,后期可以有多个管道
    # '你的项目名.pipelines.刚刚管道的类名': 权重, #权重越小先执行,后期可以有多个管道
}

# 配置下载中间件
DOWNLOADER_MIDDLEWARES = {
   "csdn_scrapy.middlewares.CsdnScrapyDownloaderMiddleware": 543,
}

# # 配置爬虫中间件
#SPIDER_MIDDLEWARES = {
#    "csdn_scrapy.middlewares.CsdnScrapySpiderMiddleware": 543,
#}

REQUEST_FINGERPRINTER_IMPLEMENTATION = "2.7"
TWISTED_REACTOR = "twisted.internet.asyncioreactor.AsyncioSelectorReactor"
FEED_EXPORT_ENCODING = "utf-8"


运行测试

虚拟环境中运行~

scrapy crawl csdn
  • 成功保存到数据库

如果没有进行数据清洗使用.strip()处理标题,你会看到下图,而且excel的标题会异常
在这里插入图片描述
经过数据清洗后标题前后没有空白的换行符和空格了
在这里插入图片描述

  • 成功保存到excel
    在这里插入图片描述

总结

大家喜欢的话,给个👍,点个关注!给大家分享更多计算机专业学生的求学之路!

版权声明:

发现你走远了@mzh原创作品,转载必须标注原文链接

Copyright 2024 mzh

Crated:2024-3-1

欢迎关注 『scrapy爬虫』 专栏,持续更新中
欢迎关注 『scrapy爬虫』 专栏,持续更新中
『未完待续』


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1535660.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Git进阶用法:Git分支轻松使用,配有图文

一、文章内容 git和分支相关的概念.git和分支有关的命令.git项目实战环节. 二、相关概念 分支&#xff1a;分支的概念好比树干的分支&#xff0c;每一跟分支都是从主干分出来的&#xff0c;营养是主干给的&#xff0c;所以在git里主干和分支也是如此&#xff0c;在git里主分…

HBCalculator 程序:通过 VMD 可计算分子动力学模拟中氢键密度和强度的一维和二维分布

分享一个通过 VMD 可计算分子动力学模拟中氢键密度和强度的一维和二维分布程序 HBCalculator。 感谢论文的原作者&#xff01; 主要内容 “氢键是分子系统中关键的非共价相互作用&#xff0c;对生物、化学和能量相关过程产生重大影响&#xff1b;因此&#xff0c;描述氢键信息…

Leetcode 70.爬楼梯

心路历程&#xff1a; 这道题是之前学院的一道复试题&#xff0c;大家都没怎么刷过算法题&#xff0c;只记得当年凭借几次试错自己把这道题做出来了&#xff0c;当时也不知道动态规划之类的。 正常来讲&#xff0c;这种找不到循环结构的题一般都是递归解决。 注意的点&#x…

Day02-DDLDMLDQL(定义,操作,查询)(联合查询,子查询,字符集和校对集,MySQL5.7乱码问题)

文章目录 Day02-DDL&DML和DQL学习目标1. SQL语言的组成2. DDL2.1 数据库结构2.2 表结构2.3 约束2.3.1 主键约束(重要)(1)特点(2) 添加主键(3)删除主键(了解) 2.3.2 自增约束(1)特点(2) 添加自增约束(3)删除自增约束(了解) 2.3.3 非空约束(1)添加非空约束(2) 删除非空约束 2…

EtherCAT 开源主站 IGH 在 linux 开发板的移植和伺服通信测试

手边有一套正点原子linux开发板imax6ul&#xff0c;一直在吃灰&#xff0c;周末业余时间无聊&#xff0c;把EtherCAT的开源IGH主站移植到开发板上玩玩儿&#xff0c;搞点事情做。顺便学习研究下EtherCAT总线协议及其对伺服驱动器的运动控制过程。实验很有意思&#xff0c;这里总…

森林防火广播应急广播系统方案

森林防火广播应急广播系统方案 深圳锐科达网络应急广播方案 森林防火广播建设必要性&#xff1b; 森林火灾是一种突发性和破坏性极强的自然灾害&#xff0c;它的后果不仅直接危害森林资源和人民生命财产安全&#xff0c;而且会影响到气候、植被及环境等多个因素的变化&#…

git tag标签使用

创建标签 git checkout test git tag -a v1.0.0 -m v1.0.0里程碑版本 git push origin v1.0.0 删除标签 git tag -d v1.0.0 git push origin :refs/tags/v1.0.0远程分支可以直接在页面删除

day15-maven高级

1. 分模块设计与开发 步骤 创建 maven 模块 tlias-pojo&#xff0c;存放实体类。创建 maven 模块 tlias-utils&#xff0c;存放相关工具类。 <dependency><groupId>com.itheima</groupId><artifactId>tlias-pojo</artifactId><version>1.0…

气液分离器的概念和原理

气液分离器也叫低压储液器&#xff0c;在热泵或制冷系统中使用&#xff0c;主要是将出蒸发器、进压缩机气流中的液滴分离出来&#xff0c;防止压缩机发生液击&#xff0c;用于工质充注量较大、压缩机进气可能带液且压缩机对湿压缩较敏感的情况 。 液击主要出现在活塞式压缩机中…

【探讨】基于卷积神经网络深度学习模型的光场显微三维粒子空间分布重建

光场显微粒子图像测速技术通过单光场相机即可实现微尺度三维速度场的测量&#xff0c;但单光场相机角度信息有限&#xff0c;导致粒子重建的轴向分辨率低、重建速度慢。基于此&#xff0c;提出一种基于卷积神经网络深度学习模型的光场显微粒子三维空间分布重建方法&#xff0c;…

电机与直线模组选型

一。普通电机选型 普通电机选型&#xff08;一&#xff09; 三相异步电机 定子&#xff1a;产生旋转磁场 转子&#xff1a;切割磁场&#xff0c;产生洛伦兹力 结构简单&#xff0c;成本低&#xff0c;稳定 效率较低&#xff0c;转速不稳定 N60f/P 定子旋转速度&#xff1a;150…

Tomcat 单机单实例一键安装

文章目录 一、场景说明二、脚本职责三、参数说明四、操作示例五、注意事项 一、场景说明 本自动化脚本旨在为提高研发、测试、运维快速部署应用环境而编写。 脚本遵循拿来即用的原则快速完成 CentOS 系统各应用环境部署工作。 统一研发、测试、生产环境的部署模式、部署结构、…

数据结构从入门到精通——二叉树的实现

二叉树的实现 前言一、二叉树链式结构的实现1.1前置说明1.2二叉树的手动创建 二、二叉树的遍历2.1 前序、中序以及后序遍历二叉树前序遍历二叉树中序遍历二叉树后序遍历2.2 层序遍历练习 三、二叉树的具体代码实现二叉树的节点个数二叉树叶子节点个数二叉树第k层节点个数二叉树…

springboot Thymeleaf模版引擎使用

1.引入依赖 <!--thymeleaf视图引擎--> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> html中要声明约束&#xff0c;这样就可以使用themelraf视…

美摄科技剪同款SDK解决方案全面升级

视频内容已成为企业宣传、品牌塑造和市场营销的重要载体。然而&#xff0c;如何快速、高效地制作出高质量的视频内容&#xff0c;成为摆在众多企业面前的一大难题。针对这一挑战&#xff0c;美摄科技凭借深厚的技术积累和创新能力&#xff0c;推出了全新的剪同款SDK解决方案&am…

基于SpringBoot+Layui的社区物业管理系统

项目介绍 社区物业管理系统是基于java程序开发,本系统分为业主和管理员两个角色 业主可以登陆系统,查看车位费用信息,查看物业费用信息,在线投诉,查看投诉,在线报修; 管理员可以车位收费信息,物业收费信息,投诉信息,楼宇信息,房屋信息,业主信息,车位信息,抄表信…

什么是物联网远程模块

在数字化和信息化的浪潮下&#xff0c;物联网技术正在以惊人的速度改变着我们的生活和生产方式。物联网远程模块&#xff0c;作为物联网技术的核心组件之一&#xff0c;正引领着这场变革。HiWoo Box就是这样一款出色的物联网远程模块&#xff0c;它通过支持远程透传、远程锁机、…

刷题DAY30 | LeetCode 332-重新安排行程 51-N皇后 37-解数独

332 重新安排行程&#xff08;hard&#xff09; 给你一份航线列表 tickets &#xff0c;其中 tickets[i] [fromi, toi] 表示飞机出发和降落的机场地点。请你对该行程进行重新规划排序。 所有这些机票都属于一个从 JFK&#xff08;肯尼迪国际机场&#xff09;出发的先生&…

Vue中的状态管理Vuex,基本使用

1.什么是Vuex? Vuex是专门为Vue.js设计的状态管理模式;特点:集中式存储和管理应用程序中所有组件状态,保证状态以一种可预测的方式发生变化。 1.1.什么是状态管理模式? 先看一个单向数据流的简单示意图 state:驱动应用的数据源 view:以声明方式将state映射到视图 actions:…

运动想象 (MI) 分类学习系列 (2) : EEG-FMCNN

运动想象分类学习系列:EEG-FMCNN 0. 引言1. 主要贡献2. 提出的网络结构2.1 SE模块2.2 多分支一维卷积神经网络 3. 实验结果3.1 消融实验结果3.2 与基线模型比较 4. 总结欢迎来稿 论文地址&#xff1a;https://link.springer.com/article/10.1007/s11517-023-02931-x 论文题目&a…