上一篇文章中我们了解了关于爬虫的基础知识,那么在这一篇文章中我们来看看如何让程序模仿浏览器获取服务器数据。
在进入爬虫的殿堂之前我们先了解一下网络爬虫道德:尽量放慢你的速度、尽量遵循robots、不要公开你的爬虫源码、不要分享你的爬虫数据。
ok 下面就正式开始我们的学习。
既然要获取服务器数据,没有服务器可不行,我们可以自己弄一个简单的“服务器”,这样学起来会更加透彻。我们可以使用 Flask 写一个简单的 app (或者使用 Django 也可以),生产环境中的服务器一般都是 apache。
首先创建一个虚拟环境,然后建立 Flask 项目,在 app 里面写上下面的代码:
from flask import Flask, request
import os
app = Flask(__name__)
@app.route('/')
def HelloWorld():
print(request.headers)
return '你好!访问成功!'
@app.route('/get')
def getdata1():
print(request.headers)
return request.url
@app.route('/post', methods=['POST'])
def getdata():
username = request.form['name']
userage = request.form['age']
print(request.headers)
return '你好!{}岁的{}!'.format(userage, username)
@app.route('/file', methods=['POST'])
def file():
f = request.files['file']
dir = os.path.abspath(os.path.dirname(__name__))
f.save(os.path.join(dir, f.filename))
return '文件已经成功保存!'+ os.path.join(dir,f.filename)
@app.route('/proxy')
def proxy():
return request.remote_addr # 获取本机 ip
if __name__ == '__main__':
app.run(debug=True)
启动应用,
我们先使用浏览器测试一下,在浏览器里面输入上面的地址就会出现:
这个 ’服务器‘ 是可以在局域网上访问的,公网就不行啦,毕竟没有域名,具体的含义在后面用到的时候再解释吧,我们的重点还是放在爬虫上面。
1. Requests 概述
首先说一下网页爬虫的整个思路方法:
- 先爬取整个网页,也就是将网页的源代码给获取下来
- 爬取下来的网页再通过文本解析提取,找到我们需要的信息,可以是图片或者文字
以上基本就是爬虫的思路步骤了,非常的简单,简化成了两条,今天要讲的这个requests就是来完成第一步的。
requests是python的一个HTTP客户端库,非常非常的简单易学。
在说起 Requests 之前呢,我们不得不提一下 urllib3 库,它是 python 的内置模块,urllib3 提供了一系列用于操作 URL 的功能。其实 Requests 的底层就是 urllib3 但是因为它过于底层了,直接使用它会比较繁琐,所以人们开发了 request ,当然简洁的代价就是我们可以直接操纵的东西变少了。
在 requests 库中文文档 中提到
所以我们就先使用这个库进行我们的学习啦。
request 一共有七个方法,除一个通用的方法外剩下的六个分别对应六种请求。我们主要关注 GET 请求和 POST 请求。如果不了解这两个请求可以看一下这篇文章。
2. 基本的 GET 请求
首先使用 response = requests.get(url)
或者 response = requests('get', url)
创建一个 response 对象,response 有一些常用的方法:
方法 | 描述 |
---|---|
response.text | 获取 str 类型的响应(一般来说就是相应网站的 html 文件) |
response.content | 获取 bytes 类型的响应 |
response.staus_code | 获取状态码 |
response.headers | 获取响应头 |
response.request | 获取响应对应的请求 |
例如我们使用 requests 对 http://www.baidu.com 进行访问。
import requests
resp = requests.get('http://www.baidu.com')
print(resp)
# <Response [200]>
# 也可以这么写
response = requests.request("get", "http://www.baidu.com")
print(response)
# <Response [200]>
print(response.status_code)
# 200
print(response.text)
# <!DOCTYPE html><!--STATUS OK--><html> <head><meta ...
print(type(response.text))
# <class 'str'>
print(response.cookies)
# <RequestsCookieJar[<Cookie BDORZ=27315 for .baidu.com/>]>
在往下继续之前呢我们需要注意一下:response.text
和 response.content
的区别:
- response.text
- 类型:str
- 解码类型:根据 HTTP 头部对响应的编码推测的文本编码
- 如何修改编码方式:
response.encoding="gbk"
- response.content
- 类型:bytes
- 解码类型:没有指定
- 如何修改编码方式:
response.content.decode("utf8")
因为保存文件的时候我们也需要使用二进制传输,所以一般 response.content
用在需要保存的场合。
3. 添加 headers (headers 参数)
请求带上 header 可以模拟浏览器,欺骗服务器,获取和浏览器一致的内容,我们先来看一下不加 header 服务器看到的效果:
r = requests.get('http://127.0.0.1:5000/get')
print(r.text)
Host: 127.0.0.1:5000
User-Agent: python-requests/2.22.0
Accept-Encoding: gzip, deflate
Accept: */*
Connection: keep-alive
直接暴露自己是爬虫,有很多不欢迎爬虫的网站,那么我们就无法请求到它的数据。比如说知乎网,我们稍后再说它的例子。
另外加请求头还有一个好处,就是可以很大程度上避免动态加载,这对编写爬虫的我们来说省了很多事。如果你了解 JavaScript 你就知道,在之前的一段时间,JavaScript 被滥用了,这导致很多人禁止它的加载,另外还有很多低版本浏览器的使用者。网站编写者为了照顾这些人,一般对于不能加载 JS 的浏览器都有一个“备用网页”。所以如果我们使用一个低版本浏览器的请求头就可以避免动态加载(当然这是在它有备用网页的情况下)
我们来看一下怎么加请求头:
请求头使用的数据结构是字典,在requests.get
中的参数是 headers
。
我们可以像这样添加 headers:
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36
(KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"}
# 用法:
requests.get(url,headers=headers)
我们可以右键检查,点击下面三个按钮,刷新,找到自己浏览器的 User-Agent 。
我们再次访问我们的服务器试试:
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36'
}
r = requests.get('http://127.0.0.1:5000/', headers=headers)
print(r.text)
Host: 127.0.0.1:5000
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36
Accept-Encoding: gzip, deflate
Accept: */*
Connection: keep-alive
下面我们访问一下知乎试试:首先不添加 headers,然后添加上 headers
import requests
url = 'https://www.zhihu.com'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36'
}
r = requests.get(url)
print(r.status_code)
# 400 访问失败
r = requests.get(url, headers=headers)
print(r.status_code)
# 200 访问成功
伪装成功。
4. 发送带有查询参数的请求(params 参数)
我们知道 GET 请求也可以提交参数,get 方式在 url 后面拼接参数,类似于这种:
https://www.baidu.com/s?wd=python&c=b 问号后面的就是参数,
发送带有参数的请求有两种方式,第一种是直接写在 url 里面:
import requests
url = 'http://127.0.0.1:5000/get?name=zhangsan&age=22'
r = requests.get(url)
print(r.text)
# {"age":"22","name":"zhangsan"}
第二种是将 data 写在 一个字典里面,然后传递给参数 params。
data = {
"name":"zhangsan",
"age":20
}
# r = requests.get('https://httpbin.org/get', params=data)
r = requests.get('http://127.0.0.1:5000/get', params=data)
print(r.text)
# {"age":"20","name":"zhangsan"}
Ps:如果不想构建服务器可以将此处的 http://127.0.0.1:5000/
替换为https://httpbin.org
但是返回的结果可能略有差异。
5. 使用 IP 代理爬虫(proxy 参数)
IP代理也就是代理服务器,其功能主要就是代理网络用户去获取网络信息,形象的说就是网络信息的中转站。
为什么爬虫需要使用代理?
- 让目标服务器以为不是同一个客户端在请求,放置因为ip发送请求过多而被反爬
-
防止我们的真实地址被泄露,防止被追究
我们可以在一些免费代理网站上,比如https://www.kuaidaili.com/free/上面找到免费的 ip。
下面是一个使用代理的实例:
proxies = {
"http":'218.95.50.108',
}
r = requests.get('https://httpbin.org/ip', proxies=proxies)
print(r.text)
# {"origin": "120.6.172.142, 120.6.172.142"}
我们使用的是一个高匿名的 ip 代理,所以返回的 ip 跟我们设置的不一样。
如果我们使用的是一个付费代理,那么我们这一这样写:'http':'http://user:pwd@115.223.200.85:9000'
。
6. 设置相应时间
最后说一个简单是知识点~语法如下: response = requests.get(url,timeout=3)
单位是秒
好吧文章已经很长啦,POST 只好放到下一篇里啦
全文over