【爬虫】3.Scrapy框架以及Request/Response

文章目录

  • scrapy框架
  • Resquest/Response对象
    • Resquest
    • Response
  • spider开发流程
    • 继承scrapy.Spider
    • 为Spider取名
    • 设置爬虫起点
    • 解析界面
  • 简单利用,刷CSDN博客阅读量

scrapy框架

【爬虫】3.Scrapy框架以及Request/Response_第1张图片

组件 描述 类型
Scrapy Engine 引擎,负责Spider、ItemPipeline、Downloader、Scheduler中间的通讯,信号、数据传递等 内部组件
Scheduler 调度器:,它负责接受引擎发送过来的Request请求,并按照一定的方式进行整理排列,入队,当引擎需要时,交还给引擎。 内部组件
Downloader 下载器:负责下载Scrapy Engine(引擎)发送的所有Requests请求,并将其获取到的Responses交还给Scrapy Engine(引擎),由引擎交给Spider来处理 内部组件
Spider 爬虫:它负责处理所有Responses,从中分析提取数据,获取Item字段需要的数据,并将需要跟进的URL提交给引擎,再次进入Scheduler(调度器), 用户实现
Item Pipeline 管道:它负责处理Spider中获取到的Item,并进行进行后期处理(详细分析、过滤、存储等)的地方. 可选组件
Downloader Middlewares 下载中间件:你可以当作是一个可以自定义扩展下载功能的组件,负责对resquest和response对象处理。 可选组件
Spider Middlewares Spider中间件:你可以理解为是一个可以自定扩展和操作引擎和Spider中间通信的功能组件(比如进入Spider的Responses;和从Spider出去的Requests ) 可选组件

流程:

  • 当SPIDER要爬取某URL地址的页面时,需使用该URL构造一 个Request对象,提交给ENGINE。
  • Request对象随后进入SCHEDULER按某种算法进行排队,之 后的某个时刻SCHEDULER将其出队,送往DOWNLOADER。
  • DOWNLOADER根据Request对象中的URL地址发送一次HTTP 请求到网站服务器,之后用服务器返回的HTTP响应构造出一个 Response对象,其中包含页面的HTML文本。
  • Response对象最终会被递送给SPIDER的页面解析函数(构造 Request对象时指定)进行处理,页面解析函数从页面中提取数据,封装成Item后提交给ENGINE,Item之后被送往ITEM PIPELINES进行处理,最终可能由EXPORTER以某种数据格式写入文件(csv,json);另一方面,页面解析函数还从页面中提取链接(URL),构造出新的Request对象提交给ENGINE。

Resquest/Response对象

Resquest

Request对象用来描述一个HTTP请求,下面是其构造器方法的参数列表:

Request(url[,callback,method='GET',headers,body,cookies,meta,encoding='utf8',priority=0,dont_filter=False,errback])
参数 描述
url(必须) 请求页面的url地址,bytes或str类型, 如’http://www.python.org/doc’。
callback 页面解析函数,Callable类型,Request对象请求的页面下载完成后,由该参数指定的页面解析函数被调用。如果未传递该参数,默认调用Spider的parse方法
method HTTP请求的方法,默认为’GET’
headers HTTP请求的头部字典,dict类型,例如{‘Accept’: ‘text/html’,‘User-Agent’:Mozilla/5.0’}。如果其中某项的值为None,就表示不发送该项HTTP头部,例如{‘Cookie’: None},禁止发送Cookie
body HTTP请求的正文,bytes或str类型
cookies Cookie信息字典,dict类型,例如{‘currency’:‘USD’, ‘country’:‘UY’}。
meta Request的元数据字典,dict类型,用于给框架中其他组件传递信息,比如中间件Item Pipeline。其他组件可以使用Request对象的meta属性访问该元数据字典(request.meta),也用于给响应处理函数传递信息,详见Response的meta属性
encoding url和body参数的编码默认为’utf-8’。如果传入的url或 body参数是str类型,就使用该参数进行编码。
priority 请求的优先级默认值为0,优先级高的请求优先下载。
dont_filter 默认情况下(dont_filter=False),对同一个url地址多次提交下载请求,后面的请求会被去重过滤器过滤(避免重复下载)。如果将该参数置为True,可以使请求避免被过滤,强制下载。例如,在多次爬取一个内容随时间而变化的页面时(每次使用相同的url),可以将该参数置为True。
errback 请求出现异常或者出现HTTP错误时(如404页面不存在)的回调函数。

Response

Response对象用来描述一个HTTP响应,Response只是一个基类,根据响应内容的不同有TextResponse,HtmlResponse,XmlResponse,我们通常爬取的网页,其内容是HTML文本,创建的便是HtmlResponse对象,HtmlResponse对象有很多属性,但最常用的是以下的3个方法:

  • xpath(query)
  • css(query)
  • urljoin(url)
    前两个方法用于提取数据,后一个方法用于构造绝对url。

