Python爬虫之Scrapy框架系列(5)——项目实战【某瓣Top250电影所有信息的txt文本存储】

news/2024/11/29 8:35:29/

上篇文章已经成功解析提取到豆瓣Top250电影想要的所有数据。下一步就是将其交给管道进行存储。

目录:

  • 1. 编写items.py文件(定义结构化数据字段)
  • 2. 爬虫文件里将数据一一对应字段名:
  • 3. 将数据返回给管道:
  • 4. 编写pipelines.py文件进行数据存储:
  • 5. 某瓣Top250首页25个电影更多信息已经抓取完毕,效果如下:
  • 拓展:上面实现了某瓣首页25个电影信息的爬取,那么如何爬取更多页呢?
    • 1. 首先,分析如何爬取两页:
    • 2. 获取两页的信息都可以实现了,那么获取更多(比如:10页),只要找到每页url的规律,给个循环就OK啦!
      • 2.1 剖析每页url可知:每加一页,对应的start参数的值就会加25。
      • 2.2 在爬虫文件每个请求执行完成功之后,利用格式化输出.format()方法向引擎发送每页的请求即可!
      • 2.3 运行会发现很棒哦!

1. 编写items.py文件(定义结构化数据字段)

  • 首先,引擎交给spider(爬虫文件)的信息已经被爬虫解析并提取正确的信息,下一步是spider(爬虫文件)将数据再次交给引擎,而能否成功交给引擎,这就取决于items.py文件(定义结构化数据字段)是否有对应的字段名等待插入数据:
# -*- coding: utf-8 -*-# Define here the models for your scraped items
#
# See documentation in:
# https://docs.scrapy.org/en/latest/topics/items.htmlimport scrapyclass DoubanItem(scrapy.Item):# define the fields for your item here like:# name = scrapy.Field()#需要定义字段名  就像数据库那样,有字段名,才能插入数据(即存储数据)# films_name=scrapy.Field()   #定义字段名film_name=scrapy.Field()star_name=scrapy.Field()score=scrapy.Field()

items.py文件中已经创建好字段名等待插入数据了,下一步就是:

2. 爬虫文件里将数据一一对应字段名:

在刚刚的爬虫文件的循环下写入即可:

            # 使用字段名  收集数据item=item=DoubanItem()item["film_name"]=film_nameitem["star_name"]=star_nameitem["score"]=score

注意:在settings.py文件中开启管道并关闭robots协议!

3. 将数据返回给管道:

  • 引擎将数据交给管道的中间的item这一步已经成功走过去了,下一步就是如何将数据返回给管道:在这里要注意一个问题:惯性思维会让我们在这个函数里定性的使用return返回item,但是,切记return返回的是parse这个方法(会造成只会传给管道第一个电影信息的bug)。而我们所需要的是返回每次解析后的数据,so我们想到了生成器,使用yield返回,这样每搞一次数据出来,生成器就给一次数据,循环如此,非常nice!!!

我们只需在爬虫文件的循环最底下加入即可:

			             # 形式:{"film_name":"肖申克的救赎","star_name":"蒂姆","score":"9.7"}yield item

4. 编写pipelines.py文件进行数据存储:

  • 引擎已经将数据交给管道(即pipelines.py管道文件),但是,我们这是25个请求,就会进行25次处理,也就意味着,引擎会交给管道25次数据,那么我们在管道里进行储存数据的时候,按往常来说就要来来回回打开关闭文件,进行数据的写入。这样显然不好。所以:在此引入管道文件里的两种牛批的方法:
#爬虫文件开启,此方法就开启
def open_spider(self,spider):pass#爬虫文件关闭,此方法就开启
def close_spider(self,spider):pass
  • 这就非常合我们的需求,结合这两个方法,我们只需要在open_spider()方法里加入打开文件操作;在close_spider()方法里加入关闭文件操作即可,这样就避免了文件的来来回回的开启关闭,好处不言而喻。

  • 来看看升级版的pipelines.py文件(管道文件):

