皇冠新体育APP

IT技术之家

皇冠新体育APP > 皇冠新体育APP

皇冠新体育APP

Scrapy_Dsprain

上线事件:2023-08-24 16:36:34 皇冠新体育APP 48次 标签:
简介Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架。我们只需要少量代码,就能够快速的抓取。Scrapy使用了Twisted[‘twisted’]异步网络框架,可以加快我们的下载速度。Scrapy的工作流程模块功能实现方式Scrapy Engine(引擎)总指挥:负责数据和信号的在不同模块间传递scrapy框架实现Scheduler (调度器)一个队列,存放引擎发过来的request请求scrapy框架实现Downloader (下载器)...

简介

Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架。我们只需要少量代码,就能够快速的抓取。
Scrapy使用了Twisted[‘twisted’]异步网络框架,可以加快我们的下载速度。

Scrapy的工作流程

模块功能实现方式
Scrapy Engine(引擎)总指挥:负责数据和信号的在不同模块间传递scrapy框架实现
Scheduler (调度器)一个队列,存放引擎发过来的request请求scrapy框架实现
Downloader (下载器)下载引擎发送来的requests请求,并返回引擎scrapy框架实现
Spider (爬虫)处理引擎发来的response,提取数据,提取url,并交给引擎需要手写
Item Pipeline (管道)处理引擎传过来的数据,比如存储需要手写
Downloader Middlewares (下载器中间件)可以自定义的下载扩展中间件,比如设置代理一般不用手写
Spider Middlewares (爬虫中间件)可以自定义request请求和进行response过滤一般不用手写

Scrapy创建项目

# 安装scrapy
pip install Scrapy
# 创建项目
scrapy startproject projectname
# 创建爬虫
scrapy genspider spidername spider域名
# 提取数据,完善spider。
# 保存数据,pipeline中保存数据。
# 启动爬虫
scrapy crawl spidername

Scrapy项目目录结构

Scrapy编写爬虫

爬虫文件

创建爬虫之后,会在项目中spiders目录下生成爬虫名的py文件。我们要对这个文件进行完善。编写数据爬取方式。
itcast.py

import scrapy


class ItcastSpider(scrapy.Spider):
    name = 'itcast'   # 定义的爬虫名
    allowed_domains = ['itcast.cn']  # 允许爬取的域名范围
    start_urls = ['//www.itcast.cn/channel/teacher.shtml']  # 开始爬取的url

    def parse(self, response):
    	# 数据解析方法。方法名不能修改。
        li_list = response.xpath("//div[@class='tea_con']//li")
        for li in li_list:
            item = {}
            item["name"] = li.xpath(".//h3/text()").extract_first()  
            item["title"] = li.xpath(".//h4/text()").extract()[0]
            # extract_first()  == extract()[0]
            yield item
从考虑这其中提现空格符串: extract() 返回一个包含有字符串数据的列表。extract_first() 返回列表的第一个字符串。同extract()[0] 注意力: spider中的parse方法名不能修改。需要爬去的URL地址必须要属于allow_domain下的链接。start_urls 首次爬取的时候,可以不满足此条件。response.xpath()返回的是一个包含selector对象的列表。scrapy中的response没有content属性,使用body替代。response.body是二进制信息,使用时需要decode()转码。 spider的数据库传至pipline利用yield。让全部整个方程成为某个转换器,才能减少内存条占据。

爬虫构造请求

有很多之后,抓取都要从手机网页中分离出来出 URL,并抓取该URL中的主要内容。这之后就都要结构需求。
class ItcastSpider(scrapy.Spider):
    name = 'itcast'   # 定义的爬虫名
    allowed_domains = ['itcast.cn']  # 允许爬取的域名范围
    start_urls = ['//www.itcast.cn/channel/teacher.shtml']  # 开始爬取的url

    def parse(self, response):
    	next_url = response.xpath("").extract_first()  # 获取到二级URL
    	# 构造请求
    	yield scrapy.Request(next_url, callback=self.parse2)
    	# 解析函数间传递数据。parse 传递数据到parse2
    	# item = {}
    	# .. 省略item中数据的获取过程。
    	# yield scrapy.Request(next_url, callback=self.parse2, meta={"item"=item})
    	
	def parse2(self, response):
		# 对二级URL所做处理
		pass
    	

scrapy.Request 能构建一个requests,同时制定提取数据的callback函数。
scrapy.Request(url [, callback, method, headers, body, cookies, meta, dont_filter=False])

