当前位置: 首页 > news >正文

Python爬虫的scrapy的学习(学习于b站尚硅谷)

目录

  • 一、scrapy
    •   1. scrapy的安装
      •   (1)什么是scrapy
      •   (2)scrapy的安装
    •   2. scrapy的基本使用
      •   (1)scrap的使用步骤
      •   (2)代码的演示
    •   3. scrapy之58同城项目结构和基本方法(注:58同城的数据不是公开数据,不能爬取;本次代码也爬取不到相应的数据)
      •   (1)scrapy项目的组成
      •   (2)scrapy爬虫文件的组成以及响应response的属性和方法
      •   (3)代码演示
    •   4. 汽车之家scrapy工作原理
      •   (1)scrapy架构组成
      •   (2)scrapy的工作原理
      •   (3)代码演示
    •   5.调试工具scrapy shell
      •   (1)什么是scrapy shell
      •   (2)安装ipython
      •   (3)ipython的使用方法
    •   6. scrapy之当当网爬取数据(本节获取数据失败,已在第9节成功解决,不想再改动本节内容了)
      •   (1)yied
      •   (2)本节的演示
    •   7.scrapy_当当网管道封装(本节获取数据失败,已在第9节成功解决,不想再改动本节内容了)
    •   8.scrapy_当当网开启多条管道下载(本节获取数据失败,已在第9节成功解决,不想再改动本节内容了)
    •   9.scrapy_当当网多页下载
    •   10.scrapy_电影天堂多页数据下载
    •   11. scrapy_链接提取器CrawlSpider的使用(含MySql、pymysql的使用)
      •   (1)MySQL的安装和初级使用
      •   (2)CrawlSpider的作用
      •   (3)CrawlSpider的使用方法
      •   (4)代码演示
    •   12.scrapy_crawlspider读书网获取图片的封面地址和名字
      •   (1)CrawlSpider的使用步骤
      •   (2)代码演示
    •   13.scrapy_读书网数据入库和链接跟进(失败,卡在最后的“由于日标计算机积极拒绝”,没有系统学过MySQL,卡住了)
      •   (1)准备工作(安装Ubuntu、在Ubuntu上安装mysql中途含出现的两个问题的解决办法、Windows上安装pymysql)
      •   (2)pymysql的使用步骤
      •   (3)本次的演示(失败,卡在最后的“由于日标计算机积极拒绝”)
    •   14. scrapy_日志信息以及日志级别
      •   (1)日志信息的定义、等级、如何设置日志
      •   (2)代码演示
    •   15.scrapy_百度翻译post请求
      •   (1)scrapy 下的post请求的用法
      •   (2)代码演示

  说明:该文章是学习 尚硅谷在B站上分享的视频 Python爬虫教程小白零基础速通p51-104而记录的笔记,笔记来源于本人,关于python基础可以去CSDN上阅读本人学习黑马程序员的笔记。 若有侵权,请联系本人删除。笔记难免可能出现错误或笔误,若读者发现笔记有错误,欢迎在评论里批评指正。 请合法合理使用爬虫,不爬取任何涉密以及涉及隐私的内容,合理控制请求次数,爬取的内容未经授权请不要用于商用,保护自己,免受牢狱之灾。
在这里插入图片描述
在这里插入图片描述
  本章将介绍scrapy,它是爬虫在企业级研发中用得最多的技术,由于scrapy使用框架,故具有编程更简单、爬取速度更快、更好地进行爬虫的开发。
  注:由于本人是先做word,再将代码复制到CSDN中的,代码可能会出现类似下图的情况,多几个“-”号的问题。代码太多,根本改不完,难免有没改到的。

在这里插入图片描述

一、scrapy

  1. scrapy的安装

  (1)什么是scrapy

  scray是一个为了爬取网站数据,提取结构性数据而编写的应用框架。可以应用在包括数据挖掘、信息处理或存储历史数据等一系列的程序中。
  什么是结构性数据?结构性就是类似的具有相同特征的东西,里面的数据就是结构性数据。
  下面将举一个具体例子进行说明。打开读书网,点击“计算机/网络”。假如我们想采取这个网站中所有书的信息,包括名字、作者、简介、图片等。
在这里插入图片描述
  如下图,选中一本书进行定位(即在某本书处打开检查),发现这些书的信息有一个相同的结构,比如书名都在结构“/html/body/div[6]/div/div[2]/div[2]/ul/li/div/h3/a”下,它们具有相同的结构,这就是结构性的例子。至于结构性数据,比如书名就是该结构下的数据。
在这里插入图片描述
在这里插入图片描述

  (2)scrapy的安装

  安装命令:pip install scrapy -i https://pypi.mirrors.ustc.edu.cn/simple/
  安装具体步骤:如下图,先打开“命令提示符”。
在这里插入图片描述
  然后在命令提示符里安装scrapy。
在这里插入图片描述
在这里插入图片描述

  2. scrapy的基本使用

  (1)scrap的使用步骤

1. 创建爬虫的项目     scrapy startproject 项目名字注意:项目的名字不允许使用数字开头   也不能包含中文
2. 创建爬虫文件要在spiders文件夹中去创建爬虫文件进入spiders文件夹:cd 项目的名字\项目的名字\spiders,- 本次演示使用的命令为    cd scrapy_baidu_091\scrapy_baidu_091\spiders创建爬虫文件scrapy genspider 爬虫的名字 要爬取的网页eg:scrapy genspider baidu http://www.baidu.com
3. 运行爬虫代码scrapy crawl 爬虫的名字eg:scrapy crawl baidu注:在运行爬虫程序时,需注释掉文件“setting.py”中的“ROBOTSTXT_OBEY = True,  即不遵守君子协议

  注意,对于请求的地址,如果含有符号&,则需改成”&”或’&’,不然会报错。

  (2)代码的演示

  本次演示的目的就是使用scrapy让百度打印一句话,进而熟悉scrapy的基本使用。如下图,创建文件夹“爬虫的scrapy”。
在这里插入图片描述
  如下图所示,找到新建的文件夹,在命令提示符窗口中将路径切换到这个文件夹。
在这里插入图片描述
在这里插入图片描述
  输入命令“scrapy startproject scrapy_baidu_091”来创建一个名为“scrapy_baidu_091”的项目。可以到PyCharm中去查看是否有对应的项目文件。
在这里插入图片描述
在这里插入图片描述
  再在项目文件夹里创建一个test文件,用来记笔记。然后如下所示,将本次演示的思路进行记录。(其实这个test里面记的笔记是随着程序的编写而记录的,但是本人直接放在此处,以便对整个演示有个指导作用。)
在这里插入图片描述

1. 创建爬虫的项目scrapy startproject 项目名字注意:项目的名字不允许使用数字开头   也不能包含中文
2. 创建爬虫文件要在spiders文件夹中去创建爬虫文件进入spiders文件夹:cd 项目的名字\项目的名字\spiders,- 本次演示使用的命令为    cd scrapy_baidu_091\scrapy_baidu_091\spiders创建爬虫文件scrapy genspider 爬虫的名字 要爬取的网页eg:scrapy genspider baidu http://www.baidu.com
3. 运行爬虫代码scrapy crawl 爬虫的名字eg:scrapy crawl baidu注:在运行爬虫程序时,需注释掉文件“setting.py”中的“ROBOTSTXT_OBEY = True,即不遵守君子协议

在这里插入图片描述
  然后使用命令“cd scrapy_baidu_091\scrapy_baidu_091\spiders”切换到文件夹spiders下,使用命令“scrapy genspider baidu http://www.baidu.com”创建爬虫文件(即“baidu.py”)。
在这里插入图片描述
在这里插入图片描述
  需要知道的是,爬虫的名字一般用于运行爬虫的时候使用的值。
在这里插入图片描述
  如下,对文件“baidu.py”进行编程,然后再在“命令提示符”窗口中输入“scrapy crawl baidu”运行爬虫代码,发现并没有"苍茫的天涯是我的爱"。说明存在反爬手段。

import scrapyclass BaiduSpider(scrapy.Spider):# 爬虫的名字     用于运行爬虫的时候使用的值name = "baidu"# 允许访问的域名allowed_domains = ["www.baidu.com"]# 起始的url地址     指的是第一次要访问的域名# start_urlsstart_urls = ["http://www.baidu.com"]# 下面是执行start_urls之后执行的的方法  方法中的response就是返回的那个对象,# 相当于    response = urllib.request.uropen()#          response = requests.get()def parse(self, response):print("苍茫的天涯是我的爱")

在这里插入图片描述
  第一个需要解决的是所谓的君子协议,故去文件“setting.py”中注释掉图中所示的代码,即不遵守该协议。(注:scrapy一看就是爬虫程序,理论上得遵守君子协议。但有时仅仅是为了爬取网页上公开的不涉及隐私的、且不会对网站造成任何危害的、不用作商业用途、不损害他人利益、合理合法的使用,一般也没人管,也不会出现问题。)
在这里插入图片描述在这里插入图片描述
  然后再次运行程序,发现“苍茫的天涯是我的爱”已经成功被打印。
在这里插入图片描述
在这里插入图片描述

  3. scrapy之58同城项目结构和基本方法(注:58同城的数据不是公开数据,不能爬取;本次代码也爬取不到相应的数据)

  (1)scrapy项目的组成

在这里插入图片描述

项目名字项目名字spiders文件夹(存储的是爬虫文件)init自定义的爬虫文件    核心功能文件  ********inititems           定义数据结构的地方 即爬取的数据都包含哪些middlewares     称为中间件   用来设置代理机制pipelines        称为管道     用来处理下载的数据settings         称为配置文件  robots协议、UA定义的地方

  (2)scrapy爬虫文件的组成以及响应response的属性和方法

在这里插入图片描述

