前言
我一个寒假没有写爬虫都快忘记怎么写了连BS4都不会用了
所以写一个教程,随便复习一下网络爬虫的基本知识
【你不是在1-25还在用爬虫爬本子嘛?还把C盘装满了来着】
【都说了多少遍了不要问这个问题.......又不是我自己写的......】
正文
emmmmm先来讲讲是市面上主流的几种获取网络信息的方法
获取网络数据,其实就是所谓的“爬取”,一般分为两个阶段:
- 爬取数据
- 解析刚刚你爬的那一堆的垃圾
一般你后期解析疯不疯,就看你前期扒拉的怎么样了【惨痛教训】
所以这次我们就先来讲一讲:
扒拉数据的艺术
抓取我们以前常常会采用 urllib这样的一个内建模块 特别是其中的request模块 它可以“方便”的抓取网页的内容【OI选手的自带库肌无力微笑】
这个模块已经逐渐被Requests第三方库替代了【嗷嗷嗷嗷第三方库】
Requests第三方库我们后面会介绍到,它很适合做中小型的网络爬虫的开发
如果要进行大型的网络爬虫的开发 要用到另外一个Scrapy这样一个 非常流行的开源的爬虫框架
【附:如果你真的真的要做大型的爬虫开发的话,有时候还不如用火车头一点一滴扒拉扒拉好,因为网站天天变啊你爬虫要写成什么样子啊啊】
所以,综上所述.....
requests好好好,妙妙妙
这里我们看一下抓取的概念:

1.客户机发送一个请求Request给服务器
2.服务器会返回一个响应Response
然后拿到这个response响应之后,我们需要对此进行解析
现在流行的解析工具有BeautifulSoup库 和正则表达式模块 这些我后面都会做一些介绍
【附:正则表达式我现在都写不好,没有STL差评】
但是你想想,有需求就会有产业
外包公司API应运而生,抓取解析发送一键合成,还不定期更新,就差帮你print到屏幕上面了
啊喂喂跑题了
ok回到重点requests库
requests库
养成好习惯,pip前先看一下官网,很多很多第三方库的官网里面有彩蛋
我为什么说Requests吼,自己去看Requests官网
你看,人家官网都说了Requests是市面上少有的非转基因库
使用纯谷物饲养,天然无公害,一口恢复青春活力【雾】

