Scrapy爬虫实战

  最近,想好好学习下Scrapy爬虫框架,一种很强大的 python 爬虫框架,在观看了极客学院的课程后,自己实现了用 Scrapy爬虫豆瓣电影 top250,并存于 mysql 数据库中。接下来就开始介绍实现过程。
  首先来看看网页结构

  对应的html 代码为:

  如上图所示,主要是爬取出电影的名称、电影简要介绍、豆瓣评分、电影概括。

  环境安装:

pip3 install -U scrapy
pip3 install -U pymysql #连接数据库

  使用 scrapy startproject movie 命令新建一个 scrapy 项目。新建后的项目结构如下图:

其中,几个python文件的功能如下,
1. Items.py 定义需要抓取并需要后期处理的数据;
2. settings.py 文件配置 Scrapy,从而修改 user-agent,设定爬取时间间隔,设置代理,配置各种中间件等等;
3. pipeline.py 用于存储后期数据处理的功能,从而使得数据的爬出和处理分开,可以在这个文件中把数据存储到 mysql 数据库;
4. MovieSpider.py 自定义爬虫,主要是爬取电影的名称、电影简要介绍、豆瓣评分、电影概括。

爬取的数据结构定义(Items.py)

from scrapy import Item, Field


class MovieItem(Item):
    title = Field()
    movieInfo = Field()
    star = Field()
    quote = Field()
    pass

爬虫器(MovieSpider.py)

from scrapy.spiders import Spider
from scrapy.http import Request
from scrapy.selector import Selector

from movie.items import MovieItem


class MovieSpider(Spider):
    name = 'movie'
    url = 'https://movie.douban.com/top250'
    start_urls = ['https://movie.douban.com/top250']

    def parse(self, response):
        item = MovieItem()
        selector = Selector(response)
        movies = selector.xpath('//div[@class="info"]')
        for movie in movies:
            title = movie.xpath('div[@class="hd"]/a/span/text()').extract()
            fullTitle = ''
            for each in title:
                fullTitle += each
            movieInfo = movie.xpath('div[@class="bd"]/p/text()').extract()
            star = movie.xpath('div[@class="bd"]/div[@class="star"]/span[@class="rating_num"]/text()').extract()[0]
            quote = movie.xpath('div[@class="bd"]/p/span/text()').extract()
            if quote:
                quote = quote[0]
            else:
                quote = ''
            item['title'] = fullTitle
            item['movieInfo'] = ';'.join(movieInfo).replace(' ', '').replace('\n', '')
            item['star'] = star[0]
            item['quote'] = quote
            yield item
        nextPage = selector.xpath('//span[@class="next"]/link/@href').extract()
        if nextPage:
            nextPage = nextPage[0]
            print(self.url + str(nextPage))
            yield Request(self.url + str(nextPage), callback=self.parse)

数据存储到 mysql 数据库
首先,要在本地数据库建立 Movie 表,建表语句如下:

CREATE TABLE Movie (
  id         INT           NOT NULL PRIMARY KEY AUTO_INCREMENT
  COMMENT '自增 id',
  name       VARCHAR(1024) NOT NULL
  COMMENT '电影名称',
  movieInfo  VARCHAR(1024) NOT NULL
  COMMENT '电影详情',
  star       VARCHAR(16)                        DEFAULT NULL
  COMMENT '豆瓣评分',
  quote      VARCHAR(1024)                      DEFAULT NULL
  COMMENT '经典台词',
  createtime DATETIME                           DEFAULT CURRENT_TIMESTAMP
  COMMENT '添加时间'
)
  ENGINE = InnoDB
  DEFAULT CHARSET = utf8;

  接着,可以对数据库进行连接和存储了。这个过程可在pipeline.py完成,代码如下:

import pymysql


class MoviePipeline(object):
    def __init__(self):
        self.conn = pymysql.connect(host='127.0.0.1', port=3306, user=***, passwd=***, db=***,
                                    charset='utf8')
        self.cursor = self.conn.cursor()
        self.cursor.execute("truncate table Movie")
        self.conn.commit()

    def process_item(self, item, spider):
        try:
            self.cursor.execute("insert into Movie (name,movieInfo,star,quote) VALUES (%s,%s,%s,%s)", (
                item['title'], item['movieInfo'], item['star'], item['quote']))
            self.conn.commit()
        except pymysql.Error:
            print("Error%s,%s,%s,%s" % (item['title'], item['movieInfo'], item['star'], item['quote']))
        return item

  到此,爬虫程序就写完了,来看下结果,

  有250条数据,和网站电影数目一致,再来看下内容,

  以上就是使用 Scrapy 框架爬取所有过程,详细代码可以在我的 github查看,作者水平有限,如有不足之处,请不吝赐教。

注意:在使用 mypysql 连接数据库时,数据库的表字段属性要定义成字符串类型,pymysql 无法插入整形和浮点型到 mysql 表中,这里面有个坑,弄了好久,都没搞定。

猜你喜欢

转载自blog.csdn.net/lionel_fengj/article/details/72904843