python爬虫需要哪些基础知识-【PYTHON】【爬虫】关于python爬虫的一些基础知识

2023-11-02

基础知识

HTTP协议

我们浏览网页的浏览器和手机应用客户端与服务器通信几乎都是基于HTTP协议,而爬虫可以看作是一个另类的客户端,它把自己伪装成浏览器或者手机应用客户端,按照自己的逻辑贪婪的向服务器索取数据,如何向服务器索取数据,所以了解HTTP协议就显得很有必要了。

HTTP协议中文名称是超文本传输协议,是一个基于请求与响应模式的、无状态的、应用层的协议,常基于TCP的连接方式。请求和响应模式很好理解,客户端发送请求,服务器响应客户端的请求,就像学校食堂打菜一样,你和打菜阿姨说要哪份菜,她才会给你盛哪份菜。

351541-20200616155140511-781424114.png

无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。形象点说,可以把服务器看成是没有记忆的大学食堂打饭打菜,在每次请求中,阿姨并不知道你之前有没有打过菜,也不知道你是不是合法的学生,所以你只能一边举着学生证一边和阿姨说我要这个菜,阿姨看到你的学生证后才会给你打菜,而这个学生证就是你每次需要重传的数据信息。

当我们在浏览器地址栏中输入http://www.bilibili.com 并敲入回车后,浏览器会构造HTTP请求发送到服务器,在收到服务器的HTTP响应后,浏览器会解析页面,继续向服务器请求图片、视频、js脚本等数据,直到页面加载完成,最终展示给我们的就是B站主页了。这是我用Fiddler抓的包,展示的是HTTP最原生的面貌,接下来我就根据这张图具体的讲解HTTP协议,以及写爬虫需要关注的一些点。

1240

HTTP请求由三部分组成,分别是: 请求行、消息报头、请求正文。 在接收和解释请求消息后,服务器返回一个HTTP响应消息,HTTP响应也是由三个部分组成,分别是:状态行、消息报头、响应正文。

HTTP方法

HTTP请求的请求行以一个方法符号开头,以空格分开,后面跟着请求的URI和协议的版本。请求方法都是大写,有很多种,常见的有GET POST DELETE PUT,各种方法之间的区别不大。

351541-20200616155159135-217940286.png

这里罗列了一些常用的方法,一般来讲,GET表示向服务器请求URI对应的资源,POST表示向服务器提交数据,DELETE表示删除数据,PUT表示修改数据。但这都是一种约定,没有强制的要求,如果你碰见用DELETE方法提交数据也没必要大惊小怪。在实际写爬虫的过程中,我们只需要按照抓包请求构造数据即可,没有必要在意用了什么方法。

报头字段

重点讲解几个写爬虫需要关注的字段

User-Agent 出现在请求报头中,表示客户端的操作系统、浏览器型号版本等信息。服务器可以根据此报头向客户端返回不同的页面以适应客户端。有些网站(知乎)会校验此报头,不填写或者不主流的报头都不能拿到正常的页面。因此自己在写爬虫的时候最好将从浏览器中拷贝到代码中。

Cookie 出现在请求抱头中,前面我们说过HTTP是基于请求与响应模式并且无状态的协议,之前举了打菜阿姨的例子,Cookie就相当于每次请求中的学生证,它可以记录用户的身份信息。当我们自己写爬虫的时候,如果需要登陆,并且登陆又有验证码或者短信验证时,最简单的方法就是从浏览器中把cookie拷贝到爬虫中,就可以骗过服务器了。

Set-Cookie 出现在响应抱头中,让客户端更新页面关联的Cookie,还是拿食堂阿姨的例子,如果你的响应报头有这个字段,意思就是阿姨重新给你了一个学生证,下次打饭你得用最新的学生证,原来的学生证不好使。如果你在模拟浏览器或者客户端登陆,需要将此报头更新已有的Cookie,不过Scrapy和requests都可以自动更新,因此不需要你再手动设置。

Content-Type 标明请求正文或者响应正文的格式,客户端或者服务器会根据此字段选择合适的方式解析正文内容,以下是一些常见的值

1240

Content-Length 标明请求正文或者响应正文的长度,在使用requests构造请求的时候,我们不需要显式的加上此字段,requests会根据请求正文自动计算添加。

