1安装scrapy
如果使用大于3.8版本的conda直接可以用conda安装,在cmd中cd到conda文件夹下的Lib文件夹所在的目录下输入命令conda install scrapy 即可。
2创建一个scrapy项目
安装scrapy好后,记得把scrapy所在的路径添加用户环境变量Path中去,默认是conda文件夹的Scripts文件夹。添加完环境变量后在控制台输入scrapy startproject projectname(要创建的项目名称,不可以为已被使用过的标识符),这是会在用户名文件夹下创建这个项目,用Pycharm打开这个项目,如下图所示:
紧接着cd 进创建的项目文件夹,cd ProjectName,然后输入:scrapy genspider SpiderName xxx.com 比如笔者这里是quotes quotes.toscrape.com 第二参数是 网站域名,运行的时候,scrapy会自动补全。
创建好了项目和spider好后,用Pycharm打开刚创建的项目,Pycharm左下角点击terminal,输入pip install scrapy,就会安装好所需要的所有包。如果网速慢可以改源,网上搜一下阿里源啊清华源什么的,就可以很快安装好。
3.开始写代码
(1)解析页面
打开你创建的spider.py,比如笔者这里的quotes.py
看到:
类属性里有Spider的名字,网站域名和初始链接,有一个parse方法,故名思议,这个方法就是用来解析页面的。如下面一个例子,scrapy会返回一个response对象,他可以被xpath,beautifulsoup,或者是css选择器解析,这里用xpath解析。(这里的quotes.toscrape.com参考自崔庆才的《python3网络爬虫》)。
# -*- coding: utf-8 -*-
import scrapy
from tutorial.items import TutorialItem
class QuotesSpider(scrapy.Spider):
name = 'quotes'
allowed_domains = ['quotes.toscrape.com']
start_urls = ['http://quotes.toscrape.com/']
def parse(self, response):
quotes = response.xpath('//div[@class="quote"]')
for quote in quotes:
Item = TutorialItem()
Item['text'] = quote.xpath('.//span[@class="text"]/text()').extract_first()
Item['author'] = quote.xpath('.//small[@class="author"]/text()').extract_first()
Item['tags'] = quote.xpath('.//a[@class="tag"]/text()').extract()
yield Item
'获取下一页的链接,并通过回调函数用上面的parse方法解析下一页,下一页的内容相同'
next = response.xpath('//li[@class = "next"]/a/@href').extract_first()
url = response.urljoin(next)
yield scrapy.Request(url=url, callback=self.parse)
注意到第二行和将数据存储在item[‘xxx’],在写parse函数之前需要先创建Item,Item是用来存储数据的容器,用法和字典类似,但是多了额外的保护机制,有防止拼写错误和定义字段错误的功能。打开items,py,以上述爬虫为例,需要将items.py改成:
# -*- coding: utf-8 -*-
# Define here the models for your scraped items
#
# See documentation in:
# https://doc.scrapy.org/en/latest/topics/items.html
import scrapy
class TutorialItem(scrapy.Item):
author = scrapy.Field()
text = scrapy.Field()
tags = scrapy.Field()
根据爬到的数据定义,一个模子。
这是在左下角的terminal下输入scrapy crawl SpiderName(你自己的spider得名字),如这里输入scrapy crawl quotes terminal就会打印出爬到的内用以及一些相关的信息。
这时可以输入scrapy crawl quotes -o quotes.jl(或者.jsonline)可将爬取得数据存成json格式。
其他格式只需将 .jl换成.csv、.xml、.pickle等等。。。。
(2)将爬取到的数据存储到mongo中
利用pipelins可以对得到的数据筛选修改,存入数据库
如下面一个例子,打开pipelines.py重写它
# -*- coding: utf-8 -*-
# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: https://doc.scrapy.org/en/latest/topics/item-pipeline.html
from scrapy.exceptions import DropItem
import pymongo
class TextPipeline(object):
'''
对爬取到的数据进行修改,
如果text的长度超过50个字母,超过的部分改成...
'''
def __init__(self):
self.limit = 50
def process_item(self,item,spider):
if item['text']: #检测,防止某个item,没有爬取到等问题缺失text,而使程序奔溃,
if len(item['text']) > self.limit:
item['text'] = item['text'][0:self.limit].rstrip()+'...'
return item
else:
return DropItem('Missing Text') #不存在text跑出DropItem异常。
class MongoPipeline(object):
'''
将获得item逐个写入数据库中得到一个item写入一个
当有 itemc传进来 process_item自动执行
'''
def __init__(self, mongo_uri, mongo_db):
self.mongo_uri = mongo_uri
self.mongo_db = mongo_db
@classmethod
def from_crawler(cls,crawler):
return cls(
mongo_uri = crawler.settings.get('MONGO_URI'), #获得settings.py中得MONGO_URI,和 MONGO_DB
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 process_item(self, item, spider):
name = item.__class__.__name__
self.db[name].insert(dict(item))
print("\n\n\n 写入数据库")
return item
def close_spider(self,spider):
self.client.close()
(3)配置settings.py
打开settings.py
增加
ITEM_PIPELINES = {
'tutorial.pipelines.TextPipeline': 300, #刚刚在pipelines中定义的两个的类名,值小的先执行
'tutorial.pipelines.MongoPipeline': 400,
}
MONGO_URI = 'localhost' #表示本机数据库
MONGO_DB = 'tutorial' #项目名,在数据库中会以此来命名database
(4)运行结果
terminal终端里,显示
看到空行和”写入数据库了吗?”,观察MongoPipeline类的process_item方法,
证明了item是逐个写入的,parse函数每解析出一个item就扔给管道处理。
完犊子!