爬虫学习小结

2023-10-31

前几天学习爬虫,总结如下:

一、 Request

1. get函数初介绍

r = request.get(URL, params, **kawarg)

  • params :额外的参数,字典或者字节流格式, 可选
  • **kawarg: 12个控制访问的参数。
    返回的r是包含服务器资源的Response对象

2. response 对象

属性:

属性 说明
r,status_code HTTP请求的返回状态,200表示正常
r.text HTTP相应的字符串形式
r. enconding HTTPheader中猜测的相应内容编码方式
r.apparent_encoding 从内容中分析出的相应内容编码方式
r.content HTTP相应内容的二进制形式

两种编码方式 encoding 和apparent_encoding区别:

encoding 就是提取header中charset 字段信息
apparent_encoding根据内容分析编码方式,更加准确

3. Request库异常

异常 说明
request.ConnectionError 网络连接错误异常,如DNS查询失败,拒绝连接等。
request.HTTPErrot HTTP错误异常
request.URLRequired URL缺失异常
requests.TooManyRedirects 超过最大重定向次数,产生重定向异常
requests.ConnextTimeout 连接远程服务器超时异常
requests.Timeout 请求URL超时,产生超时异常

根据Response库提供函数确定异常,比如r.raise_for_status(),判断返回内容是否正常,如果不是返回200,说明产生异常requests.HTTPError

4. 通用代码框架

import requests
def getHTMLTexxt(url):
	try:
		r = request.get(url, timeout=30)
		r.raise_for_status()
		r.encoding = r.apparent_encoding
		return r.text
	except:
		return "产生异常"
if __name__ == "__main__":
	url = "http://www.baidu.com"
	print(getHTMLText(url))

5. Request库七个主要方法

方法 说明
requests.request() 构造一个请求,支撑以下各个方法的基础方法
request.get() 获取HTML网页的主要方法,对应于HTTP的GET方法
request.head() 获取HTML网页头信息的方法
request.post() 获取网页提交POST请求的方法
request.put() 向HTML网页提交PUT请求的方法
request.patch() 向HTML网页提价局部修改请求
request.delete() 向HTML页面提交删除请求

在这里插入图片描述
PATCH和PUT的区别:

假设URL位置有一组USERInfo,包括UserID, UsserName等20个字段。
采用PATCH,只是向URL提交UserName的局部更新
采用PUT,必须将所有20个字段一并提交到URL,未提交字段将会被删除。

r = requests.head("http://www.baidu.com")
r.headers
r.text

payload = {'key1':'value1','key2':'value2'}
r = request.post{'http://httpbin.org/post', data = payload}
r.text

post根据用户提交的内容不同,在服务器上进行相关的整理。
在这里插入图片描述

其他的六种方法都是基于requset方法直接封装起来的。

6. 控制访问参数

request.request(method, url, ** kwargs)
**kwargs::控制访问的参数,均为可选项

  • params:字典或字节序列,作为参数增加到url中
    在这里插入图片描述
  • data: 字典,字节序列或文件对象,作为Request内容
    在这里插入图片描述
    我们提交的data会放在URL对应的地方作为数据存储。
  • json 作为Request的内容, 和data很像,会把数据赋值到服务器的json域
  • headers: 字典,HTTP定制头
    在这里插入图片描述
    request函数共13个访问控制参数:
    在这里插入图片描述
    request.get函数有12个访问控制参数,request.head有13个,post, get, put patch, delete他们的访问控制参数都几乎和上面相同。

二、Robots协议

网站根目录下robots.txt, 不提供robots就是指可以无限制的爬取

三、beautifulSoup

对文件内容进行树形解析。

from bs4 import BeautifulSoup
import bs4

1. 解析器