Content-Encoding 在某些情况下,正文会讲过压缩后传输,此字段会指明压缩的类型(gzip和压缩参数)

Transfer-Encoding 如果正文内容过长,HTTP协议允许将此字段设置为chunked,然后分块传输响应正文

Connection 在HTTP1.1之前的版本,不支持持久连接,所谓的持久链接意思就是:HTTP协议一般通过TCP协议实现,客户端和服务器经过TCP三次握手建立连接,在请求和响应结束之后,此连接继续保持,当之后还有请求的时候,就不需要重新通过三次握手再建立连接,这样可以极大的降低客户端和服务器的IO负载。

在自己写爬虫的时候,我们可以根据浏览器的抓包数据有选择的添加一些请求报头,其实大部分情况下都可以直接使用浏览器中的请求头,为了避免不必要的麻烦,尽可能像的模仿浏览器总是没有错的。

响应码

响应消息的第一行的状态行包括HTTP的协议版本、状态码、状态码含义。按照约定

2xx表示请求成功

3xx表示重定向

4xx表示客户端错误(403 Forbiden 404 Not Found)

5xx表示服务器错误(502 网关错误)

更多HTTP参考:

爬虫开发

一般来说开发爬虫的过程是这样的

抓包分析获取数据的URL

通过python从上一步的URL获取数据

从上一步获取的HTML页面或者JSON数据中解析出感兴趣的数据

存储数据

下面就讲解这四个关键点

抓包发包工具

写爬虫的第一步就是分析想要的数据浏览器是通过什么URL拿到的,抓包也就在所难免。最好用的抓包工具当然是谷歌浏览器了,右键检查,选中网络,重新刷新页面就可以看到加载此网页所有的HTTP请求了,如果此链接有跳转地址,跳转之前的HTTP请求会被清掉,所以记得选上preserve log,尤其是登陆的时候,一般都会有跳转。

351541-20200616155226936-529948817.png

再介绍另外两个HTTP抓包工具——Fiddler和Charles,分别在windows和macos使用。它们可以为我们展示更多HTTP的细节,将请求和响应都调至Raw模式下,我们就可以一睹HTTP请求和响应的真实面貌。

通过抓包分析出具体的URL后,想进一步确认自己构造的参数和报头能否正确获取到数据,应该怎么做呢?不怕,postman可以帮你,你可以很轻松的选择方法,定义header,添加各种类型的body。

351541-20200616155240425-762375768.png

python请求数据

讲完了基本的HTTP协议知识后,大家可能会疑问那我该如何模仿浏览器或者手机客户端去向服务器发送HTTP请求呢?python的原生库urllib、第三方库requests、pycurl等都支持HTTP协议,既然有这么多工具可以用,大家可能就又有疑问该选择哪个工具了。在此我特地安利大家用一下requests,它让爬虫变得如此简单,让你再也不用为字符编码、重定向、cookie、响应解压缩烦恼了。如果你坚持用原生的库,那么有以下问题需要你一一解决,这些都是当年自己趟过的坑,绝非危言耸听。

需要自己判断服务器返回数据的编码格式,如果这个地方你不能正确判断,那恭喜你之后的每一步,你都必须面对乱码的问题

重定向,urllib不能自动判断重定向,需要自己解析重定向的链接并重新请求

如果模拟登陆,你必须要手动保证Cookie正确更新和发送

很多情况下响应正文是压缩过的,需要做解压处理

对于比较长的响应正文,服务器会将正文分段传输,所以还需要你做拼接操作

原生的urllib对HTTPS和持久连接都支持不好

当你花了一整天,写了好几百行的代码终于解决上面的问题后,而你旁边的同事可能早已经把数据下载完并愉快的约妹子去了。所以用requests吧,兄弟们用了都说好。下面我用两个例子讲解一下如何用requests获取想要的数据,并教你如何解决这些问题:

如何发送不同方法的请求

如何保存cookie

如何添加代理

如何处理编码问题

B站

假如我想下载B站里面某位小姐姐所有上传的视频,应该怎么办呢?首先你需要找到这位小姐姐的视频主页

1240

