热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Scrapy爬取豆瓣Top250电影和灌篮高手漫画全集

爬取豆瓣Top250电影为了寻找练手的项目,搜索了无数文档,自己总结了一套关于scrapy写spider的“标准”模板,稍后奉上。在这无数文档中,不知道是出于什么原因,要我说至少有
爬取豆瓣Top250电影

为了寻找练手的项目,搜索了无数文档,自己总结了一套关于scrapy写spider的“标准”模板,稍后奉上。在这无数文档中,不知道是出于什么原因,要我说至少有一半提到了爬取豆瓣top250电影,那我也只能先爬为敬了。

如果你看懂了我上一篇文章,那么爬豆瓣就很简单了,废话不多说,我直接上代码:

import scrapy
class doubantop250(scrapy.Spider):
name = "doubantop250"
headler = {
'User-Agent': 'Mozilla/5.0 (Linux; Android 5.1.1; Nexus 6 Build/LYZ28E) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Mobile Safari/537.36',
#'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8'
}
start_urls = [
'https://movie.douban.com/top250'
]
def start_requests(self):
for url in self.start_urls:
yield scrapy.Request(url=url, callback=self.parse, headers=self.headler)
def parse(self, response):
for lists in response.css('ol.grid_view li div.item'):
yield {
"名次": lists.css('div.pic em::text').extract(),
"信息": lists.css('div.info div.bd p::text').extract(),
"电影名": lists.css('div.info div.hd a span.title::text').extract(),
"评分":lists.css('div.info div.bd div.star span.rating_num::text').extract(),
"引言": lists.css('div.info div.bd p.quote span.inq::text').extract()
}
next_page = response.css('div.paginator span.next a::attr(href)').extract_first()
if next_page is not None:
next_page = response.urljoin(next_page)
yield scrapy.Request(next_page, callback=self.parse, headers=self.headler)

同样的css表达式scrapy shell抓不到东西?

这是因为shell里生成的request默认是没有带User-agent字段的,这个字段在反爬技术中很重要,怎么解决呢?也很简单,给它一个User-agent呀。在shell里输入:

>>> header = {
... 'User-Agent': 'Mozilla/5.0 (Linux; Android 5.1.1; Nexus 6 Build/LYZ28E) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Mobile Safari/537.36',
... }
>>> from scrapy import Request
>>> req = scrapy.Request(url='https://movie.douban.com/top250', headers=header)
>>> fetch(req)
爬取灌篮高手漫画全集

这是我发现的另一个觉得很有帮助的例子:Python3网络爬虫(十二):初识Scrapy之再续火影情缘,作者爬取了一个盗版漫画网站上的火影漫画。我觉得这篇文章最可取之处是教我们系统化的使用Scrapy编写爬虫,我从中学到了很多东西。另外我个人并没有看过火影,我爬灌篮高手好了。

作者的思路也很值得借鉴。

分析并提取所有可能用到的URL

这里我就直接列出来了,和作者写的可能有点不一样,但大同小异。想看具体分析过程的可以参考作者的原文档。之前我以为这一步是最难的,其实现在看来这一步其实是最简单的。

# 章节的名字
response.xpath("//dl/dd/a[1]/text()").extract()
# 章节的链接
response.xpath("//dl/dd/a[1]/@href").extract()
# 每张的总页数
response.xpath("//tr/td/text()").re("共(\d+)页")[0]
# script脚本内容
response.xpath('//script/text()').extract()

关于代码

代码我就不贴了,原作者在Github上传了完整的源代码,这里我讲一下我对这部分代码的理解。

逻辑

先说下这个爬虫的逻辑, 整个爬取过程中涉及到的URL一共有三种,第一种是每一章的标题和链接,第二种是每一章节中每张图片的链接,作者把每一章的图片分成了两部分:第一张图片和剩下所有的图片,然后分别写了三个parse方法来处理。

在scrapy的sipders模块里,你只需要用yield不断的抛出request或item,其中每个request会根据其包含的url和callback函数再次进入spider的某个处理方法里进行处理;item则会被pipelines.py里的pipeline处理。(想一想前面文章里的那张scrapy机构图)。这里提一点,spider抛出的item会被所有的pipeline轮流处理一变,处理的顺序是根据settings.py里的ITEM_PIPELINES冒号后面的数字决定,值越小优先级越高。Item的格式在items.py里定义。

细节一点?

comic_spider.py

在parse1中,新建了item对象,每个Item包含了章节名、章节链接、图片链接以及图片保存的路径,但是在parse1中其实只用到了章节名和章节链接两项。这里我们已经知道,章节链接和漫画的主页面的链接的域名是不一样的,因此我们在parse1的最后抛出一个请求,它对应了章节链接以及一个代表item的meta值,同时回调parse2来处理这一系列的请求。

在parse2中,我们通过从request中获取meta值的方式来获取要处理的item对象。在这个方法中,我们要分析出每个章节一共有多少张图片以及第一张图片的URL是什么。这里面涉及到一系列的正则和字符串处理操作,就不细说了,如果看不懂代码,建议在shell模式下把每一步的结果都打印出来看看,可以帮助理解。我们把第一张图片的URL存入item中,然后在最后抛出包含这一章所有图片的URL的请求,比如说如果这一章有122张图片,就会抛出121个请求,当然每个请求都包含了一个代表item的meta值,这些请求都会回调parse3方法。