解析器 使用方法 条件
bs4的HTML解析器 BeautiSoup(mk,‘heml.parser’) 安装bs4库
lxml的HTML解析器 BeautifulSoup(mk,‘lxml’) pip install lxml
lxml的xml解析器 BeautiSoup(mk,‘xml’) pop instal lxml
html5lib的解析器 BeautifulSoup(mk,‘html5lib’ pip install html5lib

2. beautifulSoup库的基本元素

基本元素 说明
Tag 标签,最基本的信息组织单元,用<> </>表示开头结尾
Name 标签的名字,比如

的名字为‘p’
Attribute 标签树形,字典形式,格式:.attrs
NavigableString 标签内非属性字符串,<>…</>中字符串
Commet 标签内字符串的注释部分

在这里插入图片描述

3. 遍历

在这里插入图片描述

  • 下行遍历
属性 说明
.contents 子节点的列表,将的所有儿子节点存入列表
.childrens 子节点的迭代类型, 与.contents类似, 用于循环遍历儿子节点
.descentants

在这里插入图片描述

  • 上行遍历
属性 说明
.parent 节点的父亲标签
.parents 节点先辈标签的迭代类型,用于循环遍历先辈节点

在这里插入图片描述

  • 平行遍历
属性 说明
.next_sibling 返回HTML文本顺序的下一个平行节点标签
.previous_sibling 返回按照HTML文本顺序的上一个平行节点标签
.next_siblings 迭代类型,返回按照HTML顺序的后续所有平行节点标签
.previous_siblings 迭代类型,返回按照HTML文本顺序的前序所有平行节点标签

在这里插入图片描述
在这里插入图片描述

4. 信息标记三种类型

  • XML, 标签
  • json, 有类型的键值对
  • yaml , 无类型的键值对 ,通过缩进表达所属关系

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
三种信息形式的比较

XML Internet上信息交互和传递
Json 移动应用云端和节点的信息通信,无注释
YAML 各类系统的配置文件,有注释易读

5. find_all函数

<>.find_all(name, attrs, recursive, string, **kwags)
返回一个列表类型,存储查找的结果
name: 对标签名臣的检索字符串
attrs:对标签属性值进行检索
recursive: 是否对子孙全部检索,默认为TRUE
string: <>…</>中字符串区域的检索字符串

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

(…)等价于 .find_all(…)
(…)等价于 soup.find_all(…)
扩展方法

方法 说明
<.find()> 搜索只返回一个类型,字符串类型,参数和find_all相同
<>.find_parents() 在先辈节点中搜索,返回列表类型
<>.find_parent() 在先辈节点返回一个结果,字符串类型
<>.find_next_siblings() 后续平行节点中搜索,返回列表类型
<>.find_next_sibling() 后续平行节点中搜索一个结果,返回字符串
<>.find_previous_siblings() 前序平行节点中搜索,返回列表类型
<>.find_previous_sibling() 前序平行节点中搜索一个结果

四、正则表达式

1. 常用的操作符

在这里插入图片描述
在这里插入图片描述

raw string类型(原生字符串类型),表示为:r’text’
原生的字符串就是不包含转义符的字符串。

2. 主要功能函数

函数 说明
re.search() 在字符串中搜索匹配正则表达式的第一个位置,返回match对象
re.match() 从一个字符串的开始位置起匹配正则表达式,返回match 对象
re.findall() 搜索字符串,列表类型返回全部匹配的字符串
re.spilit() 讲一个字符串按照正则表达式匹配结果进行分割,返回类表类型
re.finditer() 搜索字符串,返回一个匹配结果的跌打类型,每个迭代元素是match元素
re.sub() 在一个字符串中替换所有匹配正则表达式的子串,返回替换后的字符串
  • re.search(pattern, string, flags = 0)
  • flag: 正则表达式使用时的控制标记
    • re.I re.IGNORECASE 忽略正则表达式大小写
    • re.M re.MULTILINE 正则表达式中的^操作符可以将给定字符串的每行当做匹配开始
    • re.S re.DOTALL 正则表达式中的操作符能匹配所有字符,默认匹配除换行外所有字符。
match = re.search(r'[1-9]\d{5}','BIT 100081')
Iif match:
	print(match.group(0))
>>> 100081
  • re,match(pattern, string, flags = 0)
match = re.match(r'[1-9]\d{5}','BIT 100081')
if match:
	match.group(0)
>>>输出为空
match = re.match(r'[1-9]\d{5}','100081 BIT')
if match:
	match.group(0)

>>>100081
  • re.findall(pattern, string, flags = 0)
ls = re.findall(r'[1-9]\d{5}','BIT 100081 198788HU')
ls
>>>['100081','198788']
  • re.split(pattern, string, maxsplit = 0, flags = 0)
  • maxsplit :最大分隔数,如果数值小于匹配结果,剩余的部分作为最后一个元素输出
re.split(r'[1-9]\d{5}','BIT100081 519878HU', maxsplit = 1)
>>['BIT',' 519879HU']

  • re.finditer(pattern, string, flags = 0)
for m  in re.finditer(r'[1-9]\d{5}','BIT100081 TSU100084')
		if m:
			print(m.group(0))
  • re.sub(pattern, repl, string, count = 0, flags = 0)
  • 在一个字符串中替换所有匹配正则表达式的子串,返回替换后的字符串
  • repl: 替换匹配字符串的字符串
  • string 带匹配的字符串
  • count 匹配的最大替换次数
re.sub(r'[1-9]\d{5}',':zipcode','BIT100081 TSU100084')
>> 'BIT:zipcode TSU:zipcode'

3. 等价写法

rst = re.search(r’[1-9]\d{5}’,‘BIT 100081’)
等价于
pat = re.compile(r’[1-9]\d{5}’)
rst = pat.search(‘BIT 100081’)

函数式用法是一次性操作
面向对象的写法,用于编译后的多次操作

regex = re.compile(pattern, flags = 0)

在这里插入图片描述

对于之前的写法只是去掉了pattern对象

4. match对象

type(match)
<class '-src.SRE_Match'>
  • match对象的属性
属性 说明
.string 带匹配的文本
.re 匹配时的pattern对象
.pos 正则表达式搜索文本的开始位置
.endpos 正则表达式搜索文本的结束位置
  • match对象的方法
方法 说明
.group(0) 获得匹配后的字符串
.start() 匹配字符串在原始字符串的开始位置
,end() 匹配字符串在原始字符串的结束位置
.span() 返回(.start(), .end()

match 对象是返回一次的结果,如果想获得所有的匹配结果,可以使用finditer()

在这里插入图片描述

5. 贪婪匹配和最小匹配

re库默认使用贪婪匹配,即输出匹配最长的子串
如何输出最小匹配呢?
当我们看到一个操作符匹配结果有不同长度的时候,可以在后边加一个问号,返回最小结果。

match = re.search(r'PY.*N','PYANBNCNDN')
match.group(0)
>>>'PYANBNCNDN'
match = re.search(r'PY.*?N','PYANBNCNDN')
match.group(0)
>>> 'PYAN'
  • 最小匹配操作符
操作符 说明
*? 前一个字符0次货无限次扩展,最小匹配
+? 前一个字符1次或多次扩展,最小匹配
?? 前一个字符0次或1次扩展,最小匹配
{m,n}? 前一个字符m到n次,包含n, 最小匹配

五、scrapy

在这里插入图片描述

  • spider middleware
    • 目的: 对请求和爬取项再处理
    • 功能:修改丢弃,新增请求或者爬取项
    • 用户可以编写配置代码
  • scrapy 命令行格式

scrapy [options][args]

  • scrapy常用命令

在这里插入图片描述

  • 工程目录
    在这里插入图片描述

  • yield关键字

生成器是一个不断产生值的函数
包含yield语句的函数就是一个生成器
生成器每次产生一个值,函数被冻结,唤醒后在产生一个值

在这里插入图片描述

如果N = 1M, 10M, 100M
普通写法占用很大的存储空间,并且相应速度慢

  • Request 类

和我们之前学习的Request库不是一个方法
class scarpy.http.Request()
Request对象表示一个HTTP请求
由spider生成,由Downloader执行

在这里插入图片描述

  • Response类

class scrapy.http.Response()
Response对象表示一个HTTP相应
由Downloader生成,由Spider处理

在这里插入图片描述

  • Item类

class scrapy.item.Item()
Item 对象表示一个从HTML页面中提取的信息内容
由spider生成,由Item Pipeline 处理
Item 类似字典类型,可以按照字典类型操作

  • 爬虫提取信息的方法
    • spider 模块可以使用的方法
    • Beautiful Soup
    • lxml
    • re
    • Xpath Selector
    • CSS Selector
  • 编写步骤
  1. 建立工程和spider模块

scrapy startproject BaiduStocks
cd BaiduStocks
scrapy genspider stocks baidu.com
进一步修改spiders/stocks.py文件

  1. 编写spider

修改配配stacks.py文件
修改对返回页面的处理
修改对新增URL爬取请求的处理

  1. 编写pipelines

配置pipelines.py文件
定义对爬取项(Scraped Item)的处理类
配置ITEM_PIPELINES选项

  1. 使用crawl命令执行程序。

也可以进行优化
在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

爬虫学习小结 的相关文章

  • 日常学习 mmsegmentation处理数据集和图片格式

    mmsegmentation 对数据集的读取与处理 对于自定义数据集需要在mmseg datasets下建立自己的数据集文件 如 import os path as osp from builder import DATASETS from
  • 压缩/减小VirtualBox虚拟硬盘文件占用空间

    文章目录 网上的做法 导出虚拟电脑 再导入 网上的做法 网上有两种压缩空间的做法 1 在虚拟机中 使用 SDelete 例如 sdelete c z 经本人实测 不仅不能压缩 因为SDelete 扫描了整个c 盘 而 VirtualBox
  • 创建对象的五种方式

    1 使用new关键字 gt 调用构造函数 2 使用Class的newInstance方法 gt 调用构造函数 3 使用Constructor的newInstance方法 gt 调用构造函数 4 使用clone方法 gt 没有调用构造函数 5
  • windows 打开方式 其他程序不可用

    文章目录 HKEY CURRENT USER Software Microsoft Windows CurrentVersion Explorer FileExts doc 此处对应当前的文件后缀 此处以 doc为例 删除 OpenWith
  • 公积金提取 -- 小黑日常超详细教程

    公积金说明 是入职以后五险一金中的一金 它的产生是国家给予的福利 国家规定它的缴纳数组成是 工资的6 12 然后按照公司给予福利的6 12 区间值计算 公积金存款 公司缴纳的百分比 x 你的工资 x 2 注 正经公司会根据实际发给你的工资计
  • 锚点定位被顶部固定导航栏遮住的解决方案

    很多网站都有一个固定在上方的导航栏 方便用户搜索和跳转到其他页面 同时为了方便用户浏览长文档 都会加上目录 点击段落标题跳转到段落所在的位置 如图所示 如果使用锚点实现目录的跳转 会遇到 fixed 导航栏遮住了标题的问题 锚点定位机制 如
  • 留言簿怎么用?

    看不到别人留言 自己也没法写留言 囧rz
  • 训练集(离线)与测试集(上线)效果差距很大怎么办?

    前言 相信各位童鞋在跑模型的时候时不时会遇到一个尴尬的现象 就是你在训练集或者验证集的模型效果好到令人发指 一时间以为 哼 就这 游戏结束 结果当你在测试集或者上线后发现真的就游戏结束了 指标低的没眼看 本人还是一个算法菜鸟时就遇到过这种情
  • 解决choice金融终端Excel/Wps插件修复visual basic异常

    注意 如下情况无解 注意 Excel要用专业版 家庭版的Excel无法修复 WPS要用企业版 个人版的Wps无法修复 解决方法 下面是安装Office专业版的教程 进入网站https msdn itellyou cn 下载office专业版
  • 三国志13pk版登录武将输入中文名方法与更改图像详解

    今天来个正经的文 三国志13里登录武将 设定姓名时 如果用的是自带输入法 就会出现一堆乱码 这时候 有两种解决方法 下载一个具有大五码的输入法 然后输入时候既要切换输入法 切换繁体 切换窗口模式 很麻烦 尤其在输入列传的时候 打很多字会很不
  • 左耳朵耗子:拖累开发团队效率的困局与解决之道

    作者 陈皓编辑 小智影响软件开发团队效率的因素有许多 产品和业务上的效率问题固然是根本 但很多时候 这种问题并没有解 如果只从软件开发的过程出发 哪些开发方式是典型 又该怎么解呢 写在前面 我之前写过一篇叫 加班与效率 的文章 从概念上说了
  • 测试开发工程师的简历和面试准备

    文章目录 职业规划 核心事项 不必等待准备 完美 才投简历 准备简历 确定一批目标公司和目标职位 详细事项 可以慢慢完备 时间有限 注意结合所需 简历 简历命名 邮件标题同理 携带个人信息 优先使用pdf格式的简历 最好打印大小是A4 简历
  • 2020流水账

    今天这边过小年 离农历新年也没几天了 没心思复习考研 也不太想敲代码 不如写写年度总结吧 这一年算是很舒服的了 上半年因为疫情在家待了大半年 网上上课 和在学校一样 大部分时间还是坐在电脑前面玩手机 要说繁琐的话就是几个大作业 课上没咋听
  • 【随笔】在vue项目使用icon

    Vue引用icon图标 利用i标签 快速添加页面图标 利用i标签 快速添加页面图标 之前写项目遇见图标都是下载成icon然后用img展示 但是图标写多了就会变得特变麻烦 光下载的图标就会占很大空间 所以学着用i写 首先进入项目 在项目下建一
  • 【python】pyi文件

    简单做个记录 今天看代码的时候看到这样子一块 就是只有类型的声明 我不知道具体是怎么实现的 关于这个函数的上一级调用定义中 rnorm是通过那个只有申明类型的pyi文件得到的 我想查看细节但是不知道怎么看 百度了一下 pyi文件是存根文件
  • 从一个对象数组中的某一个属性组成新数组,然后比较大小

    需求 从一个对象数组中的某一个属性组成新数组 然后比较大小 示例数组 原始数组 expmArr name zhangsan age 18 name lisi age 20 name wangwu age 17 name zhaoliu ag
  • chat gpt的提示词汇总

    提示词的存在让ChatGPT能够扮演特定的角色 对用户的回答更加专业对口 ChatGPT在日常的对话中 表现的非常的完美 当在其他的场景希望使用ChatGPT来解决问题的时候 通常需要给ChatGPT一些提示 或者说暗示 让其进入某种角色
  • 全国大学生数学建模竞赛——大赛介绍与赛后总结

    全国大学生数学建模竞赛 训练过程及赛后总结 前言 今天是2018年9月18日 一个特殊的日子 距离全国大学生数学建模大赛已经过去两天了 三天两夜的比赛 每天晚上几乎做到凌晨 确实很辛苦 但是现在回过头来看看 无论成绩如何 一切的辛苦与努力都
  • 重要通知:9月1日起,微信小程序须完成备案后才可上架

    微信官方通知 近日 工信部发布了 工业和信息化部关于开展移动互联网应用程序备案工作的通知 8月9日 微信公众平台也发布了 关于开展微信小程序备案的通知 一 备案必要性 在中华人民共和国境内从事互联网信息服务的移动互联网应用程序主办者 应当依
  • Keil MDK编程环境下的 STM32 IAP下载(学习笔记)

    IAP下载 IAP的引入 不同的程序下载方式 ICP ICP In Circuit Programing 在电路编程 可通过 CPU 的 Debug Access Port 烧录代码 比如 ARM Cortex 的 Debug Interf

随机推荐

  • Collectors.summing唯独没有BigDecimal的求和方法

    最近在做订单相关的模块 有个订单列表接口 需要对订单金额进行求和 每次都得遍历list 然后用BigDecimal add 方法取求和 感觉很麻烦 想到之前有用到java8的stream collect的Collectors summing
  • 一个例子搞懂 tabelu的上下文筛选器

    示例 1 将维度筛选器转换为上下文筛选器 本示例以及以下示例使用 Tableau Desktop 附带的 Sample Superstore 数据源 在此示例中 视图解决以下问题 按总销售额计 纽约市位居前 10 名的客户有哪些 视图包含两
  • Mono和MonoDevelop源码编译安装

    Mono和MonoDevelop源码编译安装 之所以用源码编译的方式安装mono和monodevelop 是因为通过yum安装的mono不是最新版本 而且monodevelop不能建 asp net MVC3的工程 而且通过源码安装 可以进
  • 世界坐标系、相机坐标系、图像坐标系、像素坐标系之间的转换及三维空间的刚体运动

    基本概念 https blog csdn net sunshine zoe article details 73457686 世界坐标系到相机坐标系下的变换 https www jianshu com p 64b4c887c439 通过两个
  • jquery中的伪数组和each和map静态方法区别,以及其他的一些静态方法

    伪数组 1 必须要有length属性 2 如果这个length的属性值是0 那么这个对象有没有元素无所谓 3 如果这个length的属性值不为0 那么这个对象一定头下标为 length 1 的属性值 列如 伪装组 var obj lengt
  • 公有链、联盟链、私有链区别

    1 公有链 公有链是世界上任何人都可以访问读取的 任何人都可以发送交易并且如果交易有效的话可以将之包括到区块中的 以及任何人都能够参与与其共识过程的区块 优点 所有交易数据公开 透明 无法篡改 缺点 低吞吐量 TPS 交易速度慢 2 联盟链
  • java橙色风格小说精品屋小说网站源码

    没有搭建教程 懂的自行下载研究 文件 590m com f 25127180 486121419 fbf84f 访问密码 551685 安装环境 宝塔面板 tomcat8 nginx1 17 mysql5 6 不知道最高支持到多少 打开服务
  • linux netLink检测usb插拔事件

    include
  • 从一到无穷大

    这本书一开始讲数学 后来讲到4围空间 空间压缩 相对论就头疼了 本不想读下去了 后来硬着头皮往下读 发现后面章节讲解生物 化学 天文等等 哈哈 原来是本科普的读物 大概都知道一些 不错 推荐给初高中生来看一看 2013 12 07
  • Linux内核之softirq机制

    中断的上半部执行紧要的任务 下半部则可以处理数据等次要的任务 tasklet也是基于softirq实现的 不同于tasklet的是 softirq是kernel编译时静态分配的 所以如果动态创建softirq或者kill softirqs
  • java 加密知识整理(未完)

    以下为网络转载 如有侵权请告知以便改正 JKS JCEKS PKCS12 BKS UBER 转一篇文章 http hi baidu com beyond456 blog item a3a009d7479b44d9a044df32 html
  • 计算机网络自顶向下WireShark实验:IP

    前言 计算机网络自顶向下WireShark实验记录 可供参考 题目 1 Select the first ICMP Echo Request message sent by your computer and expandthe Inter
  • 第二十六篇 DenseNet实战

    文章目录 摘要 1 项目结构 2 划分训练集和测试集 3 计算mean和Standard 3 1 标准化的作用 3 2 归一化的作用 4 Mixup CutMix CutOut数据集增强 5 训练
  • Windows应用-C#使用命令行执行PowerShell脚本

    前言 类似于bat脚本 能够自动执行一些任务 但是对bat不熟悉 因此选择使用C 来实现 具体是能够通过执行特定的语句实现对文件的读写与执行 代码 using System using System Collections Generic
  • 排序算法-堆排序

    思路 堆排序 Heapsort 是指利用堆积树 堆 这种数据结构所设计的一种排序算法 它是选择排序的一种 它是通过堆 来进行选择数据 需要注意的是排升序要建大堆 排降序建小堆 我们先将要排序的数据建成堆 然后通过下图所示的步骤进行排序 特性
  • 调试经验 - Fat文件打开失败的问题

    问题描述 在M7上调试打开SD卡中的某个文件 并读取内容的过程中 发现在SD卡中存在的一个文件firmware bin 通过open接口访问时 出现访问失败的问题 排查过程 发现f open 中传入的open flag为FA READ FA
  • 算法之拓扑关系

    目录 前言 算法解析 Kahn算法 DFS算法 总结 参考资料 前言 如何确定代码源文件的编译依赖关系 我们知道 一个完整的项目往往会包含很多代码源文件 编译器在编译整个项目的时候 需要按照依赖关系 依次编译每个源文件 比如 A cpp 依
  • Nginx动态负载均衡

    Nginx一般作为反向代理服务器来实现反向代理来转发处理请求 同时也可以作为静态资源服务器来加快静态资源的获取和处理 1 正向代理与反向代理 正向代理 正向代理 是一个位于客户端和原始服务器之间的服务器 为了从原始服务器取得内容 客户端向代
  • Elasticsearch整合springboot

    Elasticsearch 项目整合 Elasticsearch Rest Client 1 通过 9300 TCP spring data elasticsearch transport api jar springboot版本不同 ra
  • 爬虫学习小结

    前几天学习爬虫 总结如下 目录 一 Request 1 get函数初介绍 2 response 对象 3 Request库异常 4 通用代码框架 5 Request库七个主要方法 6 控制访问参数 二 Robots协议 三 beautifu