scrapy分页抓取网页(什么是Items呢?官方文档Items定义如下:Items)
优采云 发布时间: 2022-02-05 22:14scrapy分页抓取网页(什么是Items呢?官方文档Items定义如下:Items)
什么是物品?官方文档Items定义如下:
项目
爬取的主要目标是从非结构化数据源中提取结构化数据,例如网页。Scrapy spider 可以使用 python 的 dict 返回提取的数据。dict虽然使用起来非常方便和熟悉,但缺乏结构,容易打错字段名或返回不一致的数据,尤其是在项目中有多个爬虫的*敏*感*词*情况下。
为了定义通用的输出数据,Scrapy 提供了 Item 类。Item 对象是一个简单的容器,用于保存爬网数据。它提供了类似字典的 API 和用于声明可用字段的简单语法。
许多 Scrapy 组件使用 Item 提供的额外信息:exporter 根据 Item 声明的字段导出数据,序列化可以通过 Item 字段的元数据定义,trackref 跟踪 Item 实例以帮助查找内存泄漏(请参阅 Debugging with trackref 内存泄漏)等。
使用简单的类定义语法和 Field 对象来声明项目。我们打开scrapyspider目录下的items.py文件,编写如下代码声明Item:
import scrapy
class DoubanMovieItem(scrapy.Item):
# 排名
ranking = scrapy.Field()
# 电影名称
movie_name = scrapy.Field()
# 评分
score = scrapy.Field()
# 评论人数
score_num = scrapy.Field()
履带式
在scrapyspider/spiders目录下创建douban_spider.py文件,编写初步代码:
from scrapy.spiders import Spider
from scrapyspider.items import DoubanMovieItem
class DoubanMovieTop250Spider(Spider):
name = 'douban_movie_top250'
start_urls = ['https://movie.douban.com/top250']
def parse(self, response):
item = DoubanMovieItem()
这是一个基本的scrapy蜘蛛模型,首先我们需要在Scrapy.spiders中导入Spider类,以及我们刚刚在scrapyspider.items中定义的豆瓣电影项目。然后创建我们自己的爬虫类 DoubanMovieTop250Spider 并继承 Spider 类。scrapy.spiders中有很多不同的爬虫类供我们继承。一般来说,Spider类可以满足要求。(其他爬虫的使用请参考官方文档)。
蜘蛛
类scrapy.spider.Spider
蜘蛛是最简单的蜘蛛。每个其他蜘蛛都必须从这个类继承(包括 Scrapy 附带的其他蜘蛛和您自己编写的蜘蛛)。Spider 不提供任何特殊功能。它只是请求给定的 start_urls/start_requests 并根据返回的结果(结果响应)调用蜘蛛的 parse 方法。
name 定义蜘蛛名称的字符串。蜘蛛的名字定义了 Scrapy 如何定位(和初始化)蜘蛛,所以它必须是唯一的。但是,您可以在没有任何限制的情况下生成同一个蜘蛛的多个实例。name是spider最重要的属性,是必须的。
如果蜘蛛爬取单个 网站(单个域),通常的做法是在 网站(域)之后命名蜘蛛(带或不带后缀)。例如,如果蜘蛛正在爬行,蜘蛛通常会被命名为 mywebsite。
allowed_domains 是可选的。收录允许蜘蛛抓取的域列表。开启 OffsiteMiddleware 后,域名不在列表中的 URL 将不会被跟进。
start_urls URL 列表。当没有指定具体的 URL 时,蜘蛛会从这个列表开始爬取。因此,要获取的第一个页面的 URL 将是列表之一。后续 URL 将从获取的数据中提取。
start_requests() 这个方法必须返回一个可迭代的。该对象收录蜘蛛用来抓取的第一个请求。
当蜘蛛开始爬取并且没有指定 URL 时调用该方法。当指定 URL 时,将调用 make_requests_from_url() 来创建 Request 对象。此方法只会被 Scrapy 调用一次,因此您可以将其实现为*敏*感*词*。
该方法的默认实现是使用 start_urls 的 url 来生成 Request。
如果要修改原来爬取了一个网站的Request对象,可以重写这个方法。例如,如果你需要在启动时 POST 到某个 网站,你可以这样写:
def start_requests(self):
return [scrapy.FormRequest("http://www.example.com/login",
formdata={'user': 'john', 'pass': 'secret'},
callback=self.logged_in)]
def logged_in(self, response):
# here you would extract links to follow and return Requests for
# each of them, with another callback
pass
make_requests_from_url(url) 该方法接受一个 URL 并返回一个请求对象进行爬取。该方法在初始化请求时被 start_requests() 调用,也用于将 url 转换为请求。
如果默认不覆盖,在该方法返回的Request对象中,parse()作为回调函数,dont_filter参数也设置为on。(详情请参阅请求)。
parse(response) 当response没有指定回调函数时,这个方法是Scrapy处理下载的response的默认方法。
parse 处理响应并返回处理后的数据和/或要遵循的 URL。Spider 对其他 Request 回调函数有相同的要求。
此方法和其他 Request 回调函数必须返回收录 Request 和/或 Item 的可迭代对象。
参数:响应(Response)——用于分析的响应
log(message[, level, component]) 使用 scrapy.log.msg() 方法记录(记录)消息。日志中自动携带蜘蛛的名称属性。有关更多数据,请参阅日志记录。
closed(reason) 这个函数在蜘蛛关闭时被调用。这个方法提供了一个快捷方式,而不是调用 signals.connect() 来*敏*感*词* spider_close 信号。
提取网页信息
我们使用 xpath 语法来提取我们需要的信息。不熟悉xpath语法的同学可以在W3School网站中学习,很快就能上手。首先,我们在chrome浏览器中进入豆瓣电影TOP250页面,按F12打开开发者工具。
点击工具栏左上角类似鼠标的符号图标或Ctrl+Shift+c点击页面中我们想要的元素,在工具栏中查看其在网页HTML源代码中的位置。一般抓的时候,先抓大再抓小的原则。通过观察,我们可以看到该页面上所有电影的信息都位于一个类属性为grid_view的ol标签内的一个li标签中。
1
肖申克的救赎
/ The Shawshank Redemption
/ 月黑高飞(港) / 刺激1995(台)
[可播放]
导演: 弗兰克·德拉邦特 Frank Darabont 主演: 蒂姆·罗宾斯 Tim Robbins /...
1994 / 美国 / *敏*感*词* 剧情
9.6
766719人评价
希望让人自由。
...
...
...
因此,我们按照上述原则爬取所需信息
from scrapy.spiders import Spider
from scrapyspider.items import DoubanMovieItem
class DoubanMovieTop250Spider(Spider):
name = 'douban_movie_top250'
start_urls = ['https://movie.douban.com/top250']
def parse(self, response):
item = DoubanMovieItem()
movies = response.xpath('//ol[@class="grid_view"]/li')
for movie in movies:
item['ranking'] = movie.xpath(
'.//div[@class="pic"]/em/text()').extract()[0]
item['movie_name'] = movie.xpath(
'.//div[@class="hd"]/a/span[1]/text()').extract()[0]
item['score'] = movie.xpath(
'.//div[@class="star"]/span[@class="rating_num"]/text()'
).extract()[0]
item['score_num'] = movie.xpath(
'.//div[@class="star"]/span/text()').re(ur'(\d+)人评价')[0]
yield item
Scrapy提取的页面信息内容详细请参考官方文档的相应章节。
运行爬虫
在项目文件夹中打开 cmd 并运行以下命令:
scrapy crawl douban_movie_top250 -o douban.csv
注意这里的douban_movie_top250是我们刚刚写的爬虫的名字,-o douban.csv是scrapy提供的一个快捷方式,可以将item输出为csv格式
尝试运行爬虫,为什么没有输出?!!!
在你所有的努力之后你会失败吗?!!!别着急,我们看下一个控制台输出的信息。原来是403错误。这是因为豆瓣给爬虫设置了一个很小的阈值,我们只需要在发送请求时更改请求头user-agent即可。
更改后的代码在某些地方感觉不同吗?为什么 start_urls 不见了?start_requests 函数有什么作用?还记得刚才对 Spider 类的介绍吗?让我们回过头来回顾一下上面对 start_urls 和 start_requests 函数的介绍。简单来说,通过使用start_requests函数,我们有了更多的权限来处理初始URL,比如这次在初始URL中加入了请求头user_agent。
再次运行爬虫,我们想要的信息全部下载到douban.scv文件夹中。直接用WPS打开查看信息。
自动翻页
不要太激动,没发现问题吗?在这种情况下,我们只能抓取到当前页面的 25 部电影的内容。我怎样才能和其他人一起爬下来?实现自动翻页一般有两种方式:
在页面中找到下一页的地址;根据 URL 的变化规律,自己构建所有的页面地址。
一般情况下我们使用第一种方式,第二种方式适用于页面的下一页地址是JS加载的情况。今天我们只讲第一种方法。先用Chrome浏览器的开发者工具找到下一页的地址
然后在解析页面的时候,得到下一页的地址,把地址交给调度器(Scheduler)
from scrapy import Request
from scrapy.spiders import Spider
from scrapyspider.items import DoubanMovieItem
class DoubanMovieTop250Spider(Spider):
name = 'douban_movie_top250'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36',
}
def start_requests(self):
url = 'https://movie.douban.com/top250'
yield Request(url, headers=self.headers)
def parse(self, response):
item = DoubanMovieItem()
movies = response.xpath('//ol[@class="grid_view"]/li')
for movie in movies:
item['ranking'] = movie.xpath(
'.//div[@class="pic"]/em/text()').extract()[0]
item['movie_name'] = movie.xpath(
'.//div[@class="hd"]/a/span[1]/text()').extract()[0]
item['score'] = movie.xpath(
'.//div[@class="star"]/span[@class="rating_num"]/text()'
).extract()[0]
item['score_num'] = movie.xpath(
'.//div[@class="star"]/span/text()').re(ur'(\d+)人评价')[0]
yield item
next_url = response.xpath('//span[@class="next"]/a/@href').extract()
if next_url:
next_url = 'https://movie.douban.com/top250' + next_url[0]
yield Request(next_url, headers=self.headers)
最后再次运行爬虫,打开douban.csv。有没有发现已经获取了所有的电影信息,其中250个不超过1个,不小于250个?
最后,使用 WPS 的过滤功能,您可以过滤任何符合您要求的视频。(ps:外国和尚不总是会念经,记得用WPS打开这个CVS文件,用EXCEL打开会因为中文导致显示异常。)
结尾
自从写了这篇 Scrapy 爬虫框架教程后,我越来越觉得把学到的东西导出并没有想象中的那么简单。很多时候,在写了几个小时的教程之后,我发现我仍然无法完美地表达我想要表达的东西。如果有什么不对的地方,请纠正我。有一系列的听证会,并且有艺术行业的专业。我们都互相学习:)
源码地址:Wooden-Robot/scrapy-tutorial