爬虫框架Scrapy第一个项目

爬取cnblog文章信息。

创建项目

命令行执行:

scrapy startproject cnblog

cnblog是我们的项目名称。然后会在当前目录多一个文件夹cnblog,目录结构为:

cnblog/
    scrapy.cfg
    cnblog/
         __init__.py
        items.py
        pipelines.py
        middlewares.py
        settings.py
        spiders/
            __init__.py

简单介绍下各个文件(夹)的作用:

  • scrapy.cfg

项目的配置文件,带有这个文件的那个目录作为scrapy项目的根目录。

  • items.py

定义你所要抓取的字段。这里可以定义很多类。然后在Spider类中通过yield把爬取的item推送给pipeline。

  • pipelines.py

管道文件,Spider推送过来的item在这里会被清洗,去重,然后保存到文件或者数据库。

  • middlewares.py

中间件,主要是对功能的拓展,你可以添加一些自定义的功能,比如添加随机user-agent, 添加proxy。

  • settings.py

设置文件,用来设置爬虫的默认信息,相关功能开启与否,比如是否遵循robots协议,设置默认的headers,设置文件的路径,管道文件的选择,中间件的执行顺序等等。

  • spiders/

在这个文件夹下面,编写你自定义的spider。

编写爬虫

spiders文件夹下创建一个爬虫文件cnblog_spider.py,直接代码:

import scrapy

class Cnblog_Spider(scrapy.Spider):

    name = "cnblog"
    allowed_domains = ["cnblogs.com"]
    start_urls = [
     'https://www.cnblogs.com/',
    ]

    def parse(self, response):
        title = response.xpath('//a[@class="titlelnk"]/text()').extract()
        link = response.xpath('//a[@class="titlelnk"]/@href').extract()
        print(title)
        print(link)

修改settings.py文件

ROBOTSTXT_OBEY = False   #不遵循robots协议

#去掉下面的这个注释,以设置请求头信息,伪造浏览器headers,并手动添加一个user-agent
DEFAULT_REQUEST_HEADERS = {
  'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
  'Accept-Language': 'en',
  #user-agent新添加
  'User-Agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36"
}

爬取

在scrapy.cfg所在目录执行命令:

scrapy crawl cnblog

查看输出结果即可。

数据存储

存为txt文件和mongdb中。

修改items.py文件来定义我们自己的item:

import scrapy

class CnblogItem(scrapy.Item):
    title = scrapy.Field()
    link = scrapy.Field()

修改cnblog_spider.py文件

import scrapy
from cnblog.items import CnblogItem   #新添加

class Cnblog_Spider(scrapy.Spider):

    name = "cnblog"
    allowed_domains = ["cnblogs.com"]
    start_urls = [
     'https://www.cnblogs.com/',
    ]

    def parse(self, response):
        item = CnblogItem()    #新添加
        item['title'] = response.xpath('//a[@class="titlelnk"]/text()').extract()   #修改
        item['link'] = response.xpath('//a[@class="titlelnk"]/@href').extract()     #修改
        yield item   #新添加

修改pipelines.py文件,实现保存。

import pymongo   #别忘了导入这个模块

class FilePipeline(object):
    '''
    实现保存到txt文件的类,类名这个地方为了区分,做了修改,
    当然这个类名是什么并不重要,你只要能区分就可以,
    请注意,这个类名待会是要写到settings.py文件里面的。
    '''
    def process_item(self, item, spider):
        with open('cnblog.txt', 'w', encoding='utf-8') as f:
            titles = item['title']
            links = item['link']
            for i,j in zip(titles, links):
                f.wrire(i + ':' + j + '\n')
        return item        
        

class MongoPipeline(object):
    '''
    实现保存到mongo数据库的类,
    '''
    collection = 'cnblog'  #mongo数据库的collection名字,随便

    def __init__(self, mongo_uri, mongo_db):
        self.mongo_uri = mongo_uri
        self.mongo_db = mongo_db

    @classmethod
    def from_crawler(cls, crawler):
    '''
    scrapy为我们访问settings提供了这样的一个方法,这里,
    我们需要从settings.py文件中,取得数据库的URI和数据库名称
    '''
        return cls(
            mongo_uri = crawler.settings.get('MONGO_URI'),
            mongo_db = crawler.settings.get('MONGO_DB')
        )

    def open_spider(self, spider):                  #爬虫一旦开启,就会实现这个方法,连接到数据库
        self.client = pymongo.MongoClient(self.mongo_uri)
        self.db = self.client[self.mongo_db]

    def close_spider(self, spider):            #爬虫一旦关闭,就会实现这个方法,关闭数据库连接
        self.client.close()

    def process_item(self, item, spider):  
        '''
        每个实现保存的类里面必须都要有这个方法,且名字固定,用来具体实现怎么保存
        '''
        
        titles = item['title']
        links = item['link']
        table = self.db[self.collection]
        for i, j in zip(titles, links):
            data = {}
            data['文章:链接'] = i + ':' + j
            table.insert_one(data)
        return item
                

修改settings.py文件

ROBOTSTXT_OBEY = False

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/58.0.3029.110 Safari/537.36"
}
#新修改
ITEM_PIPELINES = {      
    'cnblog.pipelines.FilePipeline': 300,    #实现保存到txt文件
    'cnblog.pipelines.MongoPipeline': 400,     #实现保存到mongo数据库
}
#新添加数据库的URI和DB
MONGO_URI = 'mongodb://localhost:27017'  D
MONGO_DB = "cnblog" 

如果你仅仅想保存到txt文件,就将后者注释掉,同样的道理,如果你仅仅想保存到数据库,就将前者注释掉,当然,你可以两者都实现保存,就不用注释任何一个。对于上面的含义,cnblog.pipelines.FilePipeline其实就是应用cnblog/pipelines模块里面的FilePipeline类,就是我们之前写的那个,300和400的含义是执行顺序,因为我们这里既要保存到文件,也要保存到数据库,那就定义一个顺序,这里的设置就是先执行保存到文件,在执行保存到数据库,数字是0-1000,你可以自定义。

执行爬取命令即可:

scrapy crawl cnblog

 

posted @ 2018-05-01 21:19  wbinbin  阅读(152)  评论(0)    收藏  举报