Python3.X网络爬虫学习(五)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Apple_hzc/article/details/82526285

利用Scrapy框架对豆瓣电影排行榜相关数据进行爬取

从上一节中我们知道了scrapy框架和shell指令的测试功能,以及scrapy项目的文件构成。今天利用框架写一个简单的爬虫,将豆瓣电影上的排名、电影名、评分和评价人数获取下来,并保存在表格文件中。

一、Items的编写

使用Scrapy中的Item对象可以保存爬到的数据,相当于存储爬取到的数据的容器。一般来说,网页中的信息基本上都是非结构化信息,我们需要从中提取出我们关注的结构化信息,这样更利于我们对数据的管理,此时,我们可以将提取到的结构化数据存储到Item对象中。

在要爬取的目标网页中,我们需要知道四个参数,分别是排名、名称、评分和评论人数,那么在items.py文件中,就需要对结构化信息进行定义,定义结构化数据信息的格式如下:

结构化数据名 = scrapy.Field()

所以,可以将默认的items.py文件修改如下:

class TestdemoItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    movie_rank = scrapy.Field()
    movie_name = scrapy.Field()
    movie_score = scrapy.Field()
    movie_comment = scrapy.Field()
t = TestdemoItem(movie_rank="1",movie_name="肖申克的救赎",movie_score="9.4",movie_comment="10000")
print(t)

我们定义了一系列结构化数据:movie_rank、movie_name、movie_score和movie_comment。在存储具体数据的时候,只需要实例化该类即可,比如上面第8行代码就将该类实例化的对象赋值给了t,然后输出了这个对象,如下所示:

可以发现,对应的数据会以字典的形式存储,原数据项名会转变为字典中的字段名,原数据项对应的值会转变为字典中相应字段名对应的值。


二、Spider的编写

在一个爬虫项目中,爬虫文件是一个极其重要的部分,爬虫所进行的爬取动作以及数据提取等操作,都是在该文件中进行定义和编写的,通过爬虫文件,可以定义如何对网站进行相应的爬取。

import scrapy
from TestDemo.items import TestdemoItem
class TestDemo(scrapy.Spider):
    name = "douban"
    start_urls = ["https://movie.douban.com/"]
    
    def parse(self, response):
        pass

这是一个基本的scrapy框架下spider的model,导入了scrapy和刚刚写好的items.py文件下的TestdemoItem。接着创建我们自己的爬虫类douban(name也就是爬虫的名字),并继承Spider类,scrapy.spiders中有很多不同的爬虫类可供我们继承,一般情况下使用Spider类就可以满足要求。

class scrapy.spider.Spider

Spider是最简单的spider。每个其他的spider必须继承自该类(包括Scrapy自带的其他spider以及自己编写的spider)。Spider仅仅请求给定的 start_urls/start_requests ,并根据返回的结果(resulting responses)调用spider的 parse 方法。

扫描二维码关注公众号,回复: 3183171 查看本文章

allowed_domains:可选,代表的是允许爬行的域名。当OffsiteMiddleware启用时,域名不在列表中的URL不会被跟进。

start_urls:代表的是爬行的起始地址,如果没有特别指定爬取的URL网址,则会从该属性中定义的网址开始进行爬行。我们也可以定义多个起始网址,网址与网址之间通过逗号隔开。

parse方法:处理Scrapy爬虫爬行到的网页响应(response)的默认方法,通过该方法,可以对响应进行处理并返回处理后的数据,同时该方法也负责链接的跟进。

start_requests() :该方法必须返回一个可迭代对象(iterable)。该对象包含了spider用于爬取的第一个Request。当重写该方法时,不管start_urls是否给出,都会在该方法中重新调用make_requests_from_url() 生成具体请求,并通过yield返回。该方法仅仅会被Scrapy调用一次,因此可以将其实现为生成器。

该方法的默认实现是使用 start_urls 的url生成Request。

make_requests_from_url(url):该方法接受一个URL并返回用于爬取的Request对象。该方法在初始化request时被 start_requests() 调用,也被用于转化url为request。

比如:

class MySpider(scrapy.Spider):
    name = "spider"
    urls = ("网址1",
            "网址2",
            "网址3",
           )

    #重写start_requests()方法
    def start_request(self):
        for url in self.urls:
            #调用默认make_requests_from_url()方法生成具体请求并通过yield返回
            yield self.make_requests_from_url(url)

    def parse(self,response):
        pass

提取网页信息

通过源代码可以看出,每一部影片信息都位于一个class属性为grid_view的ol标签内的li标签内

因此我们根据以上原则对所需信息进行抓取:

class TestDemo(scrapy.Spider):

    name = "douban"
    allowed_domains = ['movie.douban.com']
    #更改发送请求时的请求头,防止403错误
    headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 SE 2.X MetaSr 1.0'}

    def start_requests(self):
        url = 'https://movie.douban.com/top250'
        yield scrapy.Request(url, headers=self.headers)

    def parse(self, response):
        items = TestdemoItem()
        movies = response.xpath("//ol[@class='grid_view']/li")
        for movie in movies:
            items["movie_rank"] = movie.xpath(".//div[@class='pic']/em/text()").extract()[0]
            items["movie_name"]=movie.xpath(".//div[@class='hd']/a/span[1]/text()").extract()[0]
            items["movie_score"] = movie.xpath(".//div[@class='star']/span[@class='rating_num']/text()").extract()[0]
            items["movie_comment"] = movie.xpath(".//div[@class='star']/span/text()").re('\d+人评价')[0]
            yield items

在settings.py文件中,修改如下代码(默认下被注释,取消注释并添加User-Agent信息即可):

USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 SE 2.X MetaSr 1.0'

如果不修改则会报403错误。使用start_requests函数,让我们对初始URL的处理就有了更多的权利,比如这次给初始URL增加请求头User_Agent。

让我们在该项目下通过命令行:scrapy crawl douban 先看看效果,发现仅仅只爬取了当前页面的25个影片信息,那么如何进一步爬取后面所有页面的信息呢?


三、自动翻页

通过对网页元素的分析,我们可以找到下一页的地址:

然后在解析该页面时获取下一页的地址时将地址交给调度器(Scheduler)。

只需添加如下代码:

    next_url = response.xpath("//span[@class='next']/a/@href").extract()
    #如果下一页存在        
    if next_url:
        next_url = "https://movie.douban.com/top250" + next_url[0]
        yield scrapy.Request(next_url, callback=self.parse,headers=self.headers)

最后在项目下通过命令行:scrapy crawl douban -o douban.csv 直接将爬取到的所有影片信息保存为项目路径下的表格文件:

可以在下面看到爬取的结果:

然后打开项目下生成的.csv文件:

总共250部影片信息一个也不少。

以上是我利用Scrapy框架对豆瓣网页爬取的第一次尝试,如有总结不到位之处还请不吝指正!

猜你喜欢

转载自blog.csdn.net/Apple_hzc/article/details/82526285