但是通过谷歌浏览器右键查看页面源码,没有从html中找到这些视频的播放信息,唯一的可能就是视频数据是通过js脚本调用服务器获取,然后生成的这张页面。爬虫小白可能会疑问,难道我需要像浏览器一样分析js脚本,然后模拟js执行吗?其实不用这么复杂,只需要简单的分析抓包结构,就可以找到请求URL了。

351541-20200616155321709-258536654.png

那么问题又来了,这个URL的其他参数是干啥的呢?凭经验,mid肯定是这位小姐姐的用户id,page和pagesize是负责分页用的,keyword和是用来搜索的关键字,order是排序选项,剩下的tid是干啥的呢?其实写爬虫很多时候都会遇到这种问题,不知道某个参数的含义,也不确定正确的取值范围,需要一些尝试和运气,这里我们不管它就好。而返回的字段中有一个aid,那肯定是视频的id,有这个就可以自己拼接出播放链接了。

351541-20200616155337841-391436967.png

是不是很简单,通过response.ok查看请求是否正确返回,因为此接口的数据为json格式,直接通过response.json()就可以直接拿到格式化的数据。

知乎

虽然现在知乎对未登录用户展示的内容越来越多,但是仍会有一些限制,用爬虫模拟登陆可以之后再去爬取数据,可以避免很多不必要的麻烦,现在就讲一讲如何用requests模拟用户登陆。

还是和之前一样,在登陆页面打开谷歌浏览器的抓包窗口,输入用户名和密码点击确定,然后在茫茫请求中找到发送登陆信息的那个HTTP请求即可,功夫不负有心人,我们终于找到了登陆的请求。

351541-20200616155423122-1842812808.png

等等,请求里面还有一个_xsrf,这是一个什么鬼参数,其实呢这是一个防止跨站请求伪造而生成的一个随机数,可以通过解析https://www.zhihu.com/#signin 页面获取,这一部分我在下面会讲解如何HTML获取数据,现在假设我们已经拿到这个数据了,如何将用户名和密码登陆呢?

351541-20200616155438084-1093673215.png

如果我们想要自动保存Cookie信息,只需要生成一个Session对象,之后所有的请求通过此对象完成,requests会像浏览器一样自动更新cookie信息,并在每次请求的时候加上cookie,因此在成功的发送post登陆请求之后,就可以用session在保持登陆状态请求数据了。需要注意的是在请求的时候我特意去掉了Cookie和Content-Length报头,因为requests会自动加上,所以不需要我们特意关注。

更多关于requests的使用可以查看官方文档:

python解析数据

因为个人在解析数据的时候遇到过很多编码的坑,所以在继续讲解之前告诉大家一些如何避免编码问题的方法。python2中有两种字符串:unicode和str,它们分别对应python3中的str和bytes。如何定义这两种类型的变量在下图中给大家列出来了。

1240

以python3为例讲解这两种类型的区别。python3中的str每一个字符可以存储一个英文字母、一个汉字甚至一个emoji表情,它可以通过特定的编码方式,例如utf-8或者gbk生成bytes,在不同的编码格式下,可能需要2-3个字符常能表示一个汉字。bytes可以指定解码格式解码生成str,如果指定的解码格式不匹配,就会导致乱码问题。为了避免乱码问题,最好的方式就是使用str,等到需要写入文件或者数据库的时候,再指定写入的编码格式,用好这个准则,我们可以避免百分之九十的编码问题。

HTTP响应的数据格式有很多,例如文本、json、html,对应的解析方式也很多。通用一点,用python内置库正则匹配找到想要的数据,但是这种方法相对来说比较麻烦,而且不好维护,比较适合文本类型的数据,但HTTP响应正文基本都是json和HTML,这种方式适用面比较窄。

当请求的数据是json格式时,我们可以很方便的用requests反序列化返回内容,取出感兴趣的数据。但是当HTTP返回的数据是html的时候,我们该如何操作,就像刚才知乎登陆的例子中,如何快速从html中解析想要的数据呢?

专门用来解析html的第三方库有很多,例如beautifulsoup、pyquery。个人推荐使用pyquery,因为它可以使用jquery的方式选取元素,而且支持xpath,以后上手scrapy会很容易。继续上面登陆知乎的例子,登陆时需要的_xsrf实际上在 https://www.zhihu.com/#signin 页面里面,只要先请求到这个页面,然后解析出_xsrf,配合之前的登陆请求,我们就可以完整的实现用python模拟浏览器登陆知乎了。