# -*- coding: utf-8 -*-# 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.htmlimport json
class DoubanPipeline(object):def open_spider(self,spider):   #爬虫文件开启,此方法就开启self.f=open("films.txt","w",encoding="utf-8")       #打开文件def process_item(self, item, spider):        #会来25次,就会调用25次这个方法  如果按常规来写,文件就会被操作25次打开关闭#为了能写进text  json.dumps将dic数据转换为strjson_str=json.dumps(dict(item),ensure_ascii=False)+"\n"self.f.write(json_str)                              #爬虫文件开启时,文件就已经打开,在此直接写入数据即可!return itemdef close_spider(self,spider):  #爬虫文件关闭,此方法就开启self.f.close()                                      #爬虫文件关闭时,引擎已经将全部数据交给管道,关闭文件

5. 某瓣Top250首页25个电影更多信息已经抓取完毕,效果如下:

在这里插入图片描述

拓展:上面实现了某瓣首页25个电影信息的爬取,那么如何爬取更多页呢?

1. 首先,分析如何爬取两页:

  • 注意:Scrapy框架运行的流程,任何模块发出的请求都是给到引擎的,所以,我们只需要在爬虫文件中的第一次请求的数据提交给管道之后,使用yield发起一个请求(某瓣电影Top250第二页的url),那么,这个请求就会自动的交给了引擎,就开启了新一轮的自动化走流程,但是,在最后引擎需要将数据再送给spider爬虫文件让其解析并获取真正想要存储到管道的数据,所以就需要callback回调自身这个parse函数。
    逻辑如下图:

在这里插入图片描述

2. 获取两页的信息都可以实现了,那么获取更多(比如:10页),只要找到每页url的规律,给个循环就OK啦!

2.1 剖析每页url可知:每加一页,对应的start参数的值就会加25。

'''
各页url规律剖析:
https://xxx.com/top250
https://xxx.com/top250?start=0&filter=
https://xxx.com/top250?start=25&filter=
https://xxx.com/top250?start=50&filter=
'''

2.2 在爬虫文件每个请求执行完成功之后,利用格式化输出.format()方法向引擎发送每页的请求即可!

  • (每完成一个请求的全部流程,page_num就会加一,25倍的page_num就对应了每页url的start参数的值;注意:我们会发现总共就10页有信息,多了就没得信息了,所以设置了if判断,如果url获取的信息为空,就返回空,引擎接到空的请求,就会自动关闭)