meta: 实现在不同的解析函数中传递数据,meta默认会携带部分信息,比如下载延迟,请求深度等。
class ItcastSpider(scrapy.Spider):
    name = 'itcast'   # 定义的爬虫名
    allowed_domains = ['itcast.cn']  # 允许爬取的域名范围
    start_urls = ['//www.itcast.cn/channel/teacher.shtml']  # 开始爬取的url

    def parse(self, response):
    	next_url = response.xpath("").extract_first()  # 获取到二级URL
    	# 构造请求
    	# 解析函数间传递数据。parse 传递数据到parse2
    	item = {}
    	.. 省略item中数据的获取过程。
    	yield scrapy.Request(next_url, callback=self.parse2, meta={"item"=item})
    	
	def parse2(self, response):
		# 对二级URL所做处理
		item = response.meta["item"]
		pass
dont_filter: 让scrapy的去重不会过滤当前url,scrapy默认有url去重的功能,对需要重复请求的url有重要用途。

pipeline

class MyspiderPipeline:
	def open_spider(self, spider):
		pass
		
    def process_item(self, item, spider):
    	# 在这个方法中编写数据存储的方法。
        return item
	
	def close_spider(self, spider):
		pass
完工pipeline编号后,需在settings中设定重置pipeline
ITEM_PIPELINES = {
   'myspider.pipelines.MyspiderPipeline': 300,
   # 'myspider.pipelines.MyspiderPipeline' pipeline的位置
   # 300 权重。当有多个pipeline时,通过权重大小,决定执行顺序。
}
从settings中的pipeline布置就能够可以看出,pipeline就能够有多种。常见为了能让的两个作用: 可能会有多个spider,不同的pipeline处理不同的item内容。一个spider的内容可能要做不同的操作,比如存入不同的数据库。 特别注意: pipeline的权重越小,优先级越高。pipeline中process_item方法名不能修改。

open_spider方法,不是默认生成的。这个方法从名字可以看出,是在开始爬虫之前调用的方法(既此方法运行在爬虫文件之前。)这个方法在整个爬虫过程中,只会执行一次。通过此方法,可以对spider对象预先添加属性信息,还可以进行连接数据库实例化,打开本地文件等操作。
closer_spider方法,在爬虫关闭的时候执行,仅执行一次。可以进行数据库关闭连接,关闭本地文件等结束操作。

items

为要提取的数据构建数据模型。
items.py

import scrapy
class MyspiderItem(scrapy.Item):
    name = scrapy.Field()
    .. 省略更多

在爬虫文件中,如果使用了items,则只能构建模型中定义的字段。如果模型中没有,会报错。
如果爬虫文件中成功使用了items获取数据,在pipeline.py文件中,item则为对应模型,可以通过下面方法进行判断。

from myspider.items import MyspiderItem
class MyspiderPipeline:
    def process_item(self, item, spider):
    	if isinstance(item, MyspiderItem):
    		..
    		# 通过dict(item) 可以强转为dict字典类型。
        return item

Log

在settings中,能设为在移动终端读取系统日志的Log游戏等级。在设为这一个指标,能全面禁止scrapy的载入和程序运行数据信息在移动终的读取。
LOG_LEVEL = "WARNING"
在也许 现身系统异常的位置,加log输出电压。如蜘蛛文件夹目录,pipelines.py文件夹目录。
import logging
logger = logging.getLogger(__name__)  # 这样处理之后,打印出的日志可以看到所在文件名

# 可能出现异常的地方
logger.warning("loginfo")

日志不在终端打印,保存本地的设置方法。
在settings中添加

LOG_LEVEL = "WARNING"
LOG_FILE = "./log.log"

settings

settings中的分配均有详细介绍的文档文件辅导,可自愿在采用时完成如何查看。
BOT_NAME = 'myspider'

SPIDER_MODULES = ['myspider.spiders']
NEWSPIDER_MODULE = 'myspider.spiders'

LOG_LEVEL = "WARNING"
LOG_FILE = "./log.log"
# 设置user_agent。
USER_AGENT = ''

# Obey robots.txt rules 这个参数决定了爬虫是否遵循robots协议。
ROBOTSTXT_OBEY = True

# 设置最大并发请求数 (default: 16)
CONCURRENT_REQUESTS = 32

# Configure a delay for requests for the same website (default: 0)
# See //docs.scrapy.org/en/latest/topics/settings.html#download-delay
# See also autothrottle settings and docs
#DOWNLOAD_DELAY = 3
# The download delay setting will honor only one of:
#CONCURRENT_REQUESTS_PER_DOMAIN = 16
#CONCURRENT_REQUESTS_PER_IP = 16

