欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

爬虫之scrapy(二)

程序员文章站 2024-03-17 14:56:04
...

爬虫之scrapy(二)

在运行scrapy之前,需要了解的先行知识戳这里

本文不讲解scrapy框架的工作原理,以及相关的理论知识。我们以实用为目的,保证看完就能用。那么,我们开始吧。

创建项目

cd到指定的路径下,使用以下命令创建项目

scrapy startproject mySpider

创建之后会生成以下项目文件。

爬虫之scrapy(二)

主要文件介绍:

  • scrapy.cfg :项目的配置文件

  • mySpider/ :项目的Python模块,将会从这里引用代码

  • mySpider/items.py :项目的目标文件

  • mySpider/pipelines.py :项目的管道文件

  • mySpider/settings.py :项目的设置文件

  • mySpider/spiders/ :存储爬虫代码目录

明确爬取内容

在正式写爬虫之前,得做一些准备工作。

  1. 明确需要爬取什么数据
  2. 分析目标页面html代码,获取写对应数据的xpath

我们以获取豆瓣TOP250(http://movie.douban.com/top250)
电影名字、信息、评分为例:

爬虫之scrapy(二)

分析页面,写对应的xpath,然后用chroPath检测是否正确。具体分析过程暂且不写。最终结果如下:


item_list = response.xpath('//ol[@class="grid_view"]/li/div[@class="item"]')
      
title = './/div[@class="hd"]/a/span[1]/text()'
            #信息
infomation = './/div[@class="bd"]/p/text()'
            #评分
score = './/div[@class="star"]/span[@class="rating_num"]/text()'
            #简介
introduction = './/p[@class="quote"]/span/text()'

编写爬虫

准备工作到此已经全部完成,接下来,就开始干正事!!

1)首先,告诉Scrapy,我要抓哪些数据

打开 items.py直接在系统生成的类里申明相应的变量,存储对应的数据。

import scrapy

# 因为创建的项目名叫 movie,所以生成系统生成了MoviewItem

# 貌似。。。Movie 打错了。。。

class MoviewItem(scrapy.Item):    
    # define the fields for your item here like:
    # name = scrapy.Field()

    #标题
    title = scrapy.Field()

    #信息
    infomation = scrapy.Field()
    #评分
    score = scrapy.Field()

    #简介
    introduction = scrapy.Field()

接下来,就是写和网页相关的爬虫代码了。那么问题来了,应该写在哪呢?纵观生成的文件,没有适合写的文件啊

此时,我想到了,伟大领袖毛爷爷的一句话:“没有条件,就创造条件”。简单粗暴,干就完事了。

2)创建爬虫文件

scrapy genspider douban "douban.com"

看看这个命令,没错,一个字,干!(gen)。注意,是gen(已经打错好几次命令了。。。)

“douban.com”,是告诉scrapy不要放荡不羁爱*,只在这个域名下爬,别上错床

运行完之后,便会在spiders文件夹下生成douban.py文件

不要犹豫,打开它!!!

import scrapy

class DoubanSpider(scrapy.Spider):
    name = 'douban'
    allowed_domains = ['douban.com']
    start_urls = ['http://douban.com/']

    def parse(self, response):
        pass

生成的参数:

name: 爬虫的名,运行的时候用
allowed_domains: 允许爬虫爬的域名,就是给你的小虫子关到笼子里去。
start_urls:起始地址
parse:用来处理爬取到的页面数据

位置有了,那就直接开搞!

  1. 修改起始地址
  2. 从items文件导入MoviewItem类
  3. 因为每一页只有25个,观察发现,通过get方式传入start参数实现翻页。所以,对URL进行处理。
  4. 在parse中写xpath

一顿操作之后,结果如下:

# -*- coding: utf-8 -*-
import scrapy
from moview.items import MoviewItem

