
公众号:uncle39py
2022/01/05阅读:49主题:默认主题
scrapy框架
此处缺图,请移步公众号 uncle39py 观看
scrapy初识
scrapy是一个爬虫框架。它是一个异步框架,即请求发出去后程序并不阻塞着,而是继续往下运行(高效)。
对框架二字的理解,就像一个大的中央帝国,有各个部门应对不同类型的日常事务,保证大一统国家的正常运转。
而requests+bs4这样的是一个个模块,只能处理和应对某一个专门的领域,当一个个模块能够无缝衔接,应对一个个不同类型的问题时,整体上就成了一个框架。
一、scrapy运行流程
看图中的序号和主件。
-
SPIDER:爬虫,用于发出各个请求;用于解析数据。是开发人员自定义的类
-
ENGINE:引擎,理解成调度机制(大总管),当序号1来的请求进入到ENGINE,就会被识别为请求并经过序号2被放到调度器中。
-
SCHEDULER:调度器,涉及爬取顺序:队列(广度优先)、堆栈(深度优先),将准备好的请求一个个丢给ENGINE(序号3)
-
DOWNLOADER:下载器,下载网页内容。途径4和5是下载中间件,对请求和响应做拦截,比如对请求统一的加头、加代理或者集成selenium自己爬取。经过序号5回到ENGINE中,被ENGINE识别为响应,就又回到SPIDERS中做解析。当解析出来的是请求则沿着1继续循环,当解析出来的是数据则沿着7、8将数据写到文件或者数据库中。
-
ITEM PIPELINES:管道,负责数据的清洗和入库
二、安装
pip3 install scrapy
windows上会有少部分人安装不上,可以按照下面的步骤处理
1、pip3 install wheel #安装后,就支持通过wheel文件安装软件,wheel文件官网:https://www.lfd.uci.edu/~gohlke/pythonlibs
2、pip3 install lxml
3、pip3 install pyopenssl
4、下载并安装pywin32:https://sourceforge.net/projects/pywin32/files/pywin32/
5、下载twisted的wheel文件:http://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted
6、执行pip3 install 下载目录\Twisted-17.9.0-cp36-cp36m-win_amd64.whl
7、pip3 install scrapy
三、创建
1、创建项目:scrapy startproject 项目名
2、创建爬虫:scrapy genspider 爬虫名 要爬取的地址
爬虫隶属于项目,一个项目下可以有多个爬虫,这就类似于Django项目和其下app的关系。
3、运行爬虫:
scrapy crawl 爬虫名
带运行日志
scrapy crawl 爬虫名 --nolog
不带运行日志
crawl的英语翻译:爬行
4、支持鼠标右键执行爬虫程序
在项目的目录下新建一个run.py(名字自取),这样就可以鼠标右键执行这个py文件
from scrapy.cmdline import execute
execute(['scrapy','crawl','chouti'])
# chouti是爬虫名
四、目录介绍
如图:
五、SPAIDER
在来看这流程张图,通过上面写的三>2创建爬虫后,会自动在spiders目录里面新建一个爬虫(py文件),爬虫的默认代码是这样的:
其中,parse函数对应流程图的序号6,在parse函数里面对取回的响应数据做解析。
在这里面一般有两类型的操作,一是用自带的解析器或第三方解析器对响应数据response.text做解析;二是yield一个新的请求地址,ENGINE会根据这个请求自动走完序号1-5的步骤,同样会再次把响应数据带回parse里面做解析。
1、两种自动的解析器:css和xpath。
title_list = response.css('.link-title')
title_list = response.xpath('//a[contains(@class,"link-title")]')
之后还需要掌握:取文本、取属性
#xpath:
response.xpath('//a[contains(@class,"link-title")]/text()').extract() # 取文本
response.xpath('//a[contains(@class,"link-title")]/@href').extract() #取属性
#css
response.css('.link-title::text').extract() # 取文本
response.css('.link-title::attr(href)').extract_first() # 取属性
#extract英语翻译:提取、提炼。extract()取出来的是列表,哪怕只有一个值也是列表
六、settings.py
先看这三个参数
#是否遵循爬虫协议。每个网站url加上/robots.txt就可以查看该网站官方允许爬取的内容。
#下面这个参数设置为False代表不遵循这个协议。
ROBOTSTXT_OBEY = False
USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36'
#配置日志级别,这样只有错误信息能打出来,其他info信息不需要打印出来。这个参数是自己添加的
LOG_LEVEL = 'ERROR'
七、持久化的两种方案
方案一:parser函数必须返回列表套字典的形式(少用,了解)
通过命令保存为csvscrapy crawl chouti -o chouti.csv
import scrapy
from myscrapy.items import ChoutiItem
class ChoutiSpider(scrapy.Spider):
name = 'chouti'
allowed_domains = ['dig.chouti.com']
start_urls = ['https://dig.chouti.com/']
def parse(self, response):
ll = []
div_list=response.xpath('//div[contains(@class,"link-item")]')
for div in div_list:
title=div.css('.link-title::text').extract_first()
url=div.css('.link-title::attr(href)').extract_first()
photo_url=div.css('.image-scale::attr(src)').extract_first()
# 持久化:方案一(用的少)parser必须返回列表套字典的形式
ll.append({'title':title,'url':url,'photo_url':photo_url})
return ll
方案二:使用piplines与items存储(mysql,redis,文件)
1、items类(类似与django中的models角色,承接数据)
class ChoutiItem(scrapy.Item):
#三个都是一样的
title = scrapy.Field()
url = scrapy.Field()
photo_url = scrapy.Field()
2、spider类,对start_urls发出请求,在parse中做数据解析
class ChoutiSpider(scrapy.Spider):
name = 'chouti'
allowed_domains = ['dig.chouti.com']
start_urls = ['https://dig.chouti.com/']
def parse(self, response):
div_list=response.xpath('//div[contains(@class,"link-item")]')
for div in div_list:
item = ChoutiItem()
title=div.css('.link-title::text').extract_first()
url=div.css('.link-title::attr(href)').extract_first()
photo_url=div.css('.image-scale::attr(src)').extract_first()
# 注意:这里只能使用中括号这种方式,不能用.
item['url'] = url
item['title'] = title
item['photo_url'] = photo_url
# 只能使用yield,每次返回一个item
yield item
3、setting中配置ITEM管道(数字越小,级别越高)
ITEM_PIPELINES = {
'myscrapy.pipelines.ChoutiMysqlPipeline': 300,
}
4、在pipelines.py中写3指定的管道类ChoutiMysqlPipeline
这里涉及三个方法
-
open_spider:开始持久化的时候执行一次,一般用于打开文件或者建立数据库连接 -
process_item:在这儿做持久化操作,步骤2 spider中yield一个item就持久化一次,直到全部持久化完 -
close_spider:持久化结束完后执行一次,一般用于关闭文件或者断开数据库连接
import pymysql
class ChoutiMysqlPipeline:
def open_spider(self,spider):
self.conn = pymysql.connect(user='root',
password="root",
host='127.0.0.1',
database='chouti',
port=3306,)
def process_item(self, item, spider):
cursor = self.conn.cursor()
sql = 'insert into article (title,url,photo_url)values(%s,%s,%s) '
cursor.execute(sql, [item['title'], item['url'], item['photo_url']])
self.conn.commit()
return item
def close_spider(self,spider):
self.conn.close()
作者介绍
