爬虫框架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

浙公网安备 33010602011771号