接下来开始引用官网的内容,随便注释和应用简介一下
如何发送请求
使用 Requests 发送网络请求非常简单。
一开始要导入 Requests 模块:
import requests
然后,尝试获取某个网页。本例子中,我们来获取 Github 的公共时间线:
>>> r = requests.get('https://github.com/timeline.json')
现在,我们有一个名为 r
的 [Response
]
(http://cn.python-requests.org/zh_CN/latest/api.html#requests.Response "requests.Response") 对象。
我们可以从这个对象中获取所有我们想要的信息。
Requests 简便的 API 意味着所有 HTTP 请求类型都是显而易见的。例如,你可以这样发送一个 HTTP POST 请求:
>>> r = requests.post("http://httpbin.org/post")
除了post,其他的请求方式也非常简单
>>> r = requests.put("http://httpbin.org/put")
>>> r = requests.delete("http://httpbin.org/delete")
>>> r = requests.head("http://httpbin.org/get")
>>> r = requests.options("http://httpbin.org/get")
虽然这只是冰山一角,但是你会使用到的也就这么多了哈哈哈哈【嘲讽
现在我们来使用python+requests获取我博客的源代码并print
import requests
r=requests.get('https://0xc000005.github.io/')
print(r.text)
非常简单是不是,而且还帮我自动解析了/n什么都
附:如果出现以下代码,说明你还没有pip,到官网里下载库然后install、
Traceback (most recent call last):
File "/usercode/file.py", line 2, in <module>
import requests
ImportError: No module named requests
传递关键字参数
你也许经常想为 URL 的查询字符串(query string)传递某种数据。
【还记得被不会写查询语句支配过的恐惧吗?】
如果你是手工构建 URL,那么数据会以键/值对的形式置于 URL 中,跟在一个问号的后面。
例如, httpbin.org/get?key=val。
Requests 允许你使用 params 关键字参数,以一个字符串字典来提供这些参数。举例来说,如果你想传递 key1=value1 和 key2=value2 到 httpbin.org/get ,那么你可以使用如下代码:
>>> payload = {'key1': 'value1', 'key2': 'value2'}
>>> r = requests.get("http://httpbin.org/get", params=payload)
#我们打印一下,发现已经被正确编码【真tm牛B】
>>> print(r.url)
http://httpbin.org/get?key2=value2&key1=value1
注意字典里值为 None 的键都不会被添加到 URL 的查询字符串里。
key什么的关键词也不会出现在返回的url里面
解析一下
requests提供了基础解析功能【也许是我不会用】
想刚刚上面的text参数就帮我正确的解析了/n什么都
除了源代码Unicode之类的,text还可以解析js
解析js我的天哪!!!
>>> import requests
>>> r = requests.get('https://github.com/timeline.json')
>>> r.text
u'[{"repository":{"open_issues":0,"url":"https://github.com/...
而且还会帮你写入字典,在前面添加相应的类型名字
Requests 会"自动"解码来自服务器的内容。大多数 unicode 字符集都能被无缝地解码。
请求发出后,Requests 会基于 HTTP 头部对响应的编码作出有根据的推测。当你访问 r.text 之时,Requests 会使用其推测的文本编码。
你可以找出 Requests 使用了什么编码,并且能够使用 r.encoding 属性来改变它:
>>> r.encoding
'utf-8'
>>> r.encoding = 'ISO-8859-1'
如果你改变了编码,每当你访问 r.text ,Request 都将会使用 r.encoding 的新值。你可能希望在使用特殊逻辑计算出文本的编码的情况下来修改编码。比如 HTTP 和 XML 自身可以指定编码。这样的话,你应该使用 r.content 来找到编码,然后设置 r.encoding 为相应的编码。这样就能使用正确的编码解析 r.text 了。
附:请务必记住你转换了什么代码,不然......
JSON获取与解析
>>> import requests
>>> r = requests.get('https://github.com/timeline.json')
>>> r.json()
[{u'repository': {u'open_issues': 0, u'url': 'https://github.com/...
也是自动写入字典的厉害玩意儿
如果 JSON 解码失败, r.json() 就会抛出一个异常。例如,响应内容是 401 (Unauthorized),尝试访问 r.json() 将会抛出 ValueError: No JSON object could be decoded 异常。
需要注意的是,成功调用 r.json() 并不意味着响应的成功。有的服务器会在失败的响应中包含一个 JSON 对象(比如 HTTP 500 的错误细节)。这种 JSON 会被解码返回。要检查请求是否成功,请使用 r.raise_for_status() 或者检查 r.status_code 是否和你的期望相同。
也就是说......用json解析你的代码可能会NE掉
【md用个鸡毛啊】
定制请求头部信息
这个很重要!!
你不能指望所有的网站都有robot.txt有些网站不太友好,他会记录异常的浏览器信息【像爬虫】
然后把你ban掉
所以你要伪造浏览器的头部,有时候还要使用vpn【应该是这样】更换ip防止ban掉什么的
这时候就要用到定制请求头了
>>> url = 'https://api.github.com/some/endpoint'
>>> headers = {'user-agent': 'my-app/0.0.1'}
>>> r = requests.get(url, headers=headers)
注意: 定制 header 的优先级低于某些特定的信息源,
例如:如果在 .netrc 中设置了用户认证信息,
使用 headers= 设置的授权就不会生效。而如果设置了 auth= 参数,.netrc
的设置就无效了。
如果被重定向到别的主机,授权 header 就会被删除。
代理授权 header 会被 URL 中提供的代理身份覆盖掉。
在我们能判断内容长度的情况下,header 的 Content-Length 会被改写。
更进一步讲,Requests 不会基于定制 header 的具体情况改变自己的行为。只不过在最后的请求中,所有的 header 信息都会被传递进去。
注意: 所有的 header 值必须是 string、bytestring 或者 unicode。尽管传递 unicode header 也是允许的,但不建议这样做。
超时
你可以告诉 requests 在经过以 timeout 参数设定的秒数时间之后停止等待响应。基本上所有的生产代码都应该使用这一参数。如果不使用,你的程序可能会永远失去响应【妈妈她在吓人w】
>>> requests.get('http://github.com', timeout=0.001)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
requests.exceptions.Timeout: HTTPConnectionPool(host='github.com', port=80): Request timed out. (timeout=0.001)
真可怕真可怕
错误与异常
遇到网络问题(如:DNS 查询失败、拒绝连接等)时,Requests 会抛出一个 ConnectionError
异常。
如果 HTTP 请求返回了不成功的状态码, Response.raise_for_status()
会抛出一个 HTTPError
异常。
若请求超时,则抛出一个 Timeout
异常。
若请求超过了设定的最大重定向次数,则会抛出一个 TooManyRedirects
异常。
所有Requests显式抛出的异常都继承自 requests.exceptions.RequestException
。
综上所述,你的代码有问题!!
后记
参考资料:
Requests官网
南京大学数据分析与收集
HTTP头部信息大全
网友评论