# 是否使用cookies,scrapy在请求二级url时,可以自动携带上级cookies (enabled by default)
#COOKIES_ENABLED = False

# Disable Telnet Console (enabled by default)
#TELNETCONSOLE_ENABLED = False

# 重写headers,注意user_agent,cookies 信息不能放入请求头,需要单独处理:
#DEFAULT_REQUEST_HEADERS = {
#   'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
#   'Accept-Language': 'en',
#}

# Enable or disable spider middlewares
# See //docs.scrapy.org/en/latest/topics/spider-middleware.html
#SPIDER_MIDDLEWARES = {
#    'myspider.middlewares.MyspiderSpiderMiddleware': 543,
#}

# Enable or disable downloader middlewares
# See //docs.scrapy.org/en/latest/topics/downloader-middleware.html
#DOWNLOADER_MIDDLEWARES = {
#    'myspider.middlewares.MyspiderDownloaderMiddleware': 543,
#}

# Enable or disable extensions
# See //docs.scrapy.org/en/latest/topics/extensions.html
#EXTENSIONS = {
#    'scrapy.extensions.telnet.TelnetConsole': None,
#}

# Configure item pipelines
# See //docs.scrapy.org/en/latest/topics/item-pipeline.html
ITEM_PIPELINES = {
   'myspider.pipelines.MyspiderPipeline': 300,
}

# Enable and configure the AutoThrottle extension (disabled by default)
# See //docs.scrapy.org/en/latest/topics/autothrottle.html
#AUTOTHROTTLE_ENABLED = True
# The initial download delay
#AUTOTHROTTLE_START_DELAY = 5
# The maximum download delay to be set in case of high latencies
#AUTOTHROTTLE_MAX_DELAY = 60
# The average number of requests Scrapy should be sending in parallel to
# each remote server
#AUTOTHROTTLE_TARGET_CONCURRENCY = 1.0
# Enable showing throttling stats for every response received:
#AUTOTHROTTLE_DEBUG = False

# Enable and configure HTTP caching (disabled by default)
# See //docs.scrapy.org/en/latest/topics/downloader-middleware.html#httpcache-middleware-settings
#HTTPCACHE_ENABLED = True
#HTTPCACHE_EXPIRATION_SECS = 0
#HTTPCACHE_DIR = 'httpcache'
#HTTPCACHE_IGNORE_HTTP_CODES = []
#HTTPCACHE_STORAGE = 'scrapy.extensions.httpcache.FilesystemCacheStorage'

Scrapy CrawlSpider 使用

通常情况下,在爬取页面中的URL时,我们是根据xpath一个个获取,然后构造。
使用CrawlSpider可以让这个过程变得简单,让scrapy框架根据我们设定的规则,自动获取所需的URL。

# 创建爬虫命令
scrapy genspider -t crawl spidername spider域名
出现的网络爬虫程序
import scrapy
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule


class ChufaSpider(CrawlSpider):
    name = 'chufa'
    allowed_domains = ['cicr.gov.cn']
    start_urls = ['//cicr.gov.cn/']

    # 定义提取URL地址规则
    # Rule是一个对象,在rules中实例化
    # rules是一个元祖,可以实例化多个Rule
    rules = (
    	# allow URL的正则。不需要主域名,会自动补充。
    	# LinkExtractor 连接提取器,提取URL地址
    	# callback 提取出来的URL地址的response会交给callback处理,根据业务判断是否需要此参数。
    	# follow 当前URL地址的响应是否重新经过rules来提取URL地址
        Rule(LinkExtractor(allow=r'Items/'), callback='parse_item', follow=True),
    )

    def parse_item(self, response):
        item = {}
        #item['domain_id'] = response.xpath('//input[@id="sid"]/@value').get()
        #item['name'] = response.xpath('//div[@id="name"]').get()
        #item['description'] = response.xpath('//div[@id="description"]').get()
        return item

重视: CrawlSpider爬虫文件中,不能定义parse方法,parse有特殊功能。如果多个Rule都满足某一个URL,会从rules中选择第一个满足的进行操作。 LinkExtractor更好比较常见指标: deny:满足括号中正则的URL一定不提取,优先级高于allow。allow_domains:会被提取的连接的domains。deny_domains:一定不会被提取连接的domains。restrict_xpaths:使用xpath表达式过滤连接。 spider.Rule更好熟悉运作: process_links:指定某个函数。在获取到连接列表时将会调用该函数,主要用来过滤URL。process_request:指定某个函数。在该Rule提取到的每个requests时都会调用该函数,用来过滤requests。