spider开发流程

Scrapy框架提出以下问题让用户在Spider子类中作答:
● 爬虫从哪个或哪些页面开始爬取?
● 对于一个已下载的页面,提取其中的哪些数据?
● 爬取完当前页面后,接下来爬取哪个或哪些页面?
上面问题的答案包含了一个爬虫最重要的逻辑,回答了这些问题,一个爬虫也就开发出来了。
以上一节的代码为例:

import scrapy


class BooksSpider(scrapy.Spider):
    # 定义唯一标识
    name = "books"
    # 爬虫爬取起点网页
    start_urls = [
        'http://books.toscrape.com/',
    ]

    def parse(self, response):
        #	提取数据
        #	每一本书的信息在
# css()方法找到所有这样的article元素,并依次迭代 for book in response.css('article.product_pod'): # 选择器可以通过命令行工具就行调试 # 书名信息在article>h3>a元素的title属性里 # 例 如:A Light in the... # 书价信息在

的TEXT中。 # 例如:

£51.77

yield { # xpath 语法 @ATTR 为选中为名ATTR的属性节点 'name': book.xpath('h3/a/@title').get(), 'price': book.css('p.price_color::text').get(), } # 检查分页 # 提取下一页的链接 #例如: next_url = response.css('ul.pager li.next a::attr(href)').extract_first() if next_url: next_url = response.urljoin(next_url) # 构造新的 Request 对象 yield scrapy.Request(next_url, callback=self.parse)

实现一个爬虫的主要步骤有4个。

  • 继承scrapy.Spider。
  • 为Spider取名。
  • 设定起始爬取点。
  • 实现页面解析函数

继承scrapy.Spider

import scrapy
class BooksSpider(scrapy.Spider):
	...

为Spider取名

name = "books"

一个scrapy项目中可以有多个Spider,类属性name就是每一个Spider的唯一标识。在scrapy crawl命令中就使用了该标志,表示启动哪一个Spider。

设置爬虫起点

start_urls = ['http://books.toscrape.com/',]

这是一个列表,可以放置所有起始网页。scrapy会调用Spider的start_requests方法,实现对起始网页的下载请求。我们也可以重构该方法。

def start_requests(self):
	yield scrapy.Request('http://books.toscrape.com/',
						  callback=self.parse_book,
						  headers={'UserAgent':	'Mozilla/5.0'},
						  dont_filter=True)

解析界面

页面解析函数也就是构造Request对象时通过callback参数指定的回调函数(或默认的parse方法)。页面解析函数是实现Spider中最核心的部分,它需要完成以下两项工作:
● 使用选择器提取页面中的数据,将数据封装后(Item或字典) 提交给Scrapy引擎。
● 使用选择器或LinkExtractor提取页面中的链接,用其构造新的 Request对象并提交给Scrapy引擎(下载链接页面)。
一个页面中可能包含多项数据以及多个链接,因此页面解析函数被要求返回一个可迭代对象(通常被实现成一个生成器函数),每次迭代返回一项数据(Item或字典)或一个Request对象。

简单利用,刷CSDN博客阅读量

需求很简单,抓取博客的链接。起始界面为https://blog.csdn.net/fxflyflyfly

import scrapy


class BooksSpider(scrapy.Spider):
    name = "csdn"
    start_urls = ['https://blog.csdn.net/fxflyflyfly/article/list/1?',
                  'https://blog.csdn.net/fxflyflyfly/article/list/2?']

    def parse(self, response):
        for book in response.css('div.article-item-box'):
            yield {
                'name':book.xpath('//a/text()').get(),
                'type':book.css('span.article-type::text').get(),
                'list':book.css('h4 a::attr(href)').get(),
            }

因为目前的博客数量不多,不用分页处理,直接设置两个起始网页,抓取博客标题,类型和url。运行上述代码,并将数据保存(出现了中文乱码的问题,暂时还没有解决)。之后处理

接下来就是利用这些链接刷博客量。

import webbrowser as web
import os
import time

url = []
with open('C:/Users/fx/example/example/spiders/csdn.csv', encoding='utf-8') as lines:
    next(lines)
    for line in lines:
        url.append(line.split(',')[-1].strip())

for j in range(10):
    for i in url:
        web.open(i, 0, autoraise=False)
        time.sleep(2)
        os.system('taskkill /F /IM MicrosoftEdgeCP.exe')
    time.sleep(30)

上述通过打开电脑默认浏览器浏览指定url,通过直接杀死进程的方式关闭网页。

你可能感兴趣的:(python)