1240

1240

使用起来是不是相当的简单,我们只要通过谷歌浏览器找到对应DOM元素,根据属性名就可以非常快速的找到想要的数据。需要注意的是response.content和response.text,这都是返回的body正文,但是前者是bytes,后者是str,requests已经帮助我们把响应正文按照正确的编码格式进行了解码,根据我们之前的阐述的原则,尽量使用str,所以26这个地方我用的是response.text。

存储数据

根据数据量的不同以及数据类型的不同,数据的存储选择也很多。如果爬取的是图片、音频、视频等多媒体文件,直接按照文件形式存储就好了。如果是一些文本,数字等数据,一般有这么几种选择:

输出到屏幕

写入文件(txt csv)

写入数据库 (mysql sqlite mongo)

如果数据量非常小,可以选择直接输出到屏幕(这种情况貌似也不需要爬虫),因为终端存储的数据量很少,而且因为没有持久化,关闭窗口就意味着数据丢失,不建议使用。

在数据量小且不愿意折腾数据库的情况下,可以把爬取的数据写入文件,但是这种情况不能随取随用,也不方便做数据分析,需要手动处理。

当数据量较多,而且需要快捷的分析数据,推荐使用数据库存储数据,大型的数据库mysql, mongo功能齐全,可以分方便的进行数据分析,而且也很容易实现分布式扩展,当你需要多进程甚至多机器运行爬虫的时候,这些数据库可能是最好的选择。sqlite相对来说功能要少很多,python原生支持,依赖少,数据量不算太大的情况下可以考虑使用。

因为这部分内容太多太深,感兴趣的童鞋如果想深入了解一些,这里列出一些文档供大家参考:

爬虫示例

下面给出一个简单的例子,为大家展示如何使用上述python库实现一个完整的爬虫。一些热门的知乎话题最多有1000条精华回答,这个例子就是爬取这些精品答案。图示页面就是回答列表,每页有二十个答案,最多有五十页。但是此页面没有完整的回答信息,需要通过显示全部对应的链接进入回答详情页才能获取完整的答案,所以我们的爬虫策略就是通过回答列表找到所有精华回答链接,再通过回答链接获取内容。而且这些页面不需要登陆也能访问,因此可以省去模拟登陆。

1240

开发环境

python是跨平台语言,但不同平台不同版本的python略微有一些差异,考虑到大家使用windows平台的较多,我在windows和ubuntu的python3.5验证过此代码,其他平台和其他python版本下可能需要做一些修改。集成开发环境推荐使用Pycharm,这是一个跨平台良心IDE,各大操作系统下都有免费的社区版本可以下载。

运行代码

代码链接

安装依赖库:

pip install requests pyquery SQLAlchemy

运行代码:

python scrawl.py

代码解释

因为数据量不大,采用sqlite存储,可以很方便的用命令行或者桌面客户端查看数据。

1240

反爬虫策略和应对方式

稍微大一些的网站都会有一些反爬虫策略,简单一点的根据User-Agent过滤,例如知乎,我们只需要设置为和浏览器相同即可。复杂一点的会限制非登陆用户,也只需要按照之前例子中的方式登陆,或者干脆先用浏览器登陆好,然后在第一次访问的时候带上浏览器中的cookie就好,实现起来难度不大。但是有不少网站,例如豆瓣和github,在检测到某一客户端频繁访问后,会直接封锁ip,这个问题解决起来就相当的棘手和蛋疼了。

解决方法也挺简单,我们只需要找到足够多的代理ip就可以了,只要策略得当,短时间内不要过度频繁的使用同一ip代码,或者当某一ip地址被封锁后马上切换到其他的ip代理,这样就可以保证高效的爬取数据了。那如何找到代理ip并且如何使用了,其实免费的代理ip很多,我们用百度搜索代理ip就可以找到很多网站,例如:http://www.ip181.com/。

351541-20200616155508645-384015512.png

1240