class DoubanSpider(scrapy.Spider):
    name = 'douban'
    allowed_domains = ['movie.douban.com']

    url = 'http://movie.douban.com/top250?start='
    index = 0
    start_urls = ['http://movie.douban.com/top250?start=' + str(index)]

    def parse(self, response):

        item = MoviewItem()

        item_list = response.xpath('//ol[@class="grid_view"]')

        for each in item_list:        
            item['title'] = each.xpath('.//div[@class="hd"]/a/span[1]/text()').extract()[0]

            #信息
            item['infomation'] = each.xpath('.//div[@class="bd"]/p/text()').extract()[0]

            #评分
            item['score'] = each.xpath('.//div[@class="star"]/span[@class="rating_num"]/text()').extract()[0]

            #简介
            item['introduction'] = each.xpath('.//p[@class="quote"]/span/text()').extract()[0]

            yield item
        # pass
        # 将下一页的URL加入请求队列。
        if self.index < 225:
            self.index += 25
            yield scrapy.Request(self.url + str(self.index),callback=self.parse)

发现没?items类,就当他是个Map字典类型,在items类写的变量当作键值就OK。

对了,因为要处理的不仅仅只有一个页面,还要爬翻页后的页面。因此,增加了后边三行代码。大概意思就是,把下一页的URL扔到请求队列,让scrapy有空的时候把这个页面的数据页拉回来。

其实,写到这,爬虫已经可以用了。只是,把上边的yield item改成保存数据的代码就OK了。大概这个样子

    def parse(self, response):

        if not os.path.exists('./qcmn'):
            os.makedirs('./qcmn')
        else:
            url = response.xpath("//div[@id='big-pic']//p//a//img/@src").extract()[0]
            file_name = url.split("/")

            with urllib.request.urlopen(url, timeout=30) as response, open('./qcmn/' + file_name[-2] + file_name[-1], 'wb') as f_save:
                f_save.write(response.read())
                f_save.flush()
                f_save.close()
                print(file_name[-2] + file_name[-1] + "  保存成功")

但是,这样总觉得不够完整。来来来,继续搞。

当parse使用yield item 之后,这些数据会去哪呢?这个时候,scarpy会把这些数据扔到另一个队列中,由管道文件(pipelines)处理。

但是,注意,在使用管道文件之前,需要打开setting文件,将管道文件放出来。


ITEM_PIPELINES = {
   'moview.pipelines.MoviewPipeline': 300,
}

后边的数字表示优先级,暂时不用管它。总之,在settings.py文件中找到ITEM_PIPELINES,然后去掉注释就OK。

接着,打开piplines文件

import pymysql

class MoviewPipeline(object):

    def __init__(self):
        self.connect = pymysql.connect(host='127.0.0.1',user='root',password='root',db='spider')
        self.cursor = self.connect.cursor()
    def process_item(self, item, spider):
        sql = """
            INSERT into movie (title,infomation,score,introduction) VALUES(%s,%s,%s,%s)
        """

        self.cursor.execute(sql,(item['title'],item['infomation'],item['score'],item['introduction']))
        return item

    def close_spider(self,spider):
        self.cursor.close()
        self.connect.close()

这里我是把数据写到数据库了,你也可以根据自己需要,写到本地文件。

最后的最后,为了防止服务器发现有人在悄咪咪的干这些见不得人的事,我们要设置一点点东西。

打开settings.py文件。

# 注释掉接受语言为英语的这一行,
# 添加user-agent 骗骗服务器
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; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36'
}

# 注释掉 robots.txt (就是不遵守网站的允许的爬虫约定)
# Obey robots.txt rules
# ROBOTSTXT_OBEY = True

OK,大功告成,运行

scrapy craw douban

让这个小虫子愉快的跑起来吧。。。

注意!!命令中的名字,不是项目名,是name变量的值噢!!

总结

上述过程是沿着scrapy框架爬取过程的流程写的,写代码的时候不必要按照这个流程写。但是以下这几个步骤不能少

  1. 创建项目和新建爬虫文件
  2. 确定目标网站以及明确需要的数据(items)
  3. 分析目标网站,整理正确的xpath,用于从网页中提取需要的信息。(parse)
  4. 在管道文件中写数据处理。
  5. 根据需要,改写settings
相关标签: python 爬虫