创建Scrapy项目(二)

上一篇我们已经搭建好了Scrapy框架,这一篇我们来获取网页上面的数据。

第一步:解析网页结构,分析自己所要的数据

打开网页,我们可以看到网页的结构如下图所示:


我们想要的内容则是这部分内容(电影的内容以及电影的介绍)


可能有些人觉得只弄这些东西没有意思,那我们继续进详情页看看,随便点开一个电影,进入详情页,我们可以看到网页里面有这些内容:



图片太大有些电影详情页也没有图片,所以我就省去了,不过有图片的我还是会把图片给下载下来

整理一下信息,我们所要的数据呢就是(电影的名字,电影的url,电影的类别,主演,简介,下载地址还有就是图片的url)。接下来补全爬虫

第二步:定义Items

打开Items.py文件

由于之前分析我们要获取电影的名字,电影的url,电影的类别,主演,简介,下载地址还有就是图片的url

那么我们就来定义以下它们,电影的名字:Moviename,电影的url:Movieurl,电影的类别:Moviecategory,主演:actors,简介:Introductions,下载地址:Downloadurl,图片的url:Image

接下来就在items.py文件里面输入以下代码:

Movieurl = scrapy.Field()
Moviename = scrapy.Field()
Moviecategory = scrapy.Field()
actors = scrapy.Field()
Introductions = scrapy.Field()
Image = scrapy.Field()
Downloadurl = scrapy.Field()

这样Items.py文件的内容就大功告成了

第三步:网页数据获取

打开Dytt8Spider.py文件,编辑parse函数

打开浏览器的开发者工具,随便定位电影信息,我们可以发现,所有的电影内容都包含在一个class=“co_content8”的图层里面,而电影的名字及电影的url都为里面的表格数据。仔细观察我们所要的电影url链接,发现它是不完全的,所以我们还需要补全它。所以我们可以这样编辑我们的parse函数,代码如下:

Baseurl = "http://www.dytt8.net"
contents = response.xpath("//div[@class='co_content8']/ul/td/table/tr[2]/td[2]/b")
for content in contents:
    Movieurl = content.xpath(".//a/@href").extract()[0]
    Movieurl = Baseurl + str(Movieurl)
    Moviename = content.xpath(".//a/text()").extract()
    if len(Moviename) == 0:
        Moviename = content.xpath(".//b/text()").extract()[0]
    else:
        Moviename = content.xpath(".//a/text()").extract()[0]

然而到现在为止,我们只获得了电影的名字跟电影的url,其它信息还均为获取,所以我们还需要编写一个函数,用来获取电影的详情信息,函数名为:MovieInformation

操作还是一样,先分析网页结构

打开详情页,我们可以发现,所有我们想要的内容均包含在id=‘Zoom’的图层里面,所以我们可以直接获取id=‘Zoom’图层节点下的所有文本信息(电影的类别,主演,简介,下载地址都是文本信息,可以仔细观察),这会我们只剩一个图片没有处理,仔细观察网页,我们发现有些详情页是没有图片的,所以我们也不好如何去取舍,为了偷懒,我就直接获取了id=‘Zoom’图层节点下面所有的img信息,取出第一张为图片的url,虽然这样有些欠妥,但是不能为了个别特例而把函数写的复杂,我还是使用了少数服从多数的原则,具体实现代码如下:

Image = response.xpath("//div[@id='Zoom']//img/@src").extract()
contents = response.xpath("//div[@id='Zoom']//text()").extract()
for index,content in enumerate(contents):
    if content.startswith("◎类\u3000\u3000别") or content.startswith("◎电影类型"):
        Moviecategory = content.replace('◎类\u3000\u3000别','').strip()
    if content.startswith("◎主\u3000\u3000演"):
        actors = ""
        actor = content.replace('◎主\u3000\u3000演','').strip()
        actors = actors + actor
        for x in range(index+1,len(contents)):
            value = contents[x].strip()
            if value.startswith("◎简\u3000\u3000介") or value.startswith("简\u3000\u3000介"):
                break
            else:
                actors = actors + value
        if len(actors)==0:
            actors = "不详"
    if content.startswith("◎简\u3000\u3000介") or content.startswith("简\u3000\u3000介"):
        Introductions = ""
        Introduction = content.replace('简\u3000\u3000介','').strip()
        Introductions = Introductions + Introduction
        for x in range(index+1,len(contents)):
            value = contents[x].strip()
            if value.startswith("【下载地址】"):
                break
            elif len(value)==0:
                pass
            else:
                Introductions = Introductions + value
    if content.startswith("【下载地址】"):
        Downloads = []
        for x in range(index+1,len(contents)):
            value = contents[x].strip()
            if len(value)==0:
                pass
            else:
                Downloads.append(value)