找到代理ip后,就可以用上面的方式很轻松的使用代理ip了,但是网上免费的代理ip质量不好,很多不可用,而且速度慢、不稳定,请求的时候最好设置一下超时时间。我之前在爬github的时候,会专门写一个爬虫从这些网站搜集代理ip地址,一旦检测到被github封锁,就随机选取一个代理ip使用,如果发现代理ip不可用,不断的更换知道可用的代理ip为止,每个代理ip使用的次数也会有一定的限制,保证爬虫在整个执行期间不会因为ip封锁而不可用。

异常及性能

曾经我遇到过这样的状态,写好并运行爬虫一个小时之后,因为网络抖动或者某一种特殊的页面导致解析失败,整个爬虫运行终止,这就蛋疼了。如果日志打印不充分,我连运行失败的原因都清楚,更别说修复问题,即使修复好重新运行,又要花一个小时才能到刚才的进度,费时费力。

爬虫出现异常的情况实在是太多:网络抖动、解析页面失败、反爬虫被屏蔽、写入数据异常、代码逻辑错误等等都会导致进程终止,而一般爬虫需要数小时甚至数天数周的运行,每一次的运行失败都是时间巨大的浪费。因此一定需要在可能出现异常的地方接住异常,保证爬虫不会终止,并记录日志,这些错误日志不仅可以快速的帮助我们定位错误,在出错不多的情况下,我们甚至不需要修改代码重新运行,只需要人肉补全这些数据就好。

如果发现自己的爬虫运行效率太低,爬取速度太慢,并发对于提升爬虫速度是一个不错解决方案,因为GIL的存在,多进程并发模式对于python提速更优,我们可以使用生产者消费者的模式将爬虫任务进行拆分,从而实现多进程或者分布式。一般来说可以将HTTP请求的数据、解析数据、存储数据分别用不同的进程实现,这些进程之间通过消息队列进行通信,保证每个进程无状态,就可以非常容易的实现多进程扩展。即使某一类进程出现异常,也不需要重新启动所有的进程,只需要修复好代码重新启动,就可以实现断点续爬了。

一些常用的分布式工具:redis、rabbitmq、scrapy、celery、you-get

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

python爬虫需要哪些基础知识-【PYTHON】【爬虫】关于python爬虫的一些基础知识 的相关文章

