scrapy爬虫爬取豆瓣电影

284 阅读2分钟

这是我参与11月更文挑战的第3天,活动详情查看:2021最后一次更文挑战

实验 3

3.1 题目

爬取豆瓣电影数据使用scrapy和xpath,并将内容存储到数据库,同时将图片存储在 imgs路径下。

3.2 思路

3.2.1 setting.py

  • 解除限制
ROBOTSTXT_OBEY = False
  • 数据库配置
HOSTNAME = '127.0.0.1'
PORT = 3306
DATABASE = 'scrapy_douban'
USERNAME = 'root'
PASSWORD = 'root'
  • 请求头
DEFAULT_REQUEST_HEADERS = {    
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',    
'Accept-Language': 'en',    
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.16 Safari/537.36',} 
  • 开启pipelines
ITEM_PIPELINES = {
   'doubanSpider.pipelines.DoubanspiderPipeline': 300,
}

3.2.2 item.py

  • 定义爬取的内容字段
class DoubanspiderItem(scrapy.Item):
    number = scrapy.Field()
    name = scrapy.Field()
    direct = scrapy.Field()
    actor = scrapy.Field()
    info = scrapy.Field()
    score = scrapy.Field()
    movie_img = scrapy.Field()

3.2.3 db_Spider.py

  • 观察网页,发现翻页规律

第二页

image-20211027112213118

第三页

image-20211027112230597

所以我们就看到规律了!

  • 初始信息
    page = 0
    start_url = 'https://movie.douban.com/top250'
    next_url = 'https://movie.douban.com/top250?start=%s&filter='
  • 爬取信息
        lis = response.xpath('//*[@id="content"]/div/div[1]/ol/li')
        for k in lis:
            number = k.xpath('div/div[1]/em/text()').extract()
            title = k.xpath('div/div[2]/div[1]/a/span[1]/text()').extract()
            directT = k.xpath('div/div[2]/div[2]/p[1]/text()').extract()
            score = k.xpath('div/div[2]/div[2]/div/span[2]/text()').extract()
            info = k.xpath('div/div[2]/div[2]/p[2]/span/text()').extract()
            img_url = k.xpath('div/div[1]/a/img/@src').extract()
            tmp = directT[0].split("主演:")
  • 错误处理

这里有两个地方需要处理

  1. 导演和演员

image-20211027112545181

我是按照字符串分割进行选择这个导演主演的!所有可能只出现这个字的情况

所有进行以下处理

            tmp = directT[0].split("主演:")
            if len(tmp) < 2:
                dt = tmp[0].split("导演:")
                dt = dt[1]
                ar = ""
            else:
                dt = tmp[0].split("导演:")
                dt = dt[1]
                ar = tmp[1]
  1. 另外我发现有一些的简介是没有的!

image-20211027112834906

所以采用extract_first进行处理,那么没有的就是当作来处理了

info = k.xpath('div/div[2]/div[2]/p[2]/span/text()').extract_first()

3.2.4 pipelines.py

  • 数据库连接
    def __init__(self):
        # 获取setting中主机名,端口号和集合名
        host = settings['HOSTNAME']
        port = settings['PORT']
        dbname = settings['DATABASE']
        username = settings['USERNAME']
        password = settings['PASSWORD']
        self.conn = pymysql.connect(host=host, port=port, 
                                    user=username, password=password, 
                                    database=dbname,charset='utf8')
        self.cursor = self.conn.cursor()
  • 插入数据库中
def process_item(self, item, spider):
    data = dict(item)
    print("data",data)
    sql = "INSERT INTO spider_douban(m_number,m_name,direct,actor,info,score,movie_img)" \
          " VALUES (%s,%s, %s, %s,%s, %s, %s)"
    print("sql",sql)
    try:
        self.conn.commit()
        self.cursor.execute(sql, [data["number"],
                                  data["name"],
                                  data["direct"],
                                  data["actor"],
                                  data["info"],
                                  data["score"],
                                  data["movie_img"],
                                  ])
        print("插入成功")
    except Exception as err:
        print("插入失败", err)
    return item