Downloader Middlewares 下载中间件

当需要对请求和响应做自定义处理时,使用下载中间件。
Downloader Middlewares 默认的方法:

process_request(self, request, spider)
当每个request通过下载中间件时,该方法被调用。process_response(self, request,response,spider)
当下载器完成http请求,传递响应给引擎的时候调用。
class RandomUserAgentMiddleware:

    def process_request(self, request, spider):
    	# 提前在settings中定义USER_AGENTS_LIST列表。
        ua = random.choice(spider.settings.get("USER_AGENTS_LIST"))  
        request.headers["User-Agent"] = ua
        request.meta["proxy"] = "协议+ip+端口"  # 添加代理

    def process_response(self, request, response, spider):
        print(request.headers["User-Agent"])  # 查看每次使用的ua是否不同。
        return response
中间的件界定,,须要在settings中祖册,同pipeline。

Scrapy 模拟登陆

再不用的scrapy,用的requests做爬虫技术时,仿真模拟登入有这三种工艺: 直接携带cookies请求页面。可以放到header中,也可以在requests中给到cookies参数。找接口发送POST请求,存储cookies。selenium.找到对应的input标签,输入信息点击登陆。 食用scarpy虚拟修改密码,也是都的多种形式: 直接携带cookies。不能放到请求头中,必须给到cookie找接口发送POST请求,scrapy默认会自动存储cookies(在settings中可以设置)。selenium把登录后的cookies保存到本地,scrapy发送请求前读取本地cookies。

在开始使用scrapy模拟登陆之前,先要理解start_url的访问流程。首先,上面提到过,start_url在访问时,不会被allowed_domains规则所限制(这个限制是通过OffsiteMiddleware中间件实现的)。这是因为,我们在parse中构造的请求,是使用的scrapy.Request,而start_url的请求是使用的spider.start_requests 方法。通过源码可以看到具体实现内容。
理解了start_url的请求,就可以推测出,如果start_url是需要登录才能访问的,可以通过改写spider.start_requests 方法来实现登录后访问。

import scrapy


class ItcastSpider(scrapy.Spider):
    name = ''   # 定义的爬虫名
    allowed_domains = ['']  # 允许爬取的域名范围
    start_urls = ['']  # 开始爬取的url

	def start_requests(self):
		cookies = ""
		# cookies转化为字典
		cookies = {i.split("=")[0]:i.split("=")[1] for i in cookies.split("; ")}
		yield scrapy.Request(
			self.satrt_urls[0],
			callback=self.parse,
			cookies=cookies
		)

    def parse(self, response):
    	url = ''
    	# 默认情况下,scrapy在下次url请求时,可以自动携带cookies,不需要再次指定。
    	yield scrapy.Request(
			url,
			callback=self.parse_second
		)

	def parse_second(self, response):
    	pass

小技巧:可以在settings中设置 COOKIES_DEBUG=TRUE 参数,这样我们就可以在终端输出中看到cookie的传递,和cookie信息了。

Scrapy 模拟POST请求

实用scrapy.FormRequest方案。
class ItcastSpider(scrapy.Spider):
    name = ''   # 定义的爬虫名
    allowed_domains = ['']  # 允许爬取的域名范围
    start_urls = ['']  # 开始爬取的url
    def parse(self, response):
    	post_data = {}
		.. 省略构造post_data
		yield scrapy.FormRequest(
			"url",  # post请求路径
			formdata=post_data,
			callback=self.after_login
		)

	def after_login(self, response):
    	pass
后边此种工艺,需求不可避免找见POST提起位置。scrapy提拱了电脑自动获利Form表单控件上交位置路线的工艺。
class ItcastSpider(scrapy.Spider):
    name = ''   # 定义的爬虫名
    allowed_domains = ['']  # 允许爬取的域名范围
    start_urls = ['']  # 开始爬取的url
    def parse(self, response):
		yield scrapy.FormRequest.from_response(
			response,  # 自动的从response中寻找Form表单提交地址
			formdata={"login":"..","password":".."},  # 需要输入表单的input名和要输入的值。scrapy自动填充后提交。
			callback=self.after_login
		)

	def after_login(self, response):
    	pass

Scrapy shell

行在设备,对Scrapy能提供的性能指标通过运行和测验。以及测验xpath的最终、观察response蕴含的信息内容等方面。
scrapy shell <url>

Scrapy Redis

scrapy_redis在scrapy的基础上实现了更多,更强大的功能。具体体现在:request去重,爬虫持久化,轻松实现分布式爬虫。