一 爬虫简介
爬虫这种技术听说好多年了,知道它从互联网抓取数据非常厉害,但由于不是专门从事相关工作,了解也就是听听。最近有些空闲,打算实际学习一下,这里做个小小记录。
二 常用框架介绍
- 通用性框架
类型 | 说明 |
---|---|
scrapy | 最流行的爬虫框架,功能全面,扩展性强,社区支持完善,适用于中大型爬虫项目 |
pySpider | 国产爬虫框架,自带web界面,方便监控和管理 |
轻量级框架
beautifulSoup+Requests 经典的轻量级组合,适合小型爬虫任务浏览器自动化/动态页面处理框架
Selenium 或 playwright分布式爬虫框架
scrapy-Redis 继承scrapy所有功能,是scrapy的分布式扩展
PS:从学习的角度和通用性来说,入门scrapy是最佳选择
三 scrapy框架学习
scrapy是一个快速的高级web爬虫和网页抓取框架,用于爬取网站并从其页面中提取结构化数据,它可用于从数据挖掘到监控和自动化测试等各种用途。以下内容是在linux虚拟机上操作
- 安装scrapy
sudo apt-get install python3 python3-dev python3-pip libxml2-dev libxslt1-dev zlib1g-dev libffi-dev libssl-dev
pip install scrapy
安装完成后,可以使用 scrapy --version 查看版本信息
- 创建scrapy项目
scrapy startproject quotes_scraper #创建项目quotes_scraper
3 目录结构
quotes_scraper/ #项目包目录
├── quotes_scraper/
│ ├── __init__.py #使当前文件夹成为一个python包,通常为空
│ ├── items.py #定义抓取数据的数据结构(类似数据库字段模型)
│ ├── middlewares.py #定义中间件逻辑,拦截和修改scrapy请求或响应,类似浏览器插件
│ ├── pipelines.py #定义爬取数据后续怎么处理,比如保存还是清洗
│ ├── settings.py #scrapy项目的全局配置文件
│ └── spiders/ #放置所有爬虫的地方(核心爬虫逻辑)
│ └── __init__.py #使spiders/成为一个python包,通常为空
| |___quotes_spider.py #自己创建的爬虫文件,每个.py文件定义一个spider类,负责抓取某一类网页
| # 每个spider类可以认为是一个爬虫(爬取单元)
└── scrapy.cfg #项目配置入口文件,可以认为执行爬虫时,会从这里进入然后加载到项目里面的配置模块 settings.py
ps:经过实践,简单的项目其实主要是对quotes_spider.py进行实现就行了,其他py文件不用动
四 项目实践1 :爬取Quotes to Scrape 网站上的名人名言、作者、标签
1.scrapy startproject quotes_spider -------------创建项目
2.cd quotes_spider;
scrapy genspider quotes quotes.toscrape.com-----创建一个初始爬虫quotes.py,用来爬取域名为“quotes.toscrape.com”的网站
3.编辑quotes.py 爬虫内容实现
4.scrapy crawl quotes —运行爬虫
PS:quotes.py实现内容如下
import scrapy #引入scrapy模块,为定义爬虫类做准备;scrap是python写的爬虫框架,scrapy.Spider是它提供的基类
class QuotesSpider(scrapy.Spider): #定义一个继承自scrapy.Spider名为QuotesSpider的爬虫类;前者是所有爬虫类的基类
name = "quotes" #定义爬虫的名字,用来在命令行启动爬虫,名字不能重复,项目中唯一
allowed_domains = ["quotes.toscrape.com"] #这是一个域名白名单,防止爬虫误爬
start_urls = ["https://quotes.toscrape.com"]#指定爬虫的初始入口地址,这是爬虫开始抓取的第一个页面
#scrapy会自动向这个地址发送请求,并将响应交给parse()方法处理
def parse(self, response): #parse是scrapy中默认的,用于处理网页response响应的回调函数;pass这里是占位符,表示这个函数没有实现任何逻辑,依赖用户实现
#response代表请求的网页对象所有内容及相关信息
for quote in response.css("div.quote"): #通过css选择器选中html中所有class=quote的div标签
yield{ #yield返回一条提取到的数据记录;scrapy会把yield出来的字典当作一个item,最终保存或传给管道处理
"text":quote.css("span.text::text").get(),#找到span标签里面class=text的span,::text提取文本内容
"author":quote.css("small.author::text").get(), #提取 <small class="author"> 标签的文本内容
"tags":quote.css("div.tags a.tag::text").getall(),#找出 <div class="tags"> 下面所有 <a class="tag"> 标签的文本
} #.getall() 表示获取所有匹配项的文本,返回的是一个列表
next_page = response.css("li.next a::attr(href)").get() #获取超链接地址
if next_page:
yield response.follow(next_page,self.parse)#是scrapy中翻页(抓取下一页)的核心写法之一,意思是根据next_page提供的链接地址,发起新的请求,并用
#当前的parse方法处理返回的页面内容
#response.follow是scrapy提供的简化方法,用于跟进链接并创建新的请求
#这一句可以保证抓到最后一页
五 项目实践2:从东方财富网爬取股票信息
1.scrapy startproject stock_spider
2.cd stock_spider;
scrapy genspider dfcf quotes.eastmoney.com
3.编辑爬虫文件dfcf.py
4.运行并导出文件(临时测试,settings.py文件robotobey 改为false)
scrapy crawl dfcf -o stock.csv -s FEED_EXPORT_ENCODING=gbk
PS:dfcf.py实现内容如下
import scrapy
import json #json是一种轻量级的数据交换格式,本质是纯文本表示结构化数据,这句导入json库,提供了处理json数据的方法
class DfcfSpider(scrapy.Spider):
name = "dfcf"
allowed_domains = ["eastmoney.com"]
start_urls = [
"https://79.push2.eastmoney.com/api/qt/clist/get?pn=1&pz=10&fid=f3&fs=m:1+t:2&fields=f12,f14,f2,f3,f4,f5,f6,f15,f16"
]
def parse(self, response):
data = json.loads(response.text) #把json字符串转为python数据;可以先看接口文档确认原始数据是否是json格式
# 打印结构用于调试
print("=========原始数据===========")
print(data)
if 'data' in data and 'diff' in data['data']: #判断某个键是否在字典里if key in dict #索引字典元素 dict['key']
stocks = data['data']['diff'] #从嵌套字典结构的JSON数据中提取data键下面的diff这部分内容,赋值给stocks
for _, stock in stocks.items(): # .items()是字典专用,用来获取键值对
yield { #yield关键字会生成一条字典结构的爬取结果,scrapy会自动收集这些结果项item,后续可以导出为json或csv或传给处理管道
"code": stock.get('f12'),
"name": stock.get('f14'),
"price": stock.get('f2'),
"change_percent": stock.get('f3'),
"change_amount": stock.get('f4'),
"volume": stock.get('f5'),
"turnover": stock.get('f6'),
"high": stock.get('f15'),
"low": stock.get('f16'),
}
else:
self.logger.error("未找到 data.diff 字段,接口可能变了或数据为空")
六 总结
本文章只是简单介绍了下scrapy怎么创建项目,以及用两个小小的demo来测试,看下爬虫的效果。后续真的有了使用场景,我再深入研究下,更新相关内容