# -*- coding: utf-8 -*-
import scrapy
import refrom ..items import DoubanItem  # 因为我们要使用包含定义字段名的类,所以需要导入class DbSpider(scrapy.Spider):name = 'db'allowed_domains = ['xxx.com']start_urls = ['xxx/top250']page_num = 0  # 类变量def parse(self, response):  # 解析和提取数据# 获取电影信息数据# films_name=response.xpath('//div[@class="info"]/div/a/span[1]/text()').extract()node_list = response.xpath('//div[@class="info"]')  # 25个if node_list:  # 此判断的作用:在爬取到10页之后,就获取不到了!判断每次是否获取到数据,如果没有则返回空(即停止了)for node in node_list:# 电影名字film_name = node.xpath('./div/a/span[1]/text()').extract()[0]# 主演   拿标签内容,再正则表达式匹配con_star_name = node.xpath('./div/p[1]/text()').extract()[0]if "主" in con_star_name:star_name = re.findall("主演?:? ?(.*)", con_star_name)[0]else:star_name = "空"# 评分score = node_list.xpath('./div/div/span[@property="v:average"]/text()').extract()[0]# 使用字段名  收集数据item = DoubanItem()item["film_name"] = film_nameitem["star_name"] = star_nameitem["score"] = score# 形式:{"film_name":"肖申克的救赎","star_name":"蒂姆","score":"9.7"}yield item  # 不使用return的原因是,return返回的是parse这个方法(会造成只会传给管道第一个电影信息的bug)。而我们所需要的是返回每次解析后的数据self.page_num += 1print("page_num:", self.page_num)page_url = "xxx/top250?start={}&filter=".format(self.page_num * 25)yield scrapy.Request(page_url, callback=self.parse)# 注意:各个模块的请求都会交给引擎,然后经过引擎的一系列操作;但是,切记:引擎最后要把得到的数据再来给到# spider爬虫文件让它解析并获取到真正想要的数据(callback=self.parse)这样就可以再给到自身。else:return'''
各页url规律剖析:
https://xxx.com/top250
https://xxx.com/top250?start=0&filter=
https://xxx.com/top250?start=25&filter=
https://xxx.com/top250?start=50&filter=
''''''
网页源码剖析:
<div class="info"><div class="hd"><a href="https://xxx.com/subject/1292052/" class=""><span class="title">肖申克的救赎</span><span class="title">&nbsp;/&nbsp;The Shawshank Redemption</span><span class="other">&nbsp;/&nbsp;月黑高飞(港)  /  刺激1995(台)</span></a><span class="playable">[可播放]</span></div><div class="bd"><p class="">导演: 弗兰克·德拉邦特 Frank Darabont&nbsp;&nbsp;&nbsp;主演: 蒂姆·罗宾斯 Tim Robbins /...<br>1994&nbsp;/&nbsp;美国&nbsp;/&nbsp;犯罪 剧情</p><div class="star"><span class="rating5-t"></span><span class="rating_num" property="v:average">9.7</span><span property="v:best" content="10.0"></span><span>1983356人评价</span></div><p class="quote"><span class="inq">希望让人自由。</span></p></div>
</div>
'''

切记:
要在settings.py文件中开启延时。
不然:网站很容易检测出来,后果严重!!!

在这里插入图片描述

2.3 运行会发现很棒哦!

在这里插入图片描述


http://www.ppmy.cn/news/18966.html

相关文章

acwing基础课——快速幂

由数据范围反推算法复杂度以及算法内容 - AcWing 常用代码模板4——数学知识 - AcWing 基本思想&#xff1a; 求一个数的n次时&#xff0c;我们的时间复杂度为O(n),当n特别大时&#xff0c;效率会很低可能超时&#xff0c;此时我们就需要运用到快速幂&#xff0c;将我们的时间…

JavaScript 输出

JavaScript 输出 很遗憾&#xff0c;在javascript中我们找不到输出和打印的函数。 但是我们可以使用其他的方式来显示需要的数据: 我们可以使用 console.log() 在浏览器控制台上面输出内容我们可以使用innerHTML 把内容写入到 HTML 元素。我们可以使用 document.write() 方法…

【进击的算法】基础算法——动态规划

&#x1f37f;本文主题&#xff1a;动态规划 &#x1f388;更多算法&#xff1a;回溯算法 &#x1f495;我的主页&#xff1a;蓝色学者的主页 文章目录一、前言二、概念2.1概念一&#xff1a;状态转移2.2概念二&#xff1a;Dp数组三、例题3.1斐波那契数列3.1.1题目描述3.1.2状态…

客快物流大数据项目(一百零七):物流信息查询服务接口开发解决方案

文章目录 物流信息查询服务接口开发解决方案 一、业务需求 二、系统架构演变 1、​​​​​​​集中式架构 2、​​​​​​​​​​​​​​垂直拆分 3、分布式服务 ​​​​​​​4、面向服务架构&#xff08;SOA&#xff09; 5、微服务架构 ​​​​​​​三、技术…

Tomcat启动的两个问题

文章目录小结问题及解决Address already in use: JVM_BindNo buffer space available &#xff0c;tomcat启动报错参考小结 Tomcat服务碰到两个常见的问题&#xff0c;进行了解决。 问题及解决 Address already in use: JVM_Bind 端口被占用的问题经常会碰到&#xff0c;最…

Allegro如何添加平衡铜操作指导

Allegro如何添加平衡铜操作指导 PCB在加工的时候,工厂会添加平衡铜,Allegro支持自动加上平衡铜,如下图 具体操作如下 选择Manufacture点击Thieving

官方正品 | Ultralytics YOLOv8算法来啦(尖端SOTA模型)

&#x1f680;&#x1f680;&#x1f680;卷王之王 | Ultralytics YOLOv8 算法来啦&#xff01;&#xff01;✨✨✨ 一、前言简介 &#x1f384;&#x1f388; &#x1f4da; 代码地址&#xff1a;卷王之王 | YOLOv8代码下载地址 &#x1f4da; 详细文档&#xff1a;https://…

day24-网络编程02

1.NIO 1.1 NIO通道客户端【应用】 客户端实现步骤 打开通道指定IP和端口号写出数据释放资源 示例代码 public class NIOClient {public static void main(String[] args) throws IOException {//1.打开通道SocketChannel socketChannel SocketChannel.open();//2.指定IP和端…