一、Scrapy简述
摘自官方文档:
Scrapy is a fast high-level web crawling and web scraping framework, used to crawl websites and extract structured data from their pages. It can be used for a wide range of purposes, from data mining to monitoring and automated testing.
Scrapy是爬虫中的一个明星框架,它具有高性能的持久化存储、异步数据爬取、高性能的数据解析、分布式爬虫的Python爬虫框架!
二、Scrapy基本使用
2.1、环境安装
pip3 install scrapy
2.2、创建Scrapy项目
scrapy startproject tutorial # 在项目名目录下创建一个爬虫文件,tutorial仅为示例。
创建完后的层级结构应该是这样子的:
tutorial/
scrapy.cfg # deploy configuration file
tutorial/ # project's Python module, you'll import your code from here
__init__.py
items.py # project items definition file
middlewares.py # project middlewares file
pipelines.py # project pipelines file
settings.py # project settings file
spiders/ # a directory where you'll later put your spiders
__init__.py
2.3、创建爬虫文件
scrapy genspider example example.com # 这个域名无关紧要,可以随时更改。
2.4、启动项目
启动爬虫有好几种方式,总的来说是分命令行与脚本文件形式。一个爬虫文件格式如下:
import scrapy
class SpiderSpider(scrapy.Spider):
name = 'spider' # 文件名
allowed_domains = ['baidu.com'] # 允许爬取的URL,不在此范围则不爬取,所以经常会注释掉。
start_urls = ['http://baidu.com/'] # 爬取的URL列表
def parse(self, response): # response为服务器响应内容封装成对象
print(response.text) # 获取响应对象的内容
命令行启动
scrapy crawl spider # crawl后面跟指定的爬虫文件
窗口会打印如下信息:
2021-05-05 10:11:00 [scrapy.core.engine] INFO: Spider opened
2021-05-05 10:11:00 [scrapy.extensions.logstats] INFO: Crawled 0 pages (at 0 pages/min), scraped 0 items (at 0 items/min)
2021-05-05 10:11:00 [scrapy.extensions.telnet] INFO: Telnet console listening on 127.0.0.1:6023
2021-05-05 10:11:00 [scrapy.downloadermiddlewares.redirect] DEBUG: Redirecting (meta refresh) to <GET http://www.baidu.com/> from <GET http://baidu.com/>
2021-05-05 10:11:00 [scrapy.core.engine] DEBUG: Crawled (200) <GET http://www.baidu.com/> (referer: None)
sanxi666
2021-05-05 10:11:00 [scrapy.core.engine] INFO: Closing spider (finished)
2021-05-05 10:11:00 [scrapy.statscollectors] INFO: Dumping Scrapy stats:
{'downloader/request_bytes': 422,
'downloader/request_count': 2,
'downloader/request_method_count/GET': 2,
'downloader/response_bytes': 1838,
'downloader/response_count': 2,
'downloader/response_status_count/200': 2,
'elapsed_time_seconds': 0.249001,
'finish_reason': 'finished',
'finish_time': datetime.datetime(2021, 5, 5, 2, 11, 0, 393058),
'httpcompression/response_bytes': 2381,
'httpcompression/response_count': 1,
'log_count/DEBUG': 2,
'log_count/INFO': 10,
'response_received_count': 1,
'scheduler/dequeued': 2,
'scheduler/dequeued/memory': 2,
'scheduler/enqueued': 2,
'scheduler/enqueued/memory': 2,
'start_time': datetime.datetime(2021, 5, 5, 2, 11, 0, 144057)}
2021-05-05 10:11:00 [scrapy.core.engine] INFO: Spider closed (finished)
脚本文件启动
import scrapy
from scrapy.crawler import CrawlerRunner
from scrapy.utils.log import configure_logging
from twisted.internet import reactor
class SpiderSpider(scrapy.Spider):
name = 'spider'
allowed_domains = ['baidu.com']
start_urls = ['http://baidu.com/']
def parse(self, response):
print('sanxi666')
configure_logging() # 打印爬取日志
runner = CrawlerRunner() # 实例化runner对象
runner.crawl(SpiderSpider) # 爬取指定的类或文件中所定义的爬虫方法
# runner.crawl(SpiderSpider2) # 如果有多个爬虫方法就这样定义即可
do = runner.join() # 等待所有爬虫程序结束
do.addBoth(lambda _: reactor.stop()) # 停止
reactor.run()
常用settings配置
跟Django类似
ROBOTSTXT_OBEY = False # 不遵循robots协议# UA伪装USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 ' 'Safari/537.36 'DOWNLOAD_DELAY = 3 # 下载失败的重试次数LOG_LEVEL = 'ERROR' # 输出的日志等级
三、Scrapy数据解析
Scrapy毋须获取响应对象,直接用response.xpath()解析数据,用法跟lxml的xpath基本一样的,返回也是列表。
extract(),将selector对象中data参数存储的所有文本提取出来,extract_first取第一个,返回的也是列表形式。
class SpiderSpider(scrapy.Spider): name = 'spider' # allowed_domains = ['baidu.com'] start_urls = ['https://docs.djangoproject.com/zh-hans/2.2/'] def parse(self, response): ui_list = response.xpath('//*[@id="s-the-view-layer"]/ul') # 用xpath解析响应内容 for ui in ui_list: ui_content = ui.xpath('./li/strong/text()')[0].extract() # extract()获取data里面的文本信息
未完待续。。。其实是我不想写了
Scrapy持久化存储
有两种方式,一种基本命令行,另一种是基于管道传输。
基于终端指令
直接在命令行启动爬虫时指定输出文件格式,此方法仅可将parse方法的返回值存储到本地的文本文件中
-o 跟一个文件,仅支持json、xml、CSV等
优点:简捷
缺点:不够灵活,只能是规定的格式,不能存储在数据库
基于管道
流程:
数据解析
item类定义相关属性
将结果封装存储到item类型的对象中
将item对象提交给管道进行持久化存储
爬虫提交的item只会给管道第一个类接受,所以第一个管道类应该return一个item对象
在pipelines中,用process_item来处理item对象,每接受一个item就会调用一次
重写父类的open_spider()方法,仅在爬虫开始时调用一次,在这里打开文件写入即可
重写close_spider(),结束时调用一次,可以在这里关闭文件
配置文件开启管道
ITEM_PIPELINES
优点:
兼容性强,可存储在多种渠道
缺点:
需要注意编码
通过管道存储到数据库
基于spider的全站数据爬取
即将网站某个板块下的全部页码对应的页面数据进行爬取
实现方式:
将所有页面的URL添加到start_urls列表中,但是不推荐
手动进行请求发送
五大核心组件:
请求传参:
使用场景:如果爬取解析的数据不在同一张页面,这需要深度爬取
爬取boss直聘岗位
请求传参,传的是item对象,使用meta={},可以将meta字典传给请求回应的回调函数
回调函数接受item
使用response.meta['item']