response.text            获取的是响应的字符串
response.body            获取的是二进制数据
response.xpath           可以直接是xpath方法来解析response中的内容
response.extract()       提取seletor对象的data属性值
response.extract_first() 提取的seletor列表的第一个数据

  (3)代码演示

  本次将通过58同城(“https://cn.58.com/”)来介绍response的属性和方法。如下图,打开58同城,搜索前端开发。
在这里插入图片描述
  然后寻找该网页的接口。打开检查,点击网络,清空一下接口,再刷新,很容易就找到了接口。
在这里插入图片描述
  然后去命令提示符创建项目,其实PyCharm终端也可以,本次以终端进行演示。如下图所示,成功创建名为“scrapy_58tc_092”的项目(命令依次为“cd 爬虫的scrapy”、“scrapy startproject scrapy_58tc_092”)。
在这里插入图片描述
  接着复制接口的请求地址,再在PyCharm的终端中进入文件夹“spiders”(命令为“cd .\scrapy_58tc_092\scrapy_58tc_092\spiders\”),再使用命令“scrapy genspider tc 接口请求的地址”创建爬虫文件。(注意:对于请求的地址,如果含有符号&,则需改成”&”或’&’,不然会报错)
在这里插入图片描述
在这里插入图片描述
  如下图,注释掉遵守君子协议(即图中所示代码)。
在这里插入图片描述
  然后回到爬虫文件,然后如下图所示修改一句代码,运行一下代码文件(指令为“scrapy crawl tc”),验证是否能够成功运行。
在这里插入图片描述
在这里插入图片描述
  然后创建一个名为“test”的文件,用来说明scrapy项目的结构以及response的属性和方法,具体如下。(所记内容应该随着演示的进度边做边记录,但为了起指导作用,个人直接听完了然后再来写的笔记)
在这里插入图片描述

1. scrapy项目的结构项目名字项目名字spiders文件夹(存储的是爬虫文件)init自定义的爬虫文件    核心功能文件  ********inititems           定义数据结构的地方 即爬取的数据都包含哪些middlewares     称为中间件   用来设置代理机制pipelines       称为管道     用来处理下载的数据settings        称为配置文件  robots协议、UA定义的地方2. response的属性和方法response.text            获取的是响应的字符串response.body            获取的是二进制数据response.xpath           可以直接是xpath方法来解析response中的内容response.extract()       提取seletor对象的data属性值response.extract_first() 提取的seletor列表的第一个数据

在这里插入图片描述
  然后爬虫文件“tc.py”中进行如下编程运行(运行指令“scrapy crawl tc”),验证是否能获取网页源码。发现网页需要进行58同城的验证。

import scrapyclass TcSpider(scrapy.Spider):name = "tc"allowed_domains = ["cn.58.com"]start_urls = ["https://cn.58.com/sou/?key=%E5%89%8D%E7%AB%AF%E5%BC%80%E5%8F%91&classpoli-cy=uuid_TNcWRNaySTeW63QGr4FnmMaRrMFXfR6e%2Cclassify_B&search_uuid=TNcWRNaySTeW63QGr4FnmMaRrMFXfR6e&search_type=history"]def parse(self, response):content = response.text  # 获取网页源码print('=================================')  # 打印此行,便于寻找代码的执行结果print(content)

在这里插入图片描述
在这里插入图片描述
  试了一会不会获取,想要研究的自己去搞。而且去网上查了下,还有人因为爬取58同城的数据而犯法的,吓得赶紧上网查了查关于爬虫的法律法规。
在这里插入图片描述
  下面的话仅为个人观点:由上图可见单纯的抓取公开数据、仅仅违背robots君子协议都不是违法行为。相反,爬虫技术的发展在一定程度上促进了反爬技术的发展。另外,58同城那些数据,确实属于他们的商业信息,不属于公开信息,不应该被随便爬取。不得不说的是,58同城的一些数据通过鼠标点击就能查看到,如果58同城如果没有设立反爬机制,让爬虫轻松爬取到了信息,那样的话自身也有一定责任,信息保护不到位,未成功让爬虫行为人知道这个不是公开信息,不应该爬取58同城的信息。另外,爬虫行为人也应当思考,58同城是靠一些数据信息营业的,不应该去获取他们的数据。还有那几个违法的过分了,绕开反爬机制来爬取非法数据就存在问题了,还用去盈利,错上加错啊。
  因此,我们就不要想着突破58同城,去获取任何数据了。不能突破验证码的代码如下。

import scrapyclass TcSpider(scrapy.Spider):name = "tc"allowed_domains = ["cn.58.com"]start_urls = ["https://cn.58.com/sou/?key=%E5%89%8D%E7%AB%AF%E5%BC%80%E5%8F%91&classpoli-cy=uuid_TNcWRNaySTeW63QGr4FnmMaRrMFXfR6e%2Cclassify_B&search_uuid=TNcWRNaySTeW63QGr4FnmMaRrMFXfR6e&search_type=history"]# 请求头headers = {'User-Agent': 'ozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; Hot Lingo 2.0)'}def parse(self, response):# 1.字符串content = response.text  # 获取网页源码# 2.二进制数据# content = response.body# print('=================================')  # 打印此行,便于寻找代码的执行结果# print(content)span = response.xpath('xpath路径[0]')print('=================================')  # 打印此行,便于寻找代码的执行结果print(span.extract())

  4. 汽车之家scrapy工作原理

  (1)scrapy架构组成

在这里插入图片描述

  (2)scrapy的工作原理

在这里插入图片描述
  scrapy的工作原理如上图所示,观察绿色的箭头、红色的箭头回路后发现,爬虫spiders先发送一个url给引擎,引擎再将这个url送给调度器。之后,调度器就会生成一个请求对象并发送给引擎,引擎再将这个请求送给下载器,下载器再去向互联网下载数据,并将数据送回引擎,引擎再将数据送给spiders,这个数据就是scrapy爬虫文件中的response,然后spiders再根据需要使用xpath路径来解析数据得到一个解析结果。如果这个解析结果是url,它就会将刚刚的过程再执行一遍;如果这个解析结果是数据,它就被管道下载并保存了。

  (3)代码演示

  本次将演示如何获取汽车之家中,爬取我们感兴趣的数据,这里具体爬取了热门宝马汽车的名字和价格。
  如下图,搜索“汽车之家”(其官网链接为汽车之家),搜索“宝马 热门车”,进入宝马热门车的页面。然后打开检查,点击网络,刷新页面,找到页面的接口。然后复制该接口的请求地址。
在这里插入图片描述
在这里插入图片描述
  使用指令进入文件夹“爬虫的scrapy”(“cd .\爬虫的scrapy\”),创建名为“scrapy_carhome_093”的项目(“scrapy startproject scrapy_carhome_093”)。
在这里插入图片描述
  如下图所示,进入文件夹spiders(“cd .\scrapy_carhome_093\scrapy_carhome_093\spiders\”)中创建爬虫文件“car.py”(“scrapy genspider car 接口的请求地址”)。
在这里插入图片描述
  如下图所示,仅修改一句代码,验证在该网站上能否执行程序。
在这里插入图片描述
在这里插入图片描述
  如下图所示,找到各个图片的名字的xpath路径,然后再复制(记得加上“/text()”)。
在这里插入图片描述
在这里插入图片描述
  然后编写代码,验证获取的数据是否包含车名。然后思考怎么获取车名的数据。

import scrapyclass CarSpider(scrapy.Spider):name = "car"allowed_domains = ["car.autohome.com.cn"]start_urls = ["https://car.autohome.com.cn/price/brand-15.html"]def parse(self, response):name_list = response.xpath('//div[@class="list-cont"]/div/div[2]/div[1]/a/text()')for name in name_list:print(name)

在这里插入图片描述
在这里插入图片描述
  此时我们想到获取标签的属性值需使用extract,故继续编写代码,获取车名。
在这里插入图片描述
在这里插入图片描述
  如果我们对车的价格比较感兴趣,可与获取车名的方法一样,找到它们的xpath路径,然后继续编程,获取到对应的数据。
在这里插入图片描述

import scrapyclass CarSpider(scrapy.Spider):name = "car"allowed_domains = ["car.autohome.com.cn"]start_urls = ["https://car.autohome.com.cn/price/brand-15.html"]def parse(self, response):name_list = response.xpath('//div[@class="list-cont"]/div/div[2]/div[1]/a/text()')price_list = response.xpath('//*[@id="brandtab-1"]/div/div/div[2]/div[2]/div[2]/div[1]/span/span/text()')for i in range(len(name_list)):name = name_list[i].extract()price = price_list[i].extract()print(name, price)

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

  5.调试工具scrapy shell

  (1)什么是scrapy shell

在这里插入图片描述

  (2)安装ipython

在这里插入图片描述
  具体安装步骤如下:使用快捷键Win+R打开运行窗口,输入cmd并按Enter键打开命令提示符窗口。
在这里插入图片描述
  在命令提示符窗口中将目录切换到scripts文件夹中,再使用命令“pip install ipython -i https://pypi.mirrors.ustc.edu.cn/simple/”安装。
在这里插入图片描述

  (3)ipython的使用方法

在这里插入图片描述

# 进入到scrapy shell的终端    直接在windows的终端中输入scrapy shell 域名
# 如果想看到一些高亮 或者 自动补全 那么可以安装ipython 安装命令:pip install ipython# scrapy shellI www.baidu.com

  如下图所示,在终端中使用scrapy shell进入百度,然后就会返回一堆对象。
在这里插入图片描述
在这里插入图片描述
  之后就可以按照scrapy的语法正常使用了,可见scrapy shell对于调试、获取复杂网页的数据来说,十分便利。
在这里插入图片描述
在这里插入图片描述

  6. scrapy之当当网爬取数据(本节获取数据失败,已在第9节成功解决,不想再改动本节内容了)

  (1)yied

在这里插入图片描述

  (2)本节的演示

  本次将演示如何下载当当网中的10页数据。(原视频讲解了如何爬取某个分类的所以有数据,我们就是学习使用而已,爬两页就够了,别人维护网站也不容易。再次强调,爬取数据仅供学习使用,千万别商用。)
如下图,进入到当当网(“http://www.dangdang.com/”)的“爱情/情感”的电子书的网页中。
在这里插入图片描述
在这里插入图片描述
  如下图,使用命令“scrapy startproject scrapy_dangdang_095”创建项目文件。
在这里插入图片描述
  再使用指令“cd scrapy_dangdang_095/scrapy_dangdang_095/spiders”进入文件夹“spiders”中,使用指令“scrapy genspider dang 域名”创建爬虫文件“dang.py”(其中域名为刚刚复制的网址,另外,网址中含有&,需要变成‘&’或”&”)。
在这里插入图片描述
在这里插入图片描述
  然后尝试打印一行数据,判断是否含有反爬手段。结果发现没有。

# Define here the models for your scraped items
#
# See documentation in:
# https://docs.scrapy.org/en/latest/topics/items.htmlimport scrapyclass ScrapyDangdang095Item(scrapy.Item):# define the fields for your item here like:# name = scrapy.Field()# 数据结构,通俗地说就是你要下载的数据都有什么# 图片src = scrapy.Field()# 名字name = scrapy.Field()# 价格price = scrapy.Field()

在这里插入图片描述
在这里插入图片描述
  然后去文件“items.py”中定义本次演示的数据结构。数据结构,通俗地说就是你要下载的数据都有什么。

# Define here the models for your scraped items
#
# See documentation in:
# https://docs.scrapy.org/en/latest/topics/items.htmlimport scrapyclass ScrapyDangdang095Item(scrapy.Item):# define the fields for your item here like:# name = scrapy.Field()# 数据结构,通俗地说就是你要下载的数据都有什么# 图片src = scrapy.Field()# 名字name = scrapy.Field()# 价格price = scrapy.Field()

在这里插入图片描述
  如下图,寻找到图片、书名、价格的xpath路径,然后复制到PyCharm中。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
  观察这几个数据的xpath路径,发现都在一个a标签下。于是继续编写程序。
在这里插入图片描述
  编写程序并执行,猜测当当网可能加入了君子协议(robots协议),得去注释君子协议后在来运行,还是没有返回数据。

import scrapyclass DangSpider(scrapy.Spider):name = "dang"allowed_domains = ["e.dangdang.com"]start_urls = ["http://e.dangdang.com/classification_list_page.html?category=AQQG&dimension=dd_sale&order=0"]def parse(self, response):# pipelines     管道用于下载数据# items         定义数据结构# 数据的xpath路径# src="//div[@id="book_list"]/a/span/img[2]/@src"# alt="//div[@id="book_list"]/a/span/img[2]/@alt"# price"//div[@id="book_list"]/a/div/div[4]/span[@class="now"]/text()"# 所有的selector的对象 都可以再次调用xpath方法a_list = response.xpath('//div[@id="book_list"]/a')print(a_list)for a in a_list:src = a.xpath('.//span/img[2]/@src').extract_first()  # 注意“.”表示当前路径下的意思,"./"不能省name = a.xpath('.//span/img[2]/@alt').extract()price = a.xpath('.//div/div[4]/span[@class="now"]/text()').extract().strip()print(src, name, price)

在这里插入图片描述在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
  暂时不会了,于是听完视频后发现代码不用变(本次没有发现懒加载导致数据的xpath路径不一样的问题)。注意,在第九节中该问题已经被解决。

  7.scrapy_当当网管道封装(本节获取数据失败,已在第9节成功解决,不想再改动本节内容了)

  紧接着上一讲的继续。如下代码所示,将爬取的数据交给管道。

import scrapy
from ..items import ScrapyDangdang095Itemclass DangSpider(scrapy.Spider):name = "dang"allowed_domains = ["e.dangdang.com"]start_urls = ["http://e.dangdang.com/classification_list_page.html?category=AQQG&dimension=dd_sale&order=0"]def parse(self, response):# pipelines     管道用于下载数据# items         定义数据结构# 数据的xpath路径# src="//div[@id="book_list"]/a/span/img[2]/@src"# alt="//div[@id="book_list"]/a/span/img[2]/@alt"# price"//div[@id="book_list"]/a/div/div[4]/span[@class="now"]/text()"# 所有的selector的对象 都可以再次调用xpath方法print('==========================================')a_list = response.xpath('//div[@id="book_list"]/a')print(a_list)for a in a_list:src = a.xpath('.//span/img[2]/@src').extract_first()  # 注意“.”表示当前路径下的意思,"./"不能省name = a.xpath('.//span/img[2]/@alt').extract()price = a.xpath('.//div/div[4]/span[@class="now"]/text()').extract().strip()# print(src, name, price)  测试代码,验证数据是否获取成功book = ScrapyDangdang095Item(src=src, name=name, price=price)# 需要将book(即ScrapyDangdang095Item对象)交给pipeline下载yield book  # 获取一个book就将book交给管道pipeline

在这里插入图片描述
  如下图,去文件“settings.py”中开启管道。(注:管道可以有很多个,那么管道是有优先级的。优先级的范围是1-1000,值越小,优先级越高。)
在这里插入图片描述
  然后去管道文件“pipelines.py”中封装管道。

# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: https://docs.scrapy.org/en/latest/topics/item-pipeline.html# useful for handling different item types with a single interface
from itemadapter import ItemAdapter# 如果想使用管道的话 那么必须在settings中开启管道
class ScrapyDangdang095Pipeline:# 在爬虫文件开始之前 执行的方法def open_spider(self, spider):self.fp = open('book.json', 'w', encoding='UTF-8')# item就是yield后面的book对象def process_item(self, item, spider):# 以下这种模式不推荐  因为每传递过来一个对象就打开一次文件  对文件的操作过于频繁# 因此定义了方法open_spider()、close_spider()# with open('book.json', 'a', encoding="UTF-8") as fp:#     # 存在两个坑#     # (1)write方法里的内容必须是字符串#     # (2)w模式下,每个对象都会打开一次文件  会覆盖之前的内容#     #      故改成 a追加模式#     fp.write(item)self.fp.write(str(item))return item# 在爬虫文件执行完成之后 执行的方法def close_spider(self, spider):self.fp.close()

在这里插入图片描述

  8.scrapy_当当网开启多条管道下载(本节获取数据失败,已在第9节成功解决,不想再改动本节内容了)

  紧接着上一节,本节将演示当当网开启多条管道下载,具体为设两条管道,一边下载json数据,一边下载图片。
  创建名为“books”的文件夹用来存储图片。
在这里插入图片描述
  去管道文件“pipelines.py”中定义新的管道类。

# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: https://docs.scrapy.org/en/latest/topics/item-pipeline.html# useful for handling different item types with a single interface
from itemadapter import ItemAdapter# 如果想使用管道的话 那么必须在settings中开启管道
class ScrapyDangdang095Pipeline:# 在爬虫文件开始之前 执行的方法def open_spider(self, spider):self.fp = open('book.json', 'w', encoding='UTF-8')# item就是yield后面的book对象def process_item(self, item, spider):# 以下这种模式不推荐  因为每传递过来一个对象就打开一次文件  对文件的操作过于频繁# 因此定义了方法open_spider()、close_spider()# with open('book.json', 'a', encoding="UTF-8") as fp:#     # 存在两个坑#     # (1)write方法里的内容必须是字符串#     # (2)w模式下,每个对象都会打开一次文件  会覆盖之前的内容#     #      故改成 a追加模式#     fp.write(item)self.fp.write(str(item))return item# 在爬虫文件执行完成之后 执行的方法def close_spider(self, spider):self.fp.close()import urllib.request# 第二条管道   下载图片
# 多条管道开启  模仿前面的管道进行编写
"""
步骤:(1)定义管道类(2)在settings中开启管道"""
class DangDangDownloadPipeline:def process_item(self, item, spider):url = 'http:' + item.get('src')filename = './books/' + item.get('name') + '.jpg'urllib.request.urlretrieve(url=url, filename=filename)return item

在这里插入图片描述
  在文件“settings.py”中开启新管道。

ITEM_PIPELINES = {# 管道可以有很多个 那么管道是有优先级的 优先级的范围是1-1000 值越小,优先级越高"scrapy_dangdang_095.pipelines.ScrapyDangdang095Pipeline": 300,# DangDangDownloadPipeline"scrapy_dangdang_095.pipelines.DangDangDownloadPipeline": 301,
}

在这里插入图片描述

  9.scrapy_当当网多页下载

  紧接着上一节,本节将演示多页的下载。首先我们需要知道,每一页的爬取的业务逻辑全都是一样的,所以只需要将执行的那个页的请求再次调用parse方法就可以了。
  去观察网络的接口,找到了存储数据的接口,并将接口的请求地址复制到PyCharm中,成功解决前面几节没有返回数据的问题。
在这里插入图片描述
在这里插入图片描述
  然后编写“dang.py”的代码。

import scrapy
from ..items import ScrapyDangdang095Item
import jsonpath
import jsonclass DangSpider(scrapy.Spider):name = "dang"allowed_domains = ["e.dangdang.com"]start_urls = ["http://e.dangdang.com/media/api.go?action=mediaCategoryLeaf&promotionType=1&deviceSerial-No=html5&macAddr=html5&channelType=html5&permanentId=20230814120937742356681582820154551&returnType=json&channelId=70000&clientVersionNo=6.8.0&platformSource=DDDS-P&fromPlatform=106&deviceType=pconline&token=&start=0&end=20&category=AQQG&dimension=dd_sale"]def parse(self, response):# pipelines     管道用于下载数据# items         定义数据结构print('==========================================')# print(response.text) # 发现获取的是json数据# with open('网页源码.json','w',encoding='UTF-8') as fp:#     fp.write(response.text)# 观察数据后直接使用jsonpath进行解析obj = json.loads(response.text)# 图片地址的列表src_list = jsonpath.jsonpath(obj, '$.data.saleList.*.mediaList[0].coverPic')# 书名的列表name_list = jsonpath.jsonpath(obj, '$.data.saleList.*.mediaList[0].title')# 价格的列表price_list = jsonpath.jsonpath(obj, '$.data.saleList.*.mediaList[0].salePrice')# print(src_list)# print(name_list)# print(price_list)for i in range(len(src_list)):src = src_list[i]# 替换特殊字符为下划线name = name_list[i].strip().replace('/', '_')\.replace('\\', '_').replace(':', '_').replace('【','(').replace('】',')')price = str(price_list[i])+'元'# print(src, name, price)  # 测试代码,验证数据是否获取成功book = ScrapyDangdang095Item(src=src, name=name, price=price)# 需要将book(即ScrapyDangdang095Item对象)交给pipeline下载yield book  # 获取一个book就将book交给管道pipeline

在这里插入图片描述
  修改文件“pipelines.py”的代码,再次运行,发现第6、7、8节的功能都已实现。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
  同理,将连续几页接口的请求地址复制到PyCharm中,观察不同页码的请求地址的变化,根据请求地址的不同观察出其中的规律。
在这里插入图片描述
  如下图所示,继续编写文件“dang.py”的代码(在下载10页图片时具体解决的问题:如何让不规范的文件名字变成合法的文件名字、如何处理相同的文件名字,请自行阅读代码进行理解)。

import scrapy
from ..items import ScrapyDangdang095Item
import jsonpath
import json# import os  # 用于判断哪些文件未成功下载,进而分析原因class DangSpider(scrapy.Spider):name = "dang"# 如果是多页下载,allowed_domains的范围需要调整,‘http://’以及更改的部分不能留allowed_domains = ["e.dangdang.com"]start_urls = ["http://e.dangdang.com/media/api.go?action=mediaCategoryLeaf&promotionType=1&deviceSerial-No=html5&macAddr=html5&channelType=html5&permanentId=20230814120937742356681582820154551&returnType=json&channelId=70000&clientVersionNo=6.8.0&platformSource=DDDS-P&fromPlatform=106&deviceType=pconline&token=&start=0&end=20&category=AQQG&dimension=dd_sale"]# 前三页的接口地址# http://e.dangdang.com/media/api.go?action=mediaCategoryLeaf&promotionType=1&deviceSerial-No=html5&macAddr=html5&channelType=html5&permanentId=20230814120937742356681582820154551&returnType=json&channelId=70000&clientVersionNo=6.8.0&platformSource=DDDS-P&fromPlatform=106&deviceType=pconline&token=&start=0&end=20&category=AQQG&dimension=dd_sale# http://e.dangdang.com/media/api.go?action=mediaCategoryLeaf&promotionType=1&deviceSerial-No=html5&macAddr=html5&channelType=html5&permanentId=20230814120937742356681582820154551&returnType=json&channelId=70000&clientVersionNo=6.8.0&platformSource=DDDS-P&fromPlatform=106&deviceType=pconline&token=&start=21&end=41&category=AQQG&dimension=dd_sale# http://e.dangdang.com/media/api.go?action=mediaCategoryLeaf&promotionType=1&deviceSerial-No=html5&macAddr=html5&channelType=html5&permanentId=20230814120937742356681582820154551&returnType=json&channelId=70000&clientVersionNo=6.8.0&platformSource=DDDS-P&fromPlatform=106&deviceType=pconline&token=&start=42&end=62&category=AQQG&dimension=dd_salebase_url = 'http://e.dangdang.com/media/api.go?action=mediaCategoryLeaf&promotionType=1&deviceSerial-No=html5&macAddr=html5&channelType=html5&permanentId=20230814120937742356681582820154551&returnType=json&channelId=70000&clientVersionNo=6.8.0&platformSource=DDDS-P&fromPlatform=106&deviceType=pconline&token=&'page = 1all_name_list = []  # 所有名字的列表,用于判断哪些文件未成功被下载def parse(self, response):# pipelines     管道用于下载数据# items         定义数据结构print('==========================================')# print(response.text) # 发现获取的是json数据# with open('网页源码.json','w',encoding='UTF-8') as fp:#     fp.write(response.text)# 观察数据后直接使用jsonpath进行解析obj = json.loads(response.text)# 图片地址的列表src_list = jsonpath.jsonpath(obj, '$.data.saleList.*.mediaList[0].coverPic')# 书名的列表name_list = jsonpath.jsonpath(obj, '$.data.saleList.*.mediaList[0].title')# 价格的列表price_list = jsonpath.jsonpath(obj, '$.data.saleList.*.mediaList[0].salePrice')# print(src_list)# print(name_list)# print(price_list)for i in range(len(src_list)):src = src_list[i]# 替换特殊字符为下划线name = name_list[i].strip().replace('/', '_') \.replace('\\', '_').replace(':', '_').replace('【', '(').replace('】', ')') \.replace('?', '_').replace('*', '_')# 防止出现相同的名字name_count = 0while name in self.all_name_list:name_count += 1name = f"{name}_{name_count}"  # 在元素后面添加计数self.all_name_list.append(name)price = str(price_list[i]) + '元'# print(src, name, price)  # 测试代码,验证数据是否获取成功book = ScrapyDangdang095Item(src=src, name=name, price=price)# 需要将book(即ScrapyDangdang095Item对象)交给pipeline下载yield book  # 获取一个book就将book交给管道pipeline# 每一页的爬取的业务逻辑全都是一样的,所以只需要将执行的那个页的请求再次调用parse方法就可以了if self.page < 10:self.page += 1url = self.base_url + f"start={(self.page - 1) * 21}&end={self.page * 21 - 1}&category=AQQG&dimension=dd_sale"# 怎么调用parse方法# scrapy.Request就是scrapy的get请求# - url就是请求地址、callback就是需要执行的函数、parse不能加括号yield scrapy.Request(url=url, callback=self.parse)# # 找到未被下载的图片#     print(len(self.all_name_list))#     print(self.all_name_list)#     for name in self.all_name_list:#         if not os.path.exists(f'./books/{name}.jpg'):#             print(f"未被下载的图片:{name}.jpg")

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

  10.scrapy_电影天堂多页数据下载

  打开电影天堂(网站链接为电影天堂,其实本网站已不再更新,网站已经更换域名,但为了和视频讲解尽量一致,本次演示所选的还是原来的网站),选择国内电影。然后点击“世界上最爱我的人”,发现该电影对应的封面。本次需求是在“items.py”定义本次的数据结构,然后将标题“世界上最爱我的人”和对应图片的地址定义为一个item对象进行下载,最终得到的数据是含标题和图片地址的json文件。如果还想下载图片,请参考上一节的“pipelines.py”的代码。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
  如下图,创建一个名为“scrapy_movie_099”的项目(“scrapy startproject scrapy_movie_099”)。
在这里插入图片描述
  如下图所示,寻找含有电影名字的接口,并复制其请求地址。
在这里插入图片描述
在这里插入图片描述
  然后进入文件夹spiders中(“cd scrapy_movie_099\scrapy_movie_099\spiders”),创建爬虫文件“mv.py”(“scrapy genspider mv 域名”)。
在这里插入图片描述
  然后看看程序是否能正常打印,如果能正常打印则说明不存在反爬。
在这里插入图片描述
在这里插入图片描述
  先去“items.py”中定义本次下载的数据结构。

# 电影的名字
name = scrapy.Field()
# 电影的图片的请求地址
src = scrapy.Field()

在这里插入图片描述
  如下图,找到了电影题目的位置和第二页的地址。
在这里插入图片描述
在这里插入图片描述
  如下图,找到电影电影题目和第二页的地址的xpath路径。
在这里插入图片描述
在这里插入图片描述
  后面发现实际的xpath路径和浏览器里寻找的不一致,故将网页源码写到文件中,根据网页源码手动编写xpath路径,然后运行程序,发现能够获取到电影名字以及第二页的地址。

import scrapyclass MvSpider(scrapy.Spider):name = "mv"allowed_domains = ["www.dytt.to"]start_urls = ["https://www.dytt.to/html/gndy/china/index.html"]def parse(self, response):# 要第一页的名字 和 第二页的图片的地址# 对应的xpath路径# '//table/tr[2]/td[2]/b/a[2]/text()'# '//table/tr[2]/td[2]/b/a[2]/@href'# 将网页源码写进一个文件中with open('mv.html', 'w', encoding='UTF-8') as fp:fp.write(response.text)# a_list:含电影名字以及第二页的地址的标签的列表a_list = response.xpath('//table/tr[2]/td[2]/b/a[2]')for a in a_list:name = a.xpath('./text()').extract_first()href = a.xpath('./@href').extract_first()print(name, href)  # 测试代码,验证是否成功获取电影名字以及第二页的地址

在这里插入图片描述
在这里插入图片描述
  经观察,实际的链接比herf多“https://www.dytt.to/”。
在这里插入图片描述
  与前面同理,找到第二页图片的请求地址的xpath路径,后面实际上运行后与浏览器找的不一样,是把实际的网页源码写成文件找的,此处是span标签和浏览器中不一样(截图已省)。
在这里插入图片描述
  编写“mv.py”代码(注意学会:将name传到meta,以便在定义到的parse方法中收到该参数),在“setting.py”中打开管道,在“pipelines.py”中封装管道,然后运行。

import scrapy
from ..items import ScrapyMovie099Itemclass MvSpider(scrapy.Spider):name = "mv"# 范围可以设大一点allowed_domains = ["www.dytt.to"]start_urls = ["https://www.dytt.to/html/gndy/china/index.html"]def parse(self, response):# 要第一页的名字 和 第二页的图片的地址# 对应的xpath路径# '//table/tr[2]/td[2]/b/a[2]/text()'# '//table/tr[2]/td[2]/b/a[2]/@href'# # 将网页源码写进一个文件中# with open('mv.html', 'w', encoding='UTF-8') as fp:#     fp.write(response.text)# a_list:含电影名字以及第二页的地址的标签的列表a_list = response.xpath('//table/tr[2]/td[2]/b/a[2]')for a in a_list:# 获取第一页的name和要点击的链接hrefname = a.xpath('./text()').extract_first()href = a.xpath('./@href').extract_first()# print(name, href)  # 测试代码,验证是否成功获取电影名字以及第二页的地址# 第二页的地址# 实际的链接比herf多“https://www.dytt.to/”url = 'https://www.dytt.to/' + href# print(name, url)  # 测试代码,验证是否是电影名字以及第二页的地址# 对第二页的链接发起访问  将name传到meta,以便在方法parse_second中收到该参数yield scrapy.Request(url=url, callback=self.parse_second, meta={'name': name})def parse_second(self, response):# print('1234567890')  # 验证是否会执行本方法# # 将网页源码写进一个文件中# with open('mv_picture.html', 'w', encoding='UTF-8') as fp:#     fp.write(response.text)# 第二页图片的请求地址src = response.xpath('//div[@id="Zoom"]//img/@src').extract_first()# print(src)  # 测试代码,验证是否获取到第二页图片的请求地址# 接收到请求的meta参数的值   实际就是电影名字name = response.meta['name']movie = ScrapyMovie099Item(src=src, name=name)# 将movie返回给管道yield movie

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

# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: https://docs.scrapy.org/en/latest/topics/item-pipeline.html# useful for handling different item types with a single interface
from itemadapter import ItemAdapterclass ScrapyMovie099Pipeline:# 打开管道def open_spider(self, spider):self.fp = open('movie.json', 'w', encoding='UTF-8')def process_item(self, item, spider):self.fp.write(str(item))return item# 关闭管道def close_spider(self,spider):self.fp.close()

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

  11. scrapy_链接提取器CrawlSpider的使用(含MySql、pymysql的使用)

  本节将使用CrawlSpider简单地爬取数据,熟悉CrawlSpider的链接提取器的语法,然后下下一节将使用MySql、pymysql将数据放入数据库中。

  (1)MySQL的安装和初级使用

  关于MySQL的安装和初级使用,请参考本人的笔记:第二阶段-第二章 SQL入门和实战

  (2)CrawlSpider的作用

在这里插入图片描述
  比如,我们可以设定一个规则,然后把当前页面所有符合这个规则的链接提取出来,然后对这些链接进行解析就可以了。
在这里插入图片描述

  (3)CrawlSpider的使用方法

在这里插入图片描述
  对于链接提取器而言,常用的是正则表达式、xpath、css,即allow=()、restrict_xpaths =()、restrict_css =()。
在这里插入图片描述

  (4)代码演示

  本次将以读书网进行演示,使用正则表达式和xpath来提取页码的链接。如下图,打开读书网,选择“当代小说”,然后在检查中找到页码的链接。然后,复制读书网的当代小说的第一页的链接。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
  如下图所示,使用scrapy shell进入读书网的当代小说的第一页的页面,输入“from scrapy.linkextractors import LinkExtractor”导入链接提取器。
在这里插入图片描述
  首先使用正则表达式提取页码的链接(“link = LinkExtrac-tor(allow=r’/book/1188_\d+.html’)”),“\d”表示一个数字,“\d+”表示可以有一到多个数字,然后打印一下验证正则表达式是否书写正确(“link.extract_links(response)”)。
在这里插入图片描述
  然后再使用xpath路径提取页码的链接(“link1 = LinkExtrac-tor(restrict_xpaths=r’//div[@class=“pages”]/a’)”,别加“@href”,否则提取不了),然后打印一下验证正则表达式是否书写正确(“link1.extract_links(response)”)。
在这里插入图片描述
在这里插入图片描述

  12.scrapy_crawlspider读书网获取图片的封面地址和名字

  紧跟着上一节,本节继续。

  (1)CrawlSpider的使用步骤

在这里插入图片描述

  (2)代码演示

  本节紧接着上一节,使用CrawlSpider爬取读书网中当代小说的书名和书的封面的地址,下一节使用MySql、pymysql将数据放入数据库中。
  首先,创建一个名为“scrapy_readbook_101”的项目(“scrapy startproject scrapy_readbook_101”)。
在这里插入图片描述
  先去复制读书网当代小说第一页的地址,然后回到PyCharm终端,进入文件夹“spiders”(“cd scrapy_readbook_101\scrapy_readbook_101\spiders”),创建爬虫文件”read.py”(指令为“scrapy genspider -t crawl read 域名”,与之前创建的scrapy爬虫文件的指令有所不同)。
在这里插入图片描述
在这里插入图片描述
  创建一个名为“test”的文件,用来记录本次案例的流程。
在这里插入图片描述

1. 创建项目 scrapy startproject 项目的名字
2. 跳转到spiders文件夹的目录下cd 项目名字\项目名字\spiders
3. 创建爬虫文件scrapy genspider -t crawl 爬虫文件的名字 爬取的域名

在这里插入图片描述
  如下图,根据页码的链接的变化规律在代码相应的地方编写正则表达式(注:在正则表达式中,“.”是通配符,故特指点需要使用反斜杠来转义,即“.”)。
在这里插入图片描述
  然后去“items.py”中定义本次下载的数据的结构。

# 书名
name = scrapy.Field()
# 书的封面的地址
src = scrapy.Field()

在这里插入图片描述
  然后去寻找书名和封面地址的xpath路径,看到“data-original”就想到懒加载,即封面地址是属性“data-original”里的内容。发现有本书由于缺少封面,导致data-original获取的内容少一项,少的那一项需要通过属性src来获取标有读书网的图片的地址。
在这里插入图片描述
在这里插入图片描述
  如下编写爬虫文件“read.py”的代码。

import scrapy
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
from ..items import ScrapyReadbook101Itemclass ReadSpider(CrawlSpider):name = "read"# 范围设大点,得包含其他页allowed_domains = ["www.dushu.com"]start_urls = ["https://www.dushu.com/book/1188.html"]rules = (Rule(LinkExtractor(allow=r"/book/1188_\d+\.html"),callback="parse_item",follow=False),)def parse_item(self, response):# 书名和封面的xpath路径# //li/div/div/a/img/@alt# //li/div/div/a/img/@data-original# 发现有本书由于缺少封面,导致data-original获取的内容少一项,# 少的那一项需要通过属性src来获取标有读书网的图片的地址。img_list = response.xpath('//li/div/div/a/img')for img in img_list:name = img.xpath('./@alt').extract_first()src = img.xpath('./@data-original').extract_first()if not src:src = img.xpath('./@src').extract_first()# print(name, src)  # 测试代码,验证是否拿到书名和封面链接book = ScrapyReadbook101Item(name=name, src=src)yield book

  如下去文件“pipelines.py”封装管道。

# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: https://docs.scrapy.org/en/latest/topics/item-pipeline.html# useful for handling different item types with a single interface
from itemadapter import ItemAdapterclass ScrapyReadbook101Pipeline:def open_spider(self, spider):self.fp = open('book.json', 'w', encoding='UTF-8')def process_item(self, item, spider):self.fp.write(str(item))return itemdef close_spider(self, spider):self.fp.close()

在这里插入图片描述
  去文件“setting.py”中打开管道。
在这里插入图片描述
  运行代码,发现数据不够。
在这里插入图片描述
  由于520-480=40,猜测少了一页数据。注意此处有一个坑,首页并不在我们所设的正则表达式的规则里。
在这里插入图片描述
  尝试将链接“https://www.dushu.com/book/1188.html”改成“https://www.dushu.com/book/1188_1.html”后发现这还是第一页,故去修改“read.py”的起始链接,然后再运行(“scrapy crawl read”),去文件“book.json”发现数据不再缺少。
在这里插入图片描述

import scrapy
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
from ..items import ScrapyReadbook101Itemclass ReadSpider(CrawlSpider):name = "read"# 范围设大点,得包含其他页allowed_domains = ["www.dushu.com"]start_urls = ["https://www.dushu.com/book/1188_1.html"]rules = (Rule(LinkExtractor(allow=r"/book/1188_\d+\.html"),callback="parse_item",follow=False),)def parse_item(self, response):# 书名和封面的xpath路径# //li/div/div/a/img/@alt# //li/div/div/a/img/@data-original# 发现有本书由于缺少封面,导致data-original获取的内容少一项,# 少的那一项需要通过属性src来获取标有读书网的图片的地址。img_list = response.xpath('//li/div/div/a/img')for img in img_list:name = img.xpath('./@alt').extract_first()src = img.xpath('./@data-original').extract_first()if not src:src = img.xpath('./@src').extract_first()# print(name, src)  # 测试代码,验证是否拿到书名和封面链接book = ScrapyReadbook101Item(name=name, src=src)yield book

在这里插入图片描述

  13.scrapy_读书网数据入库和链接跟进(失败,卡在最后的“由于日标计算机积极拒绝”,没有系统学过MySQL,卡住了)

  紧跟着上一节,本节继续。接下来我们需要将爬取的数据存储到数据库中。为了模拟干活时使用的数据库,本次使用了VMware上的虚拟机Ubuntu。

  (1)准备工作(安装Ubuntu、在Ubuntu上安装mysql中途含出现的两个问题的解决办法、Windows上安装pymysql)

  安装带有Ubuntu的VMware虚拟机,而且Ubuntu中还需要安装mysql,在Windows上安装pymysql。
  至于如何安装VMware、如何在VMware上安装Ubuntu,请参考本人的笔记“第一章 初识Linux(含VMware安装Ubuntu、CentOS、Windows、快照)”进行安装。
  至于MySql的使用方法,对与初级使用而言,本人的CSDN笔记足以应对:第二阶段-第二章 SQL入门和实战。
  至于如何在Ubuntu上安装mysql,本人参考如下连接进行安装的:Ubuntu下安装MySQL数据库,具体步骤如下:
  在FinalShell(直接在VMware中的Ubuntu界面也是一样)输入命令更新一下软件包,然后安装MySQL数据库。(视频里能正常安装,本人的却出现了问题)

sudo apt update    # 更新软件包
sudo apt install mysql-server    # 安装MySQL数据库

在这里插入图片描述在这里插入图片描述
  然后如下图所示,输入一堆命令后成功解决该问题。(这个报错需要根据提示解决。起初没注意看,直接网上查,查到的一堆博客没有一个能解决该问题,后面才看到这句提示,大意了)

sudo apt install mysql-server    # 安装MySQL数据库
apt --fix-broken install
sudo su       # 进入管理员模式
exit          # 如果在root状态,退出管理员模式

在这里插入图片描述
在这里插入图片描述
  然后就是配置安全设置。

sudo mysql_secure_installation    # 配置安全设置

在这里插入图片描述
在这里插入图片描述
  然后检查mysql server是否正在运行(如果出现“lines 1-14/14 (END”,需按Ctr+C结束)。

systemctl status mysql.service    # 检查mysql server是否正在运行

在这里插入图片描述
  连接mysql时报错“ERROR 1045 (28000): Access denied for user ‘-root’@‘localhost’ (using password: YES)”或者“ERROR 1698 (28000): Access denied for user ‘root’@‘localhost’”,找了半天终于按照链接mysqlERROR1698(28000):Access denied for user root@localhost错误解决方法中的STEP1成功解决问题,如下一堆图所示。到此,Ubuntu上已经成功安装pymysql。

sudo mysql -u -root -p    # 连接mysql,sudo是使用root权限的意思,下图中有一处没加sudo一样可以连接mysql
sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf    # 编辑文件
service mysql restart    # 重启mysql
show schemas;      # 在mysql里输入表示查询自带的数据库
exit       # 在mysql里输入表示退出mysql

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
  至于如何在Windows上安装pymysql,如下图所示,打开命令提示符,然后输入一堆指令完成安装(本人之前装过,就直接截的视频的图)。

cd python的安装目录/Scripts      # 进入python的库文件夹
pip install pymysql  # 安装库pymysql  如果安装太慢,在该条指令后面加上“-i 镜像源的网址”

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

  (2)pymysql的使用步骤

# 具体如何使用请看演示
pip install pymysql  # 安装pymysql
self.conn=pymysql.connect(host, port, user, password, db, charset) # 连接mysql
self.cursor=self.conn.cursor()
cursor.execute()   # 执行mysql代码

  (3)本次的演示(失败,卡在最后的“由于日标计算机积极拒绝”)

  本次需要使用Ubuntu去数据库中创建一个和上一节爬取到的数据的结构一样的表,然后将爬取的数据插入表中。
  双击打开VMware,然后选择Ubuntu进行登录。
在这里插入图片描述
在这里插入图片描述
  打开终端,连接mysql,创建数据库spider01。

sudo mysql -u -root -p    # 连接mysql
create database spider01 charset utf8;    # 创建数据库spider01
show schemas;      # 在mysql里输入表示查询自带的数据库

在这里插入图片描述
在这里插入图片描述
  然后使用刚刚创建的数据库,创建一张表。

use spider01;       # 使用数据库spider01
create table book(id int primary key auto_increment,name varchar(128),src varchar(128));     # 在当前使用的库中创建一张表book,包含id、name和src三列,id列将作为自增的主键,其他两列字符长度最大均为128
select * from book;     # 查询表book的内容

在这里插入图片描述
  表创建成功后,接下来需要将爬取的数据插入这个表中。首先,打开新的终端来查询Ubuntu的ip地址。

ip address show     # 查询ip

在这里插入图片描述
  打开PyCharm,在文件“setting.py”中配置几个参数,即随便找个位置输入下面几行代码(参数请根据自己的情况进行修改)。

DB_HOST = '192.168.13.129'   # 根据刚刚查询的ip设置主机的ip地址
DB_PORT = 3306           # 端口号是一个整数
DB_USER = 'jane'          # Ubuntu的用户名
DB_PASSWORD = '12345'   # Ubuntu的密码
DB_NAME = 'spider01'      # 数据库的名字
DB_CHARSET = 'UTF-8'    # 指定字符集

在这里插入图片描述
    再去“pipelines.py”中造一个管道,以便传到Ubuntu。

# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: https://docs.scrapy.org/en/latest/topics/item-pipeline.html# useful for handling different item types with a single interface
from itemadapter import ItemAdapterclass ScrapyReadbook101Pipeline:def open_spider(self, spider):self.fp = open('book.json', 'w', encoding='UTF-8')def process_item(self, item, spider):self.fp.write(str(item))return itemdef close_spider(self, spider):self.fp.close()# 导入setting文件
from scrapy.utils.project import get_project_settings
import pymysql# 将数据传输给Ubuntu的管道
class MysqlPipeline:# 连接MySqldef open_spider(self, spider):settings = get_project_settings()  # 加载setting文件self.host = settings['DB_HOST']self.port = settings['DB_PORT']self.user = settings['DB_USER']self.password = settings['DB_PASSWORD']self.name = settings['DB_NAME']self.charset = settings['DB_CHARSET']# 调用coonnect()连接musqlself.coonnect()def coonnect(self):"""连接MySql的函数"""self.conn = pymysql.connect(host=self.host,port=self.port,user=self.user,password=self.password,db=self.name,charset=self.charset)self.cursor = self.conn.cursor()def process_item(self, item, spider):# MySQL语句,将数据传入表book中sql = 'insert into book(name,src) values("{}","{}")'.format(item['name'], item['src'])self.cursor.execute(sql)  # 执行mysql语句self.conn.commit() # 确认提交return item# 断开MySql的连接def close_spider(self, spider):self.cursor.close()self.conn.close()

  在文件“setting.py”中打开管道。

    # MysqlPipeline"scrapy_readbook_101.pipelines.MysqlPipeline": 301

在这里插入图片描述
  运行程序,发现有“encoding”报错。

cd 爬虫的scrapy
cd scrapy_readbook_101\scrapy_readbook_101\spiders
scrapy crawl read

在这里插入图片描述
在这里插入图片描述
  然后进行如下修改,另外为了爬取所有所有数据(页数不局限于13页),故去修改“read.py”中的一个参数,然后再运行程序。

scrapy crawl read

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
  查了一堆还是不会解决这个问题,希望有成功解决的兄弟分享一下方法。
  比如下面的方法连个截图都没有,真抽象,没有解决问题。按照“https://blog.csdn.net/wangshuminjava/article/details/79310086”的提示,去ping一下Ubuntu的ip,telnet一下Ubuntu的端口(如果提示’telnet’ 不是内部或外部命令,请参考“https://blog.csdn.net/qq_36292543/article/details/119645130”去打开telnet)。

ping 192.168.13.129    # 验证是否能连通Ubuntu的ip
telnet 192.168.13.129 3306  # 验证是否能使用3306端口连接到Ubuntu

在这里插入图片描述
  修改防火墙允许3306也不行(方法来源于“https://blog.csdn.net/qq_43567345/article/details/105323795”)。改权限grant还失效,好多给出的解决办法都是针对的5.7,新版的较少。就算有,没有系统学过MySQL的东西暂时看不明白。
已放弃,一时半会是解决不了的。

  注:由于本节内容因为卡在最后一步不能正常运行,需要将本节新添的代码注释掉。

  14. scrapy_日志信息以及日志级别

  (1)日志信息的定义、等级、如何设置日志

  如下图所示,运行第12节的代码后会出现很多信息,这些都是scrapy的日志信息。对我们而言,不需要看浏览这么多信息。
在这里插入图片描述
在这里插入图片描述

  (2)代码演示

  如下图,创建项目和爬虫文件。

cd 爬虫的scrapy      # 进入文件夹“爬虫的scrapy”
scrapy startproject scrapy_log_103     # 创建项目“scrapy_log_103”
cd scrapy_log_103\scrapy_log_103\spiders    # 进入爬虫文件所在的文件夹
scrapy genspider log www.baidu.com       # 创建爬虫文件“log.py”

在这里插入图片描述
  如下图,尝试打印一条信息,结果没有打印。

scrapy crawl log    # 执行程序

在这里插入图片描述
  如下图,注释robots协议即可正常打印。

scrapy crawl log    # 执行程序

在这里插入图片描述
在这里插入图片描述
  加一行代码后,可以看到日志信息被屏蔽。

# 指定日志的级别
LOG_LEVEL = 'WARNING'

在这里插入图片描述
  但是如果按照上图来设置后,当报错时,会看不到调试信息。为了规避这个问题,写成如下图所示的代码即可,如果代码报错,去查看日志文件即可。

# # 指定日志的级别
# LOG_LEVEL = 'WARNING'
LOG_FILE = 'logdemo.log'

在这里插入图片描述

  15.scrapy_百度翻译post请求

  (1)scrapy 下的post请求的用法

在这里插入图片描述

  (2)代码演示

  如下图,去百度翻译中打开检查,选择网络,随便输一个英文单词,然后找到它的接口并复制请求地址。
在这里插入图片描述
在这里插入图片描述
  如下图所示,创建项目和爬虫文件。
cd 爬虫的scrapy # 进入文件夹“爬虫的scrapy”

scrapy startproject scrapy_post_104   # 创建项目“scrapy_post_104”
cd scrapy_post_104\scrapy_post_104\spiders    # 进入文件夹“spiders”
scrapy genspider test_post https://fanyi.baidu.com/sug     # 创建爬虫文件“test_post.py”

在这里插入图片描述
  目前有一个问题,这个post请求会查询单词,而在代码文件“test_post.py”中看不出来它所携带的参数(即所查的单词)在什么位置。我们要知道,不含参数的post请请求是没有意义的,即start_urls没有用。由于start_urls决定着parse的执行,故方法parse也没有用。
  故在文件“test_post.py”如下编写代码。

import scrapyclass TestPostSpider(scrapy.Spider):name = "test_post"allowed_domains = ["fanyi.baidu.com"]# # post请求 如果没有参数 那么这个请求将没有任何意义# # 所以start_urls  也没有用了# # parse方法也没有用了# start_urls = ["https://fanyi.baidu.com/sug"]## def parse(self, response):#     passdef start_requests(self):url = 'https://fanyi.baidu.com/sug'data = {'kw': 'final'  # 参数可在浏览器的检查里的接口的负载中查到}yield scrapy.FormRequest(url=url, formdata=data, callback=self.parse_second)def parse_second(self, response):content = response.textprint(content)

  去“setting.py”中设置日志信息,然后再运行程序。

# 保存日志文件
LOG_FILE = 'test_post.log'

在这里插入图片描述
  由上图知,存在编码问题。故继续在文件“test_post.py”编写代码,并运行。

import scrapy
import jsonclass TestPostSpider(scrapy.Spider):name = "test_post"allowed_domains = ["fanyi.baidu.com"]# # post请求 如果没有参数 那么这个请求将没有任何意义# # 所以start_urls  也没有用了# # parse方法也没有用了# start_urls = ["https://fanyi.baidu.com/sug"]## def parse(self, response):#     passdef start_requests(self):url = 'https://fanyi.baidu.com/sug'data = {'kw': 'final'  # 参数可在浏览器的检查里的接口的负载中查到}yield scrapy.FormRequest(url=url, formdata=data, callback=self.parse_second)def parse_second(self, response):content = response.textobj = json.loads(content)print(obj)

在这里插入图片描述
  好了,本章的笔记到此结束,谢谢大家阅读。写完本章博客,人都快废了。

相关文章:

Python爬虫的scrapy的学习(学习于b站尚硅谷)

目录 一、scrapy  1. scrapy的安装  &#xff08;1&#xff09;什么是scrapy  &#xff08;2&#xff09;scrapy的安装 2. scrapy的基本使用  &#xff08;1&#xff09;scrap的使用步骤  &#xff08;2&#xff09;代码的演示 3. scrapy之58同城项目结构和基本方法&…...

“深入解析JVM:揭秘Java虚拟机的工作原理“

标题&#xff1a;深入解析JVM&#xff1a;揭秘Java虚拟机的工作原理 摘要&#xff1a;本文将深入解析Java虚拟机&#xff08;JVM&#xff09;的工作原理&#xff0c;探讨其内部结构和运行机制。我们将介绍JVM的组成部分、类加载过程、内存管理、垃圾回收、即时编译等关键概念&…...

【数据结构与算法】十大经典排序算法-归并排序

&#x1f31f;个人博客&#xff1a;www.hellocode.top &#x1f3f0;Java知识导航&#xff1a;Java-Navigate &#x1f525;CSDN&#xff1a;HelloCode. &#x1f31e;知乎&#xff1a;HelloCode &#x1f334;掘金&#xff1a;HelloCode ⚡如有问题&#xff0c;欢迎指正&#…...

基于深度学习创建-表情符号--附源码

表情符号深度学习概述 如今,我们使用多种表情符号或头像来表达我们的心情或感受。它们充当人类的非语言线索。它们成为情感识别、在线聊天、品牌情感、产品评论等的关键部分。针对表情符号驱动的故事讲述的数据科学研究不断增加。 从图像中检测人类情绪非常流行,这可能是由…...

.netcore grpc的proto文件字段详解

一、.proto文件字段概述 grpc的接口传输参数都是根据.proto文件约定的字段格式进行传输的grpc提供了多种类型字段&#xff1b;主要包括标量值类型&#xff08;基础类型&#xff09;、日期时间、可为null类型、字节、列表、字典、Any类型&#xff08;任意类型&#xff09;、One…...

带你了解建堆的时间复杂度

目录 用向上调整建堆的时间复杂度 1.向上调整建堆的时间复杂度O(N*logN) 2.数学论证 3.相关代码 用向下调整建堆的时间复杂度 1.建堆的时间复杂度为O(N) 2.数学论证 3.相关代码 完结撒花✿✿ヽ(▽)ノ✿✿ 博主建议:面试的时候可能会被面试官问到建堆时间复杂度的证明过…...

人工智能原理(6)

目录 一、机器学习概述 1、学习和机器学习 2、学习系统 3、机器学习发展简史 4、机器学习分类 二、归纳学习 1、归纳学习的基本概念 2、变型空间学习 3、归纳偏置 三、决策树 1、决策树组成 2、决策树的构造算法CLS 3、ID3 4、决策树的偏置 四、基于实例的学习…...

单片机模块化编程文件创建流程

一、在工程文件夹下创建一个新的文件夹&#xff0c;命名为“ModulesCodesFiles”&#xff0c;译为“模块化代码文件”&#xff0c;用于存放所有模块化代码文件。 二、在“ModulesCodesFiles”文件夹下为每个模块创建一个新的文件夹&#xff0c;命名为模块的名称&#xff0c;例…...

docker image

docker image 1. 由来 docker image是Docker容器管理工具中的一个命令&#xff0c;用于管理和操作Docker镜像。 2. 常见五种示例命令和说明 以下是docker image的常见示例命令及其说明&#xff1a; 示例一&#xff1a;列出所有镜像 docker image ls描述&#xff1a;使用d…...

力扣75——单调栈

总结leetcode75中的单调栈算法题解题思路。 上一篇&#xff1a;力扣75——区间集合 力扣75——单调栈 1 每日温度2 股票价格跨度1 - 2 解题总结 1 每日温度 题目&#xff1a; 给定一个整数数组 temperatures &#xff0c;表示每天的温度&#xff0c;返回一个数组 answer &…...

Webpack和Parcel详解

构建工具和打包器是在开发过程中帮助组织、优化和打包项目的工具。它们可以处理依赖管理、资源优化、代码转换等任务&#xff0c;从而使开发流程更高效。以下是关于构建工具和打包器的一些指导&#xff1a; **Webpack&#xff1a;** Webpack 是一个功能强大的模块打包器&#…...

linux系统服务学习(六)FTP服务学习

文章目录 FTP、NFS、SAMBA系统服务一、FTP服务概述1、FTP服务介绍2、FTP服务的客户端工具3、FTP的两种运行模式&#xff08;了解&#xff09;☆ 主动模式☆ 被动模式 4、搭建FTP服务&#xff08;重要&#xff09;5、FTP的配置文件详解&#xff08;重要&#xff09; 二、FTP任务…...

7.原 型

7.1原型 【例如】 另外- this指向&#xff1a; 构造函数和原型对象中的this都指向实例化的对象 7.2 constructor属性 每个原型对象里面都有个constructor属性( constructor构造函数) 作用&#xff1a;该属性指向该原型对象的构造函数 使用场景: 如果有多个对象的方法&#…...

【图像分类】理论篇(2)经典卷积神经网络 Lenet~Resenet

目录 1、卷积运算 2、经典卷积神经网络 2.1 Lenet 网络构架 代码实现 2.2 Alexnet 网络构架 代码实现 2.3 VGG VGG16网络构架 代码实现 2.4 ResNet ResNet50网络构架 代码实现 1、卷积运算 在二维卷积运算中&#xff0c;卷积窗口从输入张量的左上角开始&#xff…...

C++系列-内存模型

内存模型 内存模型四个区代码区全局区栈区堆区内存开辟和释放在堆区开辟数组 内存模型四个区 不同区域存放的数据生命周期是不同的&#xff0c;更为灵活。 代码区&#xff1a;存放函数体的二进制代码&#xff0c;操作系统管理。全局区&#xff1a;存放全局变量&#xff0c;常…...

[管理与领导-30]:IT基层管理者 - 人的管理 - 向上管理,管理好你的上司,职业发展事半功倍。什么样的上司不值得跟随?

目录 前言&#xff1a; 一、什么是向上管理 二、为什么要向上管理 三、如何进行向上管理 四、向上管理的注意事项 五、向上管理的忌讳 六、向上管理常犯的错 七、如何帮助上司解决他关心的问题 7.1 如何帮助上司解决他关心的问题 7.2 如何帮助上司降低压力 八、什么…...

Java进阶篇--迭代器模式

目录 同步迭代器&#xff08;Synchronous Iterator&#xff09;&#xff1a; Iterator 接口 常用方法&#xff1a; 注意&#xff1a; 扩展小知识: 异步迭代器&#xff08;Asynchronous Iterator&#xff09;&#xff1a; 常用的方法 注意&#xff1a; 总结&#xff1a…...

【CAM】CAM(Class Activation Mapping)——可视化CNN的特征定位

文章目录 一、CAM(Class Activation Mapping)二、CAM技术实现2.1 网络修改2.2 微调2.2 特征提取 三、总结Reference 完整代码见Github &#xff1a;https://github.com/capsule2077/CAM-Visualization &#xff0c;如果有用可以点个Star&#xff0c;谢谢&#xff01; 一、CAM(C…...

Maven教程_编程入门自学教程_菜鸟教程-免费教程分享

教程简介 Maven 是一款基于 Java 平台的项目管理和整合工具&#xff0c;它将项目的开发和管理过程抽象成一个项目对象模型&#xff08;POM&#xff09;。开发人员只需要做一些简单的配置&#xff0c;Maven 就可以自动完成项目的编译、测试、打包、发布以及部署等工作。Maven 是…...

Gof23设计模式之模板方法模式

1.定义 定义一个操作中的算法骨架&#xff0c;而将算法的一些步骤延迟到子类中&#xff0c;使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤。 2.结构 模板方法&#xff08;Template Method&#xff09;模式包含以下主要角色&#xff1a; 抽象类&#xff0…...

springBoot 配置文件 spring.resources.add-mappings 参数的作用

在Spring Boot应用中&#xff0c;spring.resources.add-mappings参数用于控制是否将特定路径的资源文件添加到URL路径映射中。 默认情况下&#xff0c;该参数的值为true&#xff0c;即会自动将静态资源&#xff08;例如CSS、JavaScript、图片等&#xff09;的URL路径添加到Spr…...

《Java极简设计模式》第03章:工厂方法模式(FactoryMethod)

作者&#xff1a;冰河 星球&#xff1a;http://m6z.cn/6aeFbs 博客&#xff1a;https://binghe.gitcode.host 文章汇总&#xff1a;https://binghe.gitcode.host/md/all/all.html 源码地址&#xff1a;https://github.com/binghe001/java-simple-design-patterns/tree/master/j…...

C++11并发与多线程笔记(11) std::atomic续谈、std::async深入谈

C11并发与多线程笔记&#xff08;11&#xff09; std::atomic续谈、std::async深入谈 1、std::atomic续谈2、std::async深入理解2.1 std::async参数详述2.2 std::async和std::thread()区别&#xff1a;2.3 async不确定性问题的解决 1、std::atomic续谈 #include <iostream&…...

React快速入门

最近需要学到react&#xff0c;这里进行一个快速的入门&#xff0c;参考react官网 1.创建和嵌套组件 react的组件封装是个思想&#xff0c;我这里快速演示代码&#xff0c;自己本身也不太熟悉。 代码的路径是src底下的App.js function MyButton() {return (<button>I…...

windows权限维持—SSPHOOKDSRMSIDhistorySkeletonKey

windows权限维持—SSP&HOOK&DSRM&SIDhistory&SkeletonKey 1. 权限维持介绍1.1. 其他 2. 基于验证DLL加载—SPP2.1. 操作演示—临时生效2.1.1. 执行命令2.1.2. 切换用户 2.2. 操作演示—永久生效2.2.1. 上传文件2.2.2. 执行命令2.2.3. 重启生效 2.3. 总结 3. 基…...

CSS 两栏布局和三栏布局的实现

文章目录 一、两栏布局的实现1. floatmargin2. flaotBFC3. 定位margin4. flex 布局5. grid布局 二、三栏布局的实现1. float margin2. float BFC3. 定位 margin(或者定位BFC)4. flex布局5. 圣杯布局6. 双飞翼布局 一、两栏布局的实现 两栏布局其实就是左侧定宽&#xff0c;…...

消息中间件相关面试题

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是爱发博客的嗯哼&#xff0c;爱好Java的小菜鸟 &#x1f525;如果感觉博主的文章还不错的话&#xff0c;请&#x1f44d;三连支持&#x1f44d;一下博主哦 &#x1f4dd;社区论坛&#xff1a;希望大家能加入社区共同进步…...

成集云 | 电子签署集成腾讯云企业网盘 | 解决方案

源系统成集云目标系统 方案介绍 电子签署是通过电子方式完成合同、文件或其他文件的签署过程。相较于传统的纸质签署&#xff0c;电子签署具有更高效、更便捷、更安全的优势。 在电子签署过程中&#xff0c;使用电子签名技术来验证签署者的身份并确保签署文件的完整性。电子…...

提升大数据技能,不再颓废!这6家学习网站是你的利器!

随着国家数字化转型&#xff0c;大数据领域对人才的需求越来越多。大数据主要研究计算机科学和大数据处理技术等相关的知识和技能&#xff0c;从大数据应用的三个主要层面&#xff08;即数据管理、系统开发、海量数据分析与挖掘&#xff09;出发&#xff0c;对实际问题进行分析…...

uniapp开发小程序-有分类和列表时,进入页面默认选中第一个分类

一、效果&#xff1a; 如下图所示&#xff0c;进入该页面后&#xff0c;默认选中第一个分类&#xff0c;以及第一个分类下的列表数据。 二、代码实现&#xff1a; 关键代码&#xff1a; 进入页面时&#xff0c;默认调用分类的接口&#xff0c;在分类接口里做判断&#xff…...

小程序-uni-app:hbuildx uni-app 安装 uni-icons 及使用

一、官方文档找到uni-icons uni-app官网 二、下载插件 三、点击“打开HBuildX” 四、选择要安装的项目 五、勾选要安装的插件 六、安装后&#xff0c;项目插件目录 根目录uni_modules目录下增加uni-icons、uni-scss 七、引入组件&#xff0c;使用组件 <uni-icons type&qu…...

PHP中in_array()函数用法详解

in_array() 函数是PHP中常用的数组函数之一&#xff0c;用于搜索数组中是否存在指定的值。 语法 bool in_array ( mixed $needle , array $haystack [, bool $strict FALSE ] ) 参数描述needle必需。规定要在数组搜索的值。haystack必需。规定要搜索的数组。strict可选。如…...

热电联产在综合能源系统中的选址定容研究(matlab代码)

目录 1 主要内容 目标函数 程序模型 2 部分代码 3 程序结果 1 主要内容 该程序参考《热电联产在区域综合能源系统中的定容选址研究》&#xff0c;主要针对电热综合能源系统进行优化&#xff0c;确定热电联产机组的位置和容量&#xff0c;程序以33节点电网和17节点热网为例…...

校园网安全风险分析

⒈物理层的安全风险分析 网络的物理安全风险主要指网络周边环境和物理特性引起的网络设备和线路的不可用 , 而 造成网络系统的不可用。我们在考虑校园网络安全时&#xff0c;首先要考虑物理安全风险&#xff0c;它是整个 网络系统安全的前提。物理安全风险有&#xff1a;设备…...

kafka--kafka的基本概念-topic和partition

一、kafka的基本概念-topic和partition 1、topic &#xff08;主题 &#xff09; topic是逻辑概念 以Topic机制来对消息进行分类的&#xff0c;同一类消息属于同一个Topic&#xff0c;你可以将每个topic看成是一个消息队列。 生产者&#xff08;producer&#xff09;将消息发…...

【LVS】3、LVS+Keepalived群集

为什么用它&#xff0c;为了做高可用 服务功能 1.故障自动切换 2.健康检查 3.节点服务器高可用-HA Keepalived的三个模块&#xff1a; core&#xff1a;Keepalived的核心&#xff0c;负责主进程的启动、维护&#xff1b;调用全局配置文件进行加载和解析 vrrp&#xff1a;实…...

对前端PWA应用的部分理解和基础Demo

一、什么是PWA应用&#xff1f; 1、PWA简介 ​ 渐进式Web应用&#xff08;Progressive Web App&#xff09;&#xff0c;简称PWA&#xff0c;是 Google 在 2015 年提出的一种使用web平台技术构建的应用程序&#xff0c;官方认为其核心在于Reliable&#xff08;可靠的&#xf…...

CSGO饰品价格会一直下跌吗?市场何时止跌回升?

最后一届巴黎major终于落下帷幕&#xff0c;Vitality小蜜蜂2-0战胜GL成功赢下本次Major冠军&#xff0c;也是首次夺得Major冠军&#xff01;有人欢喜有人忧啊&#xff0c;csgo搬砖的饰品商人们一点也高兴不起来。 4月-5月&#xff0c;csgo皮肤饰品已持续走低快两个月了。手里满…...

线程池原理

一、线程池的定义 线程池&#xff0c;按照配置参数&#xff08;核心线程数、最大线程数等&#xff09;创建并管理若干线程对象&#xff0c;没有任务的时候&#xff0c;这些线程都处于等待空闲状态。如果有新的线程任务&#xff0c;就分配一个空闲线程执行。如果所有线程都处于…...

拷贝构造函数

1. 拷贝构造函数是构造函数的一个重载形式。 2. 拷贝构造函数的参数只有一个且必须是类类型对象的引用&#xff0c;使用传值方式编译器直接报错&#xff0c; 因为会引发无穷递归调用。 class Date { public:Date(int year 1900, int month 1, int day 1){_year year;_mont…...

数据库: MySQL安装部署、主从

单机部署 mkdir -p /opt/soft/archive cd /opt/soft/archivewget -i -c https://dev.mysql.com/get/mysql80-community-release-el7-7.noarch.rpm yum install -y mysql80-community-release-el7-7.noarch.rpm yum-config-manager --enable mysql80-community yum install -y …...

Java IO流(二)IO模型(BIO|NIO|AIO)

概述 Java IO模型同步阻塞IO&#xff08;BIO&#xff09;、同步非阻塞IO&#xff08;NIO&#xff09;、异步非阻塞IO&#xff08;AIO/NIO2&#xff09;,Java中的BIO、NIO和AIO理解为是Java语言对操作系统的各种IO模型的封装 IO模型 BIO(Blocking I/O) 概述 BIO是一种同步并阻…...

java版本spring cloud 企业工程系统管理 工程项目管理系统源码em

工程项目管理软件&#xff08;工程项目管理系统&#xff09;对建设工程项目管理组织建设、项目策划决策、规划设计、施工建设到竣工交付、总结评估、运维运营&#xff0c;全过程、全方位的对项目进行综合管理 工程项目各模块及其功能点清单 一、系统管理 1、数据字典&#xff…...

飞天使-k8s简单搭建

文章目录 k8s概念安装部署-第一版无密钥配置与hosts与关闭swap开启ipv4转发安装前启用脚本开启ip_vs安装指定版本docker 安装kubeadm kubectl kubelet,此部分为基础构建模版 k8s一主一worker节点部署k8s三个master部署,如果负载均衡keepalived 不可用&#xff0c;可以用单节点做…...

java中把一个list转tree的方法

环境 我们有个需求&#xff0c;数据库要存一个无限级联的tree&#xff0c;比如菜单&#xff0c;目录&#xff0c;或者地区等数据&#xff0c;现有两个问题&#xff1a; 问如何设计表。怎么返回给前端一个无线级联的json数据。 思考 第一个问题 在设计表的时候&#xff0c;…...

QT设置widget背景图片

首先说方法&#xff0c;在给widget或者frame或者其他任何类型的控件添加背景图时&#xff0c;在样式表中加入如下代码&#xff0c;指定某个控件&#xff0c;设置其背景。 类名 # 控件名 { 填充方式&#xff1a;图片路径 } 例如&#xff1a; QWidget#Widget {border-image: url…...

【ROS】话题通信--从理论介绍到模型实现(C++)

1.简单介绍 话题通信是ROS中使用频率最高的一种通信模式&#xff0c;话题通信是基于发布订阅模式的&#xff0c;也即:一个节点发布消息&#xff0c;另一个节点订阅该消息。像雷达、摄像头、GPS… 等等一些传感器数据的采集&#xff0c;也都是使用了话题通信&#xff0c;换言之…...

服务器数据恢复-EqualLogic存储RAID5数据恢复案例

服务器数据恢复环境&#xff1a; 一台DELL EqualLogic存储中有一组由16块SAS硬盘组建的RAID5阵列。存储存放虚拟机文件&#xff0c;采用VMFS文件系统&#xff0c;划分了4个lun。 服务器故障&检测&分析&#xff1a; 存储设备上有两个硬盘指示灯显示黄色&#xff0c;存储…...

qsort函数详解

大家好&#xff0c;我是苏貝&#xff0c;本篇博客带大家了解qsort函数&#xff0c;如果你觉得我写的不错的话&#xff0c;可以给我一个赞&#x1f44d;吗&#xff0c;感谢❤️ 文章目录 一. qsort函数参数详解1.数组首元素地址base2.数组的元素个数num和元素所占内存空间大小w…...

C#学习,委托,事件,泛型,匿名方法

目录 委托 声明委托 实例化委托 委托的多播 委托的用途 事件 通过事件使用委托 声明事件 泛型 泛型的特性 泛型方法 泛型的委托 匿名方法 编写匿名方法的语法 委托 类似于指针&#xff0c;委托是存有对某个方法的引用的一种引用类型变量&#xff0c;引用可以在运…...