到这会我们就把我们想要的数据都提取出来了,接下来就是将数据整合,保存为Item了

这里我们再讲解一下enumerate()、startswith()、strip()三个函数

enumerate()函数是python的内置函数,对于一个可遍历的对象,它可以将其组成一个索引序列,利用它可以同时获得索引

和值,多用于for循环中

startswith()主要是用来判断字符串是否以指定字符或者字符串开头 一般格式是 str.startswith(“字符/字符串”)

strip()函数的作用主要是移除字符串首尾指定的字符,一般多为空格 eg:str.strip()移除str前面的空格

由于scrapy框架里面无法使用global对象,所以scrapy提供了一个新的方式实现这个功能,那就是meta,实现上下文的值传递

我们要将parse函数里面获得Moviename及Movieurl传递给MovieInformation函数,从而实现数据的整合

具体的代码如下:

parse函数

request = scrapy.Request(url = Movieurl,callback=self.MovieInfomation)
request.meta['Movieurl'] = Movieurl
request.meta['Moviename'] = Moviename
yield request
 
 

MovieInformation函数:

Movieurl = response.meta['Movieurl']
Moviename = response.meta['Moviename']
 
 
item = MovieItem(Movieurl = Movieurl,Moviename = Moviename,Image = Image[0],Moviecategory = Moviecategory,actors = actors,Introductions=Introductions,Downloadurl = Downloads[0])
yield item

第四步:翻页功能

刚刚只是爬取了一页的数据,接下来就是实现全部数据的爬取。

一般的网页都有一个特点,都会在底部栏出现一个页码让用户更好的翻页,所以我们可以通过网页的这个特点从而获取下一页的链接,具体代码如下:

next_page = Selector(response).re('<a href="(.*?)">下一页</a>')
if next_page:
    preurl = "http://www.dytt8.net/html/gndy/dyzz/"
    url = preurl + next_page[0]
    yield scrapy.Request(url = url,callback=self.parse)
 
 

第五步:数据存储

数据要存入Mysql数据库中,所以我们首先要先创建数据库,然后创建表

创建数据库操作:

打开Mysql客户端


输入密码进去之后,输入以下命令

create database Movie;

use Movie;

create table MovieInfos

(

    id int unsigned not null auto_increment primary key,

    Movieurl varchar(255) not null,

    Moviename varchar(255) not null,

    Moviecategory varchar(255) not null,

    Image varchar(255) not null,

    Introductions longtext not null,

    Downloadurl varchar(255) not null,

    actors longtext not null

);

打开settings.py,设置Pipelines开启

ITEM_PIPELINES = {
   'Movie.pipelines.MoviePipeline': 300,
}

进行Mysql数据库的设置

MYSQL_HOST = 'localhost'
MYSQL_DBNAME = 'Movie'
MYSQL_USER = 'root'
MYSQL_PASSWD = '***********'
MYSQL_PORT = 3306

再打开Pipelines.py文件

首先要进行的就是数据库连接操作

定义一个初始化函数 __init__,具体操作如下(常规的数据库连接操作)

def __init__(self):
    self.connect = pymysql.connect(
        host = settings.MYSQL_HOST,
        port = settings.MYSQL_PORT,
        db = settings.MYSQL_DBNAME,
        user = settings.MYSQL_USER,
        password = settings.MYSQL_PASSWD,
        charset = 'utf8',
        use_unicode=True,
    )
    self.cursor = self.connect.cursor()
 
 

接下来修改process_item函数,将数据写入数据库:

def process_item(self, item, spider):
    mysql_insert = ('insert into MovieInfos(Movieurl,Moviename,Moviecategory,Image,Introductions,Downloadurl,actors) VALUES ("%s","%s","%s","%s","%s","%s","%s")'%
                   (item['Movieurl'], item['Moviename'], item['Moviecategory'], item['Image'], item['Introductions'],
                    item['Downloadurl'], item['actors']))

    self.cursor.execute(mysql_insert)
    self.connect.commit()

    return item

return item这条语句你也可以删除,看个人喜好,我是喜欢看着数据打印出来的 这样有安全感

最后就是见证奇迹的时刻,在pycharm下面的Terminal中输入scrapy crawl Dytt8,去收获自己的成果吧,部分截图如下:







猜你喜欢

转载自blog.csdn.net/xiaozhenrenjia/article/details/80694350