随机推荐

  • MyBatis-Plus——代码自动生成器

    哈喽 大家好 我是 一位上进心十足的 Java领域博主 的写作风格 喜欢用 通俗易懂 的文笔去讲解每一个知识点 而不喜欢用 高大上 的官方陈述 博客的领域是 面向后端技术 的学习 未来会持续更新更多的 后端技术 以及 学习心得 如果有对 后
  • Cesium中文教程-Cesium Workshop(一)

    欢迎来到Cesium社区 非常高兴能加入我们 为了帮助您开发自己的web地图应用程序 本教程将从头到尾介绍如何开发一款简单但有广泛影响的Cesium应用程序 本教程将接触到许多CesiumJS API重要的方面 但这并不意味着包括所有 Ce
  • openLDAP安装卸载与重装

    安装卸载 安装与卸载点击跳转 openLDAP与phpldapadmin安装点击跳转 重装问题 点击跳转
  • 基于SpringBoot工程开发Docker化微服务

    目录 1 微服务容器化治理的优缺点 1 1 微服务容器化的优点 1 2 微服务容器化的缺点 2 微服务的两种模式 2 1 Microservice SDK 2 2 ServiceMesh 3 微服务容器化治理的推荐模式 4 Windows下
  • 湖南省副省长秦国文一行调研考察亚信科技

    9月5日 湖南省人民政府党组成员 副省长秦国文一行到亚信科技调研考察 亚信科技高级副总裁陈武主持接待 图 双方合影 在亚信科技创新展示中心 秦国文了解了亚信科技在5G 算力网络 人工智能 大数据等前沿领域的创新探索 在数字化运营 智慧城市
  • 使用java API操作hdfs--读取hdfs文件并打印

    在myclass之中创建类文件 这个myclass目录是自己创建的 编译的时候会报如下的错误 很明显就是没有导入包的结果 见这个API网站 则可以找到响应的包 当然还有java的api文档 http hadoop apache org do
  • Java程序Png图片保持透明度处理

    核心代码 import javax imageio ImageIO import java awt import java awt image BufferedImage import java io File import java io
  • Springboot调整接口响应返回时长(解决响应超时问题)

    Springboot调整接口 会话响应返回时长 解决响应超时问题 配置Http会话超时 可以通过两种方式为Spring Boot应用程序配置HTTP会话超时 application properties中配置会话超时 最简单的方法是在你的a
  • 在互联网上,没有人知道你是一条狗?

    1993 年 纽约客 The New Yorker 杂志刊登一则由彼得 施泰纳 Peter Steiner 创作的漫画 标题是 On the Internet nobody knows you re a dog 这则漫画中有两只狗 一只黑狗
  • 【C语言】通讯录实现以及信息保存至文件。

    实现一个通讯录 通讯录用来存放1000个人的信息 每个人的信息包括 姓名 性别 年龄 电话 住址 提供方法 1 添加联系人信息 2 删除指定联系人信息 3 查找指定联系人的信息 4 修改指定联系人信息 5 显示所有联系人信息 6 清空所有联
  • c++内存分区模型

    程序在运行的过程中是会被加载到内存中的 一个程序可能会执行可能会存在不同的功能块 所以不同区域存放的数据 赋予不同的生命周期 给我们更大的灵活编程 C 的程序会在内存中分为四大块 代码区 存放函数体的二进制代码 由操作系统进行管理的 全局区
  • vue在created调用点击方法_vue.js中created方法的使用详解

    这次给大家带来vue js中created方法的使用详解 使用vue js中created方法的注意事项有哪些 下面就是实战案例 一起来看一下 这是它的一个生命周期钩子函数 就是一个vue实例被生成后调用这个函数 一个vue实例被生成后还要
  • 什么是公有IP地址?什么是私有IP地址?及各自范围介绍

    什么是公有IP地址 公网IP 组建一个企业级网络 需要去向 电信运营商ISP 申请一个接入Internet的宽带 同时ISP还会给我们分配一个或多个IP地址 这些IP地址可以供我们企业内部上网 这些ISP分配给我们的IP 就是公有IP 公有
  • 柯里化的两种实现方式(定参和不定参)

    1 函数柯里化简介 函数柯里化是指把接收多个参数的函数转换为接受单一参数的函数 并返回接收剩下参数的新函数的技术 通俗点说 就是将多元函数转化为多个单元函数的连续定义 这里的元代指参数 也就说函数柯里化可以把f a b c 这样的多参的函数
  • Freebsd系统ssh登陆配置

    FreeBSD SSH配置详解 默认情况下freebsd下的ssh服务是未被开启的 需要 首先vi编辑 etc inetd conf 去掉ssh前的 保存退出 开启 ssh服务 修改freebsd可以用sshd权限用户登录ssh 但不能用r
  • JPA学习笔记 - 关联关系

    OneToMany 指定 1对多 的映射关系 可通过fetch的属性设置加载方式 JoinColmn 指定外键的列名 外键存在于 多 的一方表中 单向 n 1 先保存n的一端时 会多出update语句 因为插入n端时并未知道外键的值 插入1
  • java8 新特性stream流学习

    简介 java 8 API添加了一个新的抽象称为流Stream 可以让你以一种声明的方式处理数据 Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象 Stream API可以
  • 离散数学-二元关系

    目录 序偶与有序n元组 集合的笛卡尔积 关系的基本概念 关系的表示方法 特殊关系 关系的性质 自反性 反自反性 对称性 反对称性 传递性 关系的复合运算 1 基本概念 2 计算方法 2 1 有向图法 2 2 枚举法 2 3 谓词公式法 3
  • 微信小程序实现文字随机颜色

    1 实现效果 2 实现思路 从颜色列表中随机取一个颜色 赋值给数组的每一项 Math floor Math random colorArr length 3 实现代码
  • python爬虫需要哪些基础知识-【PYTHON】【爬虫】关于python爬虫的一些基础知识

    基础知识 HTTP协议 我们浏览网页的浏览器和手机应用客户端与服务器通信几乎都是基于HTTP协议 而爬虫可以看作是一个另类的客户端 它把自己伪装成浏览器或者手机应用客户端 按照自己的逻辑贪婪的向服务器索取数据 如何向服务器索取数据 所以了解