Python爬虫学习(十八)Scrapy之Spiders
在Python爬虫学习(十七)Scrapy命令行工具中提到的命令,我想大家应该摸索得差不多了,哈哈,还是挺有趣的吧。
本文就开始聊一聊,Scrapy中的Spiders。
Spider 类定义了如何爬取某个(或某些)网站。包括了爬取的动作(例如:是否跟进链接)以及如何从网页的内容中提取结构化数据(爬取item)。 换句话说,Spider 就是您定义爬取的动作及分析某个网页(或者是有些网页)的地方。
对于spider,爬取循环做着下面的事情:
-
首先生成抓取第一个URL的初始 request,request 下载完成后生成 response ,然后指定对 response 要使用的回调函数。
通过调用
start_requests()
方法(默认情况下)为start_urls
中指定的URL生成初始的Request
以及将parse
方法作为请求的回调函数。 -
在回调函数中,您将解析 Response(网页)并返回带有提取的数据的 dict,
Item
对象,Request
对象或这些对象的可迭代容器。这些请求还将包含回调(可能是相同的),然后由 Scrapy 下载,然后由指定的回调处理它们的响应。 -
在回调函数中,通常使用选择器来解析页面内容(但也可以使用BeautifulSoup,lxml或您喜欢的任何解析器),并使用解析的数据生成 Item。
-
最后,从爬虫返回的 Item 通常将持久存储到数据或写入文件。
如果你看完上述内容是这个状态,
那么,或许我们可以用前面学到的知识解读一下:
在没有用到Scrapy这个框架的时候,我们老是自己写代码去请求网页,获得响应,然后再用正则表达式、BeautifulSoup等工具来提取我们想要的信息,最后,再把提取到的结构化的数据存到文件或则数据库中。这不就分别对应着上述内容嘛,简单吧!
Spider类中包含了一些很重要的方法和属性:
- name
定义此爬虫名称的字符串。爬虫名称是爬虫如何由 Scrapy 定位(和实例化),因此它必须是唯一的。但是,可以生成多个相同的爬虫实例(instance),这没有任何限制。 name是spider最重要的属性,而且是必须的。
- start_urls
URL列表。当没有指定特定 URL 时,爬虫将从从该列表中开始抓取。因此,爬取的第一个页面将是这里列出的某个 URL。后续的 URL 将根据包含在起始 URL 中的数据连续生成。
- parse(response)
当response没有指定回调函数时,这是Scrapy用来处理下载的response的默认方法。parse
方法负责处理response并返回所抓取的数据以及跟进的URL。Spider
对其他的Request的回调函数也有相同的要求。
当然,还有很多其他内容,这就不多说了,感兴趣的话,自己去看看文档。
我们就用这些信息写爬一下电影天堂:
地址为:http://www.ygdy8.net/html/gndy/dyzz/index.html
我们可以用昨天学到的scrapy view
命令尝尝鲜,
可以看到:
原来,请求到的网页是这样的,没了那些花里胡哨的东西啦!那么,就不妨再进一步,审查元素,了解网页结构:
OK,结构已了解,现在已经是老司机的我们对这个应该是轻车熟路咯。
我们的目的是提取到每部电影的下载链接
捋一捋思路,机智的你肯定也想到了,我们需要分成两步:首先是到达每部电影的主页,然后便是提取下载链接。很好,分析的差不多,可以动手写代码了。
# -*- coding: utf-8 -*-
import scrapy
class DianyingSpider(scrapy.Spider):
name = 'dianying'
domain = 'http://www.ygdy8.net'
start_urls = ['http://www.ygdy8.net/html/gndy/dyzz/index.html']
def parse(self, response):
for link in response.css('a.ulink::attr(href)').extract():
# link是相对路径
url = response.urljoin(link) # 拼接成绝对路径
yield scrapy.Request(url, callback=self.parse_movie)
def parse_movie(self, response):
yield {
'name':response.css('div.title_all h1 font::text').extract_first(), # 提取电影标题
'link':response.css('td a::attr(href)').extract_first() # 提取下载地址
}
代码写完,我们可以直接运行它,使用scrapy runspider
命令即可。
结果如下:
当然,你也可以把它保存到文件中。
可这只是爬了一页的内容,最新的电影可有一百多页,怎么弄?哈哈哈,其实只要把parse
函数小小的改动一下即可,要不你想想呗。
对了,之前还写过了另一个没用框架的版本,这里可以找到:https://github.com/viljw/PythonSpider
最后,我也把部分内容放到了博客中:www.viljw1557.cn,码字不易,打发点可好(羞)!
以上。