那么第一张图片是怎么处理呢?很简单直接yield带有第一张图片url的item对象即可,后面会说pipeline是怎么处理这些item的。这里还有一点要注意,虽然每张图片所在的网页是按照1,2,3,4,5…进行编号的,但是图片本身的img_url是由script生成的,它需要你在每个网页里抓取,并存在item[‘img_url’]里。

在parse3中,因为parse2中抛出的每一条请求都对应了一个网页,也就是对应了一张图片,我们只需要将每张网页里的图片的url抓取出来即可,接着我们把这个url存入item中,并抛出item。

pipelines.py

还记得我们在comic_spider.py中抛出的item吗?这里会处理,在这个爬虫中,我们只会用到一个pipeline。首先我觉得需要对所有被抛出的item有个概念,这么多item是分类的?以第一章为例,橄榄高手第一章有122张图片,也就是122个item,其中每个item都带有章节名,章节链接和需要保存的路径(每章第一张图片的item由parse2抛出,其余的由parse3抛出)。那么在pipeline中,我们做的就是将每个item对应的内容保存到本地,假设我们需要保存的路径是d:/,那么最后我们要写入的地址就是d:/ + 章节名 + 图片名字.jpg。这里有一点取巧的地方就是我们用图片所在网页里那个数字作为每张图片的名字,因为它正好对应了图片的顺序,所以在图片都下载下来后顺序不会乱。

settings.py

scrapy1.5的settings.py已经有很详细的注释了,当然官方文档有更详细的注释:Settings。

结果

最后自然是运行这个爬虫程序,说实话,看着程序在运行同时文件夹里的内容逐渐增加时心里还是有成就感的,即使这个程序不是我原创的。从文件夹中的内容增加的过程可以看出,scrapy的框架采用的是异步策略(为什么?)。今天还找到一个介绍scrapy的视频,容我观摩一番,再写一篇详细点的关于scrapy的文章。


推荐阅读
  • 技术分享:从动态网站提取站点密钥的解决方案
    本文探讨了如何从动态网站中提取站点密钥,特别是针对验证码(reCAPTCHA)的处理方法。通过结合Selenium和requests库,提供了详细的代码示例和优化建议。 ... [详细]
  • 本文详细介绍了如何在Linux系统上安装和配置Smokeping,以实现对网络链路质量的实时监控。通过详细的步骤和必要的依赖包安装,确保用户能够顺利完成部署并优化其网络性能监控。 ... [详细]
  • 1.如何在运行状态查看源代码?查看函数的源代码,我们通常会使用IDE来完成。比如在PyCharm中,你可以Ctrl+鼠标点击进入函数的源代码。那如果没有IDE呢?当我们想使用一个函 ... [详细]
  • 本文将介绍如何编写一些有趣的VBScript脚本,这些脚本可以在朋友之间进行无害的恶作剧。通过简单的代码示例,帮助您了解VBScript的基本语法和功能。 ... [详细]
  • 本文介绍了如何使用 Spring Boot DevTools 实现应用程序在开发过程中自动重启。这一特性显著提高了开发效率,特别是在集成开发环境(IDE)中工作时,能够提供快速的反馈循环。默认情况下,DevTools 会监控类路径上的文件变化,并根据需要触发应用重启。 ... [详细]
  • 本文介绍了在安装或运行 Python 项目时遇到的 'ModuleNotFoundError: No module named setuptools_rust' 错误,并提供了解决方案。 ... [详细]
  • 本文详细介绍了 Dockerfile 的编写方法及其在网络配置中的应用,涵盖基础指令、镜像构建与发布流程,并深入探讨了 Docker 的默认网络、容器互联及自定义网络的实现。 ... [详细]
  • c# – UWP:BrightnessOverride StartOverride逻辑 ... [详细]
  • 前言--页数多了以后需要指定到某一页(只做了功能,样式没有细调)html ... [详细]
  • 本文详细介绍了Akka中的BackoffSupervisor机制,探讨其在处理持久化失败和Actor重启时的应用。通过具体示例,展示了如何配置和使用BackoffSupervisor以实现更细粒度的异常处理。 ... [详细]
  • Python自动化处理:从Word文档提取内容并生成带水印的PDF
    本文介绍如何利用Python实现从特定网站下载Word文档,去除水印并添加自定义水印,最终将文档转换为PDF格式。该方法适用于批量处理和自动化需求。 ... [详细]
  • 将Web服务部署到Tomcat
    本文介绍了如何在JDeveloper 12c中创建一个Java项目,并将其打包为Web服务,然后部署到Tomcat服务器。内容涵盖从项目创建、编写Web服务代码、配置相关XML文件到最终的本地部署和验证。 ... [详细]
  • XNA 3.0 游戏编程:从 XML 文件加载数据
    本文介绍如何在 XNA 3.0 游戏项目中从 XML 文件加载数据。我们将探讨如何将 XML 数据序列化为二进制文件,并通过内容管道加载到游戏中。此外,还会涉及自定义类型读取器和写入器的实现。 ... [详细]
  • Android LED 数字字体的应用与实现
    本文介绍了一种适用于 Android 应用的 LED 数字字体(digital font),并详细描述了其在 UI 设计中的应用场景及其实现方法。这种字体常用于视频、广告倒计时等场景,能够增强视觉效果。 ... [详细]
  • ImmutableX Poised to Pioneer Web3 Gaming Revolution
    ImmutableX is set to spearhead the evolution of Web3 gaming, with its innovative technologies and strategic partnerships driving significant advancements in the industry. ... [详细]
author-avatar
淡月如水夜宿雨
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有