Scrapy 使用

1、必须创建一个新的Scrapy项目。 进入您打算存储代码的目录中,运行下列命令 创建 Scrapy 项目

# 常用的三个命令
scrapy startproject mzt_crawl        # 生成项目
scrapy genspider mzt example.com     # 会创建一个 mzt.py
scrapy crawl test_spider             # .cfg 目录执行,启动爬虫 代码写好后执行

也可以在 .cfg 同目录下创建 main.py

from scrapy import cmdline
cmdline.execute(['scrapy','crawl','mzt'])  # spider和crawl是固定格式

该命令会创建包含下列内容的test_spider目录

test_spider
	test_spider
	scrapy.cfg         # 项目的配置文件
		__init__.py    # 该项目的python模块
		items.py       # 项目中的item文件
		middlewares.py # 项目中的pipelines文件
		pipelines.py   # 项目的设置文件
		settings.py    # 放置spider代码的目录.
		mzt.py         # 爬虫文件

scrapy.Spider

scrapy 的爬虫文件

import scrapy

from ..items import MztCrawlItem

class MztSpider(scrapy.Spider):
    name = 'mzt'
    # allowed_domains = ['www.laotuzi.com/meizitu/']
    start_urls = ['http://www.laotuzi.com/meizitu/']

    def parse(self,response):
        item = MztCrawlItem()
        item['name'] = response.text
        yield item

start_urls

这是一个列表,列表的每一个元素都一个一个url,当我们的爬虫启动的时候会循环这个列表,然后会把url当做请求的地址发送出去,但是在本文件的代码层面上是没有体现的,这里我们点击源码去一探究竟

# 点击scrapy.Spiderr源码中 当我们运行爬虫的时候 就会触发 start_requests 这个方法

    def start_requests(self):
        # scrapy 默认的起始函数(当执行启动命令时,会触发这个函数)
        cls = self.__class__
        if not self.start_urls and hasattr(self,'start_url'):
            raise AttributeError(
                "Crawling could not start: 'start_urls' not found "
                "or empty (but found 'start_url' attribute instead,"
                "did you miss an 's'?)")
        if method_is_overridden(cls,Spider,'make_requests_from_url'):
            warnings.warn(
                "Spider.make_requests_from_url method is deprecated; it "
                "won't be called in future Scrapy releases. Please "
                "override Spider.start_requests method instead (see %s.%s)." % (
                    cls.__module__,cls.__name__
                ),
            )
            for url in self.start_urls:
                yield self.make_requests_from_url(url)        
        else:
            for url in self.start_urls:
                # 每一个url封装成Request对象,交给调度器 这里dont_filter=True 默认不过滤
                yield Request(url, dont_filter=True)
                

这里我们重点是看 else 后面的代码,就先不看前面的两个 if 了,就是遍历然后把每一个url封装成 Request 对象,交给调度器,然后发送请求,默认是GET请求,回调函数是 parse

这里我们也可以自己重写发请求的方法,以及自定义回调函数

import scrapy


class BaiduSpider(scrapy.Spider):
    name = 'baidu'
    allowed_domains = ['baidu.com']
    start_urls = ['http://baidu.com/']
    
    
    def start_requests(self): 
        for url in self.start_urls:
            # 每一个url封装成Request对象,交给调度器
            yield Request(url, dont_filter=True, callback=self.my_parse)

    def my_parse(self, response):
        print(response.text)

Requests 对象

Request(url[, callback,method='GET', header,body, cookies, meta, encoding='utf-8', priority=0,dont_filte=False, errback])

下面介绍这些参数

  • url (string) ---------------> 请求页面的url地址,bytes或者str类型。
  • callback (callable) -------> 页面解析函数(回调函数) callable类型 Request对象请求的页面下载完成后,由该参数指定页面解析函数被调用。如果没有定义该参数,默认为parse方法。
  • method (string) ---------> http请求的方法,默认为GET
  • header (dict) -------------> http 请求的头部字典,dict类型,例如{“Accrpt”:"text/html","User-Agent":"Mozilla/5.0"},如果其中某一项的值为空,就表示不发送该项http头部,例如:{“cookie”:None} 表示禁止发生cookie.
  • body (str) -------------------> http请求的正文,bytes或者str类型。
  • cookies (dict or cookiejar对象) -----> cookies 信息字典,dict类型。
  • meta (dict) ------------------> Request的元素数据字典,dict类型,用于框架中其他组件传递信息,比如中间件Item Pipeline. 其他组件可以使Request对象的meta属性访问该元素字典(request.meta),也用于给响应处理函数传递信息。
  • encoding (string) ---------> url和body参数的编码方式,默认为utf-8,如果传入str类型的参数,就使用该参数对其进行编码。
  • priority (int) ----------------> 请求的优先级默认为0 ,优先级高的请求先下载。
  • dont_filter (boolean) ----> 指定该请求是否被 Scheduler过滤。该参数可以是request重复使用(Scheduler默认过滤重复请求)。但是默认的start_ulrs中的请求是dont_filter = True 不过滤。
  • errback (callable) --------> 请求出现异常或者出现http错时的回调函数。

发送post请求的话,这里归纳三种

基于Request对象 发送 Post 请求

这种是最接近底层的,通过自己改写请求方式和构造提交的数据

from scrapy import Request

headers = {'Content-Type':'application/x-www-form-urlencoded'}

data = {'k1':'v1','k2','v2'}

# 通过方法将data的键值对编码成下面这种格式
body = b'k1=v1&k2=v2'

Request(url, method='POST', headers=headers, body=body, callback=self.my_parse)

基于 FromRequest对象 发送 Post 请求

from scrapy import FromRequest

def parse():
	data = {} # 以键值对的形式存放要提交的数据 内部会把数据编码成k1=v1&k2=v2这种格式,发送出去
	yield scrapy.FromRequest(url, callback=self.my_parse, formdata=data) # 默认不指定请求方式就是POST请求

parse 默认回调函数

Response 对象和常见属性

在 Scrapy 中的 response 是一个基类,根据网站响应内容的不同,

当页面下载完成之后,Scrapy 中的下载器会根据 HTML 响应头部中的 ContentType 信息创建相应的子类对象

url: HTTP相应的 URL地址,str类型的

status: HTTP响应状态码,int类型的(在pycharm的控制台中你可以看到,例如200,404)

headers: 若要获取特定的值用 get('keyname') getlist('keyname')

get('keyname') : 获取指定key的第一个value值 返回str

getlist('keyname') : 获取指定key的所有value值 返回list

body: HTTP响应正文,bytes类型

text: 文本形式的HTTP响应正文,str类型,由response.body使用response.encoding解码得到的

request: 产生该HTTP响应的Requset对象

encoding: HTTP响应正文的编码

meta: response.request.meta 在构造 request 对象的时候,可以将要传递个响应处理函数的信息通过 meta 参数传入;响应处理函数处理响应时候,通过 response.meta 将信息取出


meta 传参

meta(字典)是Request对象中的一个参数,可以在请求和响应之间传递

Request(url=url,meta={'page':'1'})


def paser(self,response)
	page = response.meta.get('page') # 获取上次请求中的meta中的page对应的值
    new_page = page += 1
    
    url = 'http://www.xiaohua.com/index?page={}'.formate(new_page)
    
    ....
    
    yield Request(url=url,meta={'page':new_page})

Don't forget to add your pipeline to the ITEM_PIPELINES setting

 posted on 2021-06-03 19:46  Rannie`  阅读(208)  评论(0编辑  收藏  举报
去除动画
找回动画