Python网络爬虫之网络请求

Python网络爬虫之网络请求_第1张图片

学习笔记

一、urllib库

urllib库是Python中一个最基本的网络请求库。可以模拟浏览器的行为,向指定的服务器发送一个请求,并可以保存服务器返回的数据。

1.1 urlopen函数:

在Python3的urllib库中,所有和网络请求相关的方法,都被集到urllib.request模块下面了,以先来看下urlopen函数基本的使用:

from urllib import request
resp = request.urlopen('http://www.baidu.com')
print(resp.read())

实际上,使用浏览器访问百度,右键查看源代码。你会发现,跟我们刚才打印出来的数据是一模一样的。也就是说,上面的三行代码就已经帮我们把百度的首页的全部代码爬下来了。一个基本的url请求对应的python代码真的非常简单。
以下对urlopen函数的进行详细讲解:

  • url:请求的url。
  • data:请求的data,如果设置了这个值,那么将变成post请求。
  • 返回值:返回值是一个http.client.HTTPResponse对象,这个对象是一个类文件句柄对象。有read(size)readlinereadlines以及getcode(返回状态码)等方法。

例如:

  • read(size):
print(resp.read(10))
#输出前10个字符:
b'
  • readline
#输出一行
print(resp.readline())
  • readlines
print(resp.readlines())
#按一行一行格式读取输出
[b'\n', b'\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\t\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\r\n', b'\t\r\n', b'        \r\n', b'\t\t\t        \r\n', b'\t\r\n', b'\t\t\t        \r\n', b'\t\r\n', b'\t\t\t        \r\n', b'\t\r\n', b'\t\t\t        \r\n', b'\t\t\t    \r\n', b'\r\n', b'\t\r\n', b'        \r\n', b'\t\t\t        \r\n', b'\t\r\n', b'\t\t\t        \r\n', b'\t\r\n', b'\t\t\t        \r\n', b'\t\r\n', b'\t\t\t        \r\n', b'\t\t\t    \r\n', b'\r\n', b'\r\n', b'\n', b'\n', b'\n', b'\n', b'\n', b'\n', b'\n', b'\n', b'\n', b'\n', b'\n', b'\n', b'\n', b'\n', b'\n', b'\n', b'\n', b'\n', b'\n', b'\n', b'\n', b'\n', b'\n', b'\n', b'    \n', b'    \n', b'    \n', b'\t\n', b'    \n', b'    \n', b'    \n', b'    \n', b'\t\n', b'\t\n', b'\t\n', b'\t\n', b'\t\n', b'\t\n', b'\t\n', b'\t\n', b'\t\n', b'\t\n', b'    \n', b'    \xe7\x99\xbe\xe5\xba\xa6\xe4\xb8\x80\xe4\xb8\x8b\xef\xbc\x8c\xe4\xbd\xa0\xe5\xb0\xb1\xe7\x9f\xa5\xe9\x81\x93\n', b'    \n', b'\n', b'\n', b'\n', b'\n', b'\n', b'\n', b'\n', b'\n', b'\n', b'    \n', b'\n', b'\n', b'\n', b'\n', b'    \n', b'\n', b'\n', b'\n', b'\t\n', b'    \n', b'    
\n'
, b' \n', b' \n', b' \n', b' \n', b'\n', b'\n', b'\n', b'\n', b'\n', b'\n', b'\n', b'\n', b'\n', b'\n', b'\n', b'\n', b'\n', b'\n', b'\n', b'\n', b'\n', b'\n', b'\n', b'\n', b'\n', b'\n', b'\n', b'\r\n', b'\n', b'\n', b'\r\n']

1.2 urlretrieve函数:

这个函数可以方便的将网页上的一个文件保存到本地。以下代码可以非常方便的将百度的首页下载到本地:

from urllib import request
request.urlretrieve('http://www.baidu.com/','baidu.html')

下载刘亦菲图片:

from urllib import request
request.urlretrieve('https://ss0.baidu.com/6ONWsjip0QIZ8tyhnq/it/u=1970534157,1154154617&fm=58&bpow=1500&bpoh=2164','G:\python\lyf.jpg')

Python网络爬虫之网络请求_第2张图片

1.3 urlencode函数:

用浏览器发送请求的时候,如果url中包含了中文或者其他特殊字符,那么浏览器会自动的给我们进行编码。而如果使用代码发送请求,那么就必须手动的进行编码,这时候就应该使用urlencode函数来实现, 不然会报错,在百度搜索刘德华用程序实现的时候::

from urllib import request
url='http://www.baidu.com/s?wd=刘德华'
resp=request.urlopen(url)
print(resp.read())
//报错:
UnicodeEncodeError: 'ascii' codec can't encode characters in position 10-12: ordinal not in range(128)

urlencode可以把字典数据转换为URL编码的数据。

示例代码如下:

from urllib import parse
data = {'name':'爬虫基础','greet':'hello world','age':100}
qs = parse.urlencode(data)
print(qs)
//结果:
name=%E7%88%AC%E8%99%AB%E5%9F%BA%E7%A1%80&greet=hello+world&age=100

所以,百度搜索刘德华用程序实现为下:

url='http://www.baidu.com/s'
params={"wd":"刘德华"}
qs=parse.urlencode(params)
url=url+"?"+qs
resp=request.urlopen(url)
print(resp.read())

1.4 parse_qs函数:

可以将经过编码后的url参数进行解码。示例代码如下:

from urllib import parse
qs = "name=%E7%88%AC%E8%99%AB%E5%9F%BA%E7%A1%80&greet=hello+world&age=100"
print(parse.parse_qs(qs))
//结果:
{'name': ['爬虫基础'], 'greet': ['hello world'], 'age': ['100']}

1.5 urlparse和urlsplit:

有时候拿到一个url,想要对这个url中的各个组成部分进行分割,那么这时候就可以使用urlparse或者是urlsplit来进行分割。示例代码如下:

from urllib import request,parse
url = 'http://www.baidu.com/s?username=zhiliao'
result = parse.urlsplit(url)
//result = parse.urlparse(url)
print('scheme:',result.scheme)
print('netloc:',result.netloc)
print('path:',result.path)
print('query:',result.query)

urlparseurlsplit基本上是一模一样的。唯一不一样的地方是,urlparse里面多了一个params属性,而urlsplit没有这个params属性。比如有一个url为:url = ‘http://www.baidu.com/s;hello?wd=python&username=abc#1’,
那么urlparse可以获取到hello,而urlsplit不可以获取到。url中的params也用得比较少。

1.6 request.Request类:

对于有一些网站设置了反爬虫机制,你必须去模拟浏览器才能够爬取内容,比如设置User-Agent等,而request.Request类就是干这个的。
比如爬取拉钩网的时候,如果不设置User-Agent,网站会仍会返回信息,但是返回的信息都是没有用的,如下:
Python网络爬虫之网络请求_第3张图片

from urllib import request
url='https://www.lagou.com/jobs/list_python?labelWords=&fromSearch=true&suginput='
resp=request.urlopen(url)
print(resp.read())

需要增加一个User-Agent(还可以加Referer):

from urllib import request
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'
}
req = request.Request("https://www.lagou.com/jobs/list_python?labelWords=&fromSearch=true&suginput=",headers=headers)
resp = request.urlopen(req)
print(resp.read())

这样,我们爬到了搜索python所展示页面的原代码。

1.7 【实战】用Request爬取拉钩网python职位信息

接下来,我们希望爬取拉钩网python职位信息,但是上面的网页原代码里是不包含的,真实链接是这个:
Python网络爬虫之网络请求_第4张图片
好,设置请求头参数User-Agent及Request参数data、method,开始爬取:

from urllib import request,parse
url="https://www.lagou.com/jobs/positionAjax.json?needAddtionalResult=false"
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'
}
data={
    'first':'true',
    'pn':1,
    'kd':'python'
}
req = request.Request(url,headers=headers,data=parse.urlencode(data).encode('utf-8'),method='POST')
resp = request.urlopen(req)
print(resp.read().decode('utf-8'))

然后,拉钩网骗人小伎俩上线,返回结果是:

{"status":false,"msg":"您操作太频繁,请稍后再访问","clientIp":"171.122.52.21","state":2402}

真假?操作太频繁? 稍后再访问? 我们在浏览器刷新网页,一切正常。滚犊子,做人怎么能这么不诚实呢??哦,不不,人家是网站。。拉钩网这个网站的反爬虫真的是做得很“恶心”,很有代表性。当然,上面的数据都很有价值。满满的套路,爬虫小白十有八九是要在这栽跟头的。好,我们继续伪造,将爬虫变得更像浏览器的行为:

from urllib import request,parse
url = "https://www.lagou.com/jobs/positionAjax.json?px=default&city=%E6%9D%AD%E5%B7%9E&needAddtionalResult=false&isSchoolJob=1"
headers = {
    'Accept': 'application/json, text/javascript, */*; q=0.01',
    'Accept-Encoding': 'gzip, deflate, br',
    'Accept-Language': 'zh-CN,zh;q=0.9',
    'Connection': 'keep-alive',
    'Content-Length': '25',
    'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
    'Cookie': '_qddaz=QD.t5tj5h.s1l9y4.jqjn1obk; _ga=GA1.2.789646278.1549946982; _gid=GA1.2.679118403.1549946982; user_trace_token=20190212124942-9ce12cd7-2e81-11e9-816d-5254005c3644; LGUID=20190212124942-9ce13202-2e81-11e9-816d-5254005c3644; JSESSIONID=ABAAABAAAFCAAEGB89E6A7D04545E90940E94B60CC53735; Hm_lvt_4233e74dff0ae5bd0a3d81c6ccf756e6=1549946981,1549961455; LGSID=20190212180525-b775abf8-2ead-11e9-8172-5254005c3644; index_location_city=%E5%8C%97%E4%BA%AC; _gat=1; TG-TRACK-CODE=index_search; X_MIDDLE_TOKEN=23f587d9e90a5402110a3f0db2021a87; LGRID=20190212183330-a3c00e23-2eb1-11e9-8173-5254005c3644; Hm_lpvt_4233e74dff0ae5bd0a3d81c6ccf756e6=1549967608; SEARCH_ID=4d5baaf7c271426999b984ad75077106',
    'Host': 'www.lagou.com',
    'Origin': 'https://www.lagou.com',
    'Referer': 'https://www.lagou.com/jobs/list_python?labelWords=&fromSearch=true&suginput=',
    'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36',
    'X-Anit-Forge-Code': '0',
    'X-Anit-Forge-Token': 'None',
    'X-Requested-With': 'XMLHttpRequest'
}
data={
    'first':'true',
    'pn':1,
    'kd':'python'
}
req = request.Request(url,headers=headers,data=parse.urlencode(data).encode('utf-8'),method='POST')
resp = request.urlopen(req)
print(resp.read().decode('utf-8'))

但是,由于拉钩这个神奇的网站又加强了反爬虫机制,之前设置请求头的方法无效了,又出现了上面的结果:

{"status":false,"msg":"您操作太频繁,请稍后再访问","clientIp":"171.122.52.21","state":2402}

1.8 ProxyHandler处理器(代理设置)

(1) 很多网站会检测某一段时间某个IP的访问次数(通过流量统计,系统日志等),如果访问次数多的不像正常人,它会禁止这个IP的访问。所以我们可以设置一些代理服务器,每隔一段时间换一个代理,就算IP被禁止,依然可以换个IP继续爬取。

(2) 常用的代理有:

  • 西刺免费代理IP:http://www.xicidaili.com/
  • 快代理:http://www.kuaidaili.com/
  • 代理云:http://www.dailiyun.com/

(3) 代理的原理:

在请求目的网站之前,先请求代理服务器,然后让代理服务器去请求目的服务器,代理服务器拿到目的网站的数据后,再转发给我们。

(4) 查看自己电脑的外网IP: https://httpbin.org/ip

(5) 在代码中使用代理:

  • 使用 urllib.request.ProxyHandle ,传入一个代理,这个代理是一个字典,字典的key依赖于代理服务器能够接受的类型,一般是http或者是https,值是ip:port
  • 使用上一步创建的hander,以及request.build_opener,创建一个opener对象。
  • 使用上一步创建的opener,调用opener函数,发起请求

示例代码如下:

from urllib import request
# 这个是没有使用代理的
resp = request.urlopen('http://httpbin.org/get')
print(resp.read().decode("utf-8"))
# 这个是使用了代理的
# 1. 创建一个handler
handler = request.ProxyHandler({"http":"218.66.161.88:31769"})
# 2. 创建一个opener
opener = request.build_opener(handler)
req = request.Request("http://httpbin.org/ip")
resp = opener.open(req)
print(resp.read())  

1.9 什么是cookie:

(1)在网站中,http请求是无状态的。也就是说即使第一次和服务器连接后并且登录成功后,第二次请求服务器依然不能知道当前请求是哪个用户。

cookie的出现就是为了解决这个问题,第一次登录后服务器返回一些数据(cookie)给浏览器,然后浏览器保存在本地,当该用户发送第二次请求的时候,就会自动的把上次请求存储的cookie数据自动的携带给服务器,服务器通过浏览器携带的数据就能判断当前用户是哪个了。

cookie存储的数据量有限,不同的浏览器有不同的存储大小,但一般不超过4KB。因此使用cookie只能存储一些小量的数据。

(2)cookie的格式

Set-Cookie: NAME=VALUE;Expires/Max-age=DATE;Path=PATH;Domain=DOMAIN_NAME;SECURE

(3)参数意义

  • NAME:cookie的名字。
  • VALUE:cookie的值。
  • Expires:cookie的过期时间。
  • Path:cookie作用的路径。
  • Domain:cookie作用的域名。
  • SECURE:是否只在https协议下起作用。

Cookie 是指网站服务器为了辨别用户身份和进行Session跟踪,而储存在用户浏览器上的文本文件,Cookie可以保持登录信息到用户下次与服务器的会话。

这里以人人网为例。人人网中,要访问某个人的主页,必须先登录才能访问,登录说白了就是要有cookie信息。那么如果我们想要用代码的方式访问,就必须要有正确的cookie信息才能访问。在不设置cookie时,爬取到的也是人人网登陆页面url:http://www.renren.com/PLogin.do 的源代码。解决方案有两种,第一种是使用浏览器访问,然后将cookie信息复制下来,放到headers中。示例代码如下:

from urllib import request
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36',
    'Cookie': 'anonymid=js2rxnc1-7yrvle; depovince=GW; _r01_=1; JSESSIONID=abcI5-BoQqVA4cPwBzLJw; ick_login=f491dcf5-ed85-4ff8-b3bf-aadacd9cea5c; ick=a8701f07-365b-4943-90a3-6fb0a679a13f; XNESSESSIONID=abcjGKom6BFNlh2QjHMJw; jebecookies=06def267-6301-49ea-bfc2-60f1e7f5396e|||||; _de=EA5778F44555C091303554EBBEB4676C696BF75400CE19CC; p=09cb4e5c9b155801e1e67b33192b22361; first_login_flag=1; [email protected]; ln_hurl=http://hdn.xnimg.cn/photos/hdn121/20170428/1700/main_nhiB_aebd0000854a1986.jpg; t=e1570da12fd32071e172df5cf9e18d301; societyguester=e1570da12fd32071e172df5cf9e18d301; id=443362311; xnsid=19593a50; springskin=set; jebe_key=1a2c5c42-8189-4e93-883d-39593810caab%7Ca022c303305d1b2ab6b5089643e4b5de%7C1550057917456%7C1%7C1550057914754; vip=1; wp_fold=0; ver=7.0; loginfrom=null'
}
url = 'http://www.renren.com/880151247/profile'
req = request.Request(url,headers=headers)
resp = request.urlopen(req)
with open('renren.html','w',encoding='utf-8') as fp:
    fp.write(resp.read().decode('utf-8'))

将renren.html用浏览器打开,就是大鹏的主页:
Python网络爬虫之网络请求_第5张图片

二、http.cookiejar库

每次在访问需要cookie的页面都要从浏览器中复制cookie比较麻烦。在Python处理Cookie,一般是通过http.cookiejar模块和urllib模块的HTTPCookieProcessor处理器类一起使用。http.cookiejar模块主要作用是提供用于存储cookie的对象。而HTTPCookieProcessor处理器主要作用是处理这些cookie对象,并构建handler对象。

2.1 http.cookiejar模块

该模块主要的类有CookieJarFileCookieJarMozillaCookieJarLWPCookieJar。这四个类的作用分别如下:

  • CookieJar:管理HTTP cookie值、存储HTTP请求生成的cookie、向传出的HTTP请求添加cookie的对象。整个cookie都存储在内存中,对CookieJar实例进行垃圾回收后cookie也将丢失。
  • FileCookieJar (filename,delayload=None,policy=None):从CookieJar派生而来,用来创建FileCookieJar实例,检索cookie信息并将cookie存储到文件中。filename是存储cookie的文件名。delayload为True时支持延迟访问访问文件,即只有在需要时才读取文件或在文件中存储数据。
  • MozillaCookieJar (filename,delayload=None,policy=None):从FileCookieJar派生而来,创建与Mozilla浏览器 cookies.txt兼容的FileCookieJar实例。
  • LWPCookieJar (filename,delayload=None,policy=None):从FileCookieJar派生而来,创建与libwww-perl标准的 Set-Cookie3 文件格式兼容的FileCookieJar实例。

2.2 【实战】使用http.cookiejar库和request.HTTPCookieProcessor模拟登录人人网:

其中,HTTPCookieProcessor和我们上面用到的ProxyHandler是类似的,只是ProxyHandler用来处理代理,HTTPCookieProcessor用来处理cookie。

登录人人网,其中,大鹏董成鹏主页url为:http://www.renren.com/880151247/profile
人人网登陆url为:http://www.renren.com/PLogin.do

利用http.cookiejarrequest.HTTPCookieProcessor登录人人网。相关示例代码如下(说明:其中登陆人人网时的url和参数data用的是改版前的接口,这个不必纠结,邮箱和密码写你自己的):

from urllib import request
from urllib import parse
from http.cookiejar import CookieJar
#大鹏董成鹏主页url为:http://www.renren.com/880151247/profile
#人人网登陆url为:http://www.renren.com/PLogin.do
#1.登陆
#1.1 创建一个cookiejar对象
cookiejar = CookieJar()
#1.2 使用cookiejar创建一个HTTPCookieProcess对象
handler = request.HTTPCookieProcessor(cookiejar)
#1.3 使用上一步创建的handler创建一个opener
opener = request.build_opener(handler)
#1.4 使用opener发送登陆的请求(人人网的邮箱和密码)
headers={
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36'
}
data = {
    'email' :'*******',
    'password' : '******'
}
login_url='http://www.renren.com/PLogin.do'
req = request.Request(login_url,data = parse.urlencode(data).encode('utf-8'),headers=headers)
opener.open(req)
#2. 访问个人主页
dapeng_url = "http://www.renren.com/880151247/profile"
#获取个人主页页面的时候,不要新建一个opener,而应该使用之前的那个opener,
#因为之前的那个opener已经包含了登陆所需要的cookie信息
resp = opener.open(dapeng_url)
with open('renren.html','w',encoding='utf-8') as fp:
    fp.write(resp.read().decode('utf-8'))

整理代码,定义函数,改版为以下代码:

from urllib import request,parse
from http.cookiejar import CookieJar

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36'
}

def get_opener():
    cookiejar = CookieJar()
    handler = request.HTTPCookieProcessor(cookiejar)
    opener = request.build_opener(handler)
    return opener

def login_renren(opener):
    data = {"email": "***********", "password": "*************"}
    data = parse.urlencode(data).encode('utf-8')
    login_url = "http://www.renren.com/PLogin.do"
    req = request.Request(login_url, headers=headers, data=data)
    opener.open(req)

def visit_profile(opener):
    url = 'http://www.renren.com/880151247/profile'
    req = request.Request(url,headers=headers)
    resp = opener.open(req)
    with open('renren.html','w',encoding='utf-8') as fp:
        fp.write(resp.read().decode("utf-8"))

if __name__ == '__main__':
    opener = get_opener()
    login_renren(opener)
    visit_profile(opener)

2.3 保存cookie到本地:

保存cookie到本地,可以使用cookiejar的save方法,并且需要指定一个文件名:

from urllib import request
from http.cookiejar import MozillaCookieJar
cookiejar = MozillaCookieJar("cookie.txt")
handler = request.HTTPCookieProcessor(cookiejar)
opener = request.build_opener(handler)
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36'
}
req = req = request.Request('http://httpbin.org/cookies/set?course=abc',headers=headers)
resp = opener.open(req)
print(resp.read())
cookiejar.save(ignore_discard=True,ignore_expires=True)

结果,cookie.txt文件内容:

# Netscape HTTP Cookie File
# http://curl.haxx.se/rfc/cookie_spec.html
# This is a generated file!  Do not edit.

httpbin.org	FALSE	/	FALSE		course	abc

2.4 从本地加载cookie:

从本地加载cookie,需要使用cookiejar的load方法,并且也需要指定方法:

from urllib import request
from http.cookiejar import MozillaCookieJar
cookiejar = MozillaCookieJar("cookie.txt")
cookiejar.load(ignore_discard=True)
for cookie in cookiejar:
    print(cookie)

结果:

<Cookie course=abc for httpbin.org/>

三、requests库

Requests: 让 HTTP 服务人类。

虽然Python的标准库中 urllib2 模块已经包含了平常我们使用的大多数功能,但是它的 API 使用起来让人感觉不太好,而 Requests 自称 “HTTP for Humans”,说明使用更简洁方便。

Requests 唯一的一个非转基因的 Python HTTP 库,人类可以安全享用:)

Requests 继承了urllib2的所有特性。Requests支持HTTP连接保持和连接池,支持使用cookie保持会话,支持文件上传,支持自动确定响应内容的编码,支持国际化的 URL 和 POST 数据自动编码。

3.1 安装和文档

(1)安装方式:
利用 pip 安装 或者利用 easy_install 都可以完成安装:

  • pip install requests
  • easy_install requests

(2)requests 的底层实现其实就是 urllib3。Requests的文档非常完备,中文文档也相当不错。Requests能完全满足当前网络的需求,支持Python 2.6—3.5,而且能在PyPy下完美运行。

  • 开源地址:https://github.com/kennethreitz/requests
  • 中文文档 API: http://docs.python-requests.org/zh_CN/latest/index.html

警告:非专业使用其他 HTTP 库会导致危险的副作用,包括:安全缺陷症、冗余代码症、重新发明轮子症、啃文档症、抑郁、头疼、甚至死亡。

3.2 发送GET请求

基本GET请求(headers参数 和 parmas参数)
(1) 最基本的GET请求可以直接用get方法
response = requests.get(“http://www.baidu.com/”)

也可以这么写:
response = requests.request(“get”, “http://www.baidu.com/”)

import requests

response = requests.get("http://www.baidu.com/")
#print(type(response.text))
#print(response.text)

print(type(response.content))
print(response.content.decode('utf-8'))

#查看完整url地址
print response.url
 
#查看响应头部字符编码
print response.encoding
 
#查看响应码
print response.status_code

response.textresponse.context的区别

  1. response.context:这个是直接从网络上面抓取的数据,没有经过任何解码,所以是一个bytes类型,其实在硬盘上和网络上的字符串都是bytes类型;
  2. response.text:这个是str的数据类型,是resuests库将response.content进行解码的字符串。解码需要一个编码方式,requests会根据自己的猜测来判断编码的方式。所以有时候可能会猜测错误,就会导致解码产生乱码,这时候应该使用response.content.deconde('utf-8')进行手动解码。

(2) 添加 headers 和 查询参数

如果想添加 headers,可以传入headers参数来增加请求头中的headers信息。如果要将参数放在url中传递,可以利用 params 参数。

import requests

kw = {'wd': '长城'}

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"
}

# params 接收一个字典或者字符串的查询参数,字典类型自动转换为url编码,不需要urlencode()
response = requests.get("http://www.baidu.com/s?", params=kw, headers=headers)

with open('baidu.html','w',encoding='utf-8') as fp:
    fp.write(response.content.decode('utf-8'))

print(response.url)

3.3 发送POST请求

基本POST请求(data参数):

  1. 发送post请求非常简单,直接调用requests.post方法就可以了。如果返回的是json数据,那么可以调用response.jsoon()来将json字符串转化为字典或列表。

  2. 传入data数据
    对于 POST 请求来说,我们一般需要为它增加一些参数。那么最基本的传参方法可以利用 data 这个参数。

import requests
 
formdata = {
    "type":"AUTO",
    "i":"i love python",
    "doctype":"json",
    "xmlVersion":"1.8",
    "keyfrom":"fanyi.web",
    "ue":"UTF-8",
    "action":"FY_BY_ENTER",
    "typoResult":"true"
}
 
url = "http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule&smartresult=ugc&sessionFrom=null"
 
headers={ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36"}
 
response = requests.post(url, data = formdata, headers = headers)
 
print response.text

#如果是json文件可以直接显示
print response.json()
#运行结果

{"type":"EN2ZH_CN","errorCode":0,"elapsedTime":2,"translateResult":[[{"src":"i love python","tgt":"我喜欢python"}]],"smartResult":{"type":1,"entries":["","肆文","高德纳"]}}

{u'errorCode': 0, u'elapsedTime': 0, u'translateResult': [[{u'src': u'i love python', u'tgt': u'\u6211\u559c\u6b22python'}]], u'smartResult': {u'type': 1, u'entries': [u'', u'\u8086\u6587', u'\u9ad8\u5fb7\u7eb3']}, u'type': u'EN2ZH_CN'}

3.4 requests使用代理ip

代理(proxies参数)
如果需要使用代理,你可以通过为任意请求方法提供 proxies 参数来配置单个请求:

import requests
 
#根据协议类型,选择不同的代理
proxies = {
  "http": "http://12.34.56.79:9527",
  "https": "http://12.34.56.79:9527",
}
 
response = requests.get("http://www.baidu.com", proxies = proxies)
print response.text

3.5 Cookies 和 Sission

  1. Cookies
    如果一个响应中包含了cookie,那么我们可以利用 cookie属性拿到这个返回的cookie值:
import requests
response = requests.get('http://www.baidu.com')
print(response.cookies)
print(response.cookies.get_dict())

结果:

<RequestsCookieJar[<Cookie BDORZ=27315 for .baidu.com/>]>
{'BDORZ': '27315'}
  1. session
    在 requests 里,session对象是一个非常常用的对象,这个对象代表一次用户会话:从客户端浏览器连接服务器开始,到客户端浏览器与服务器断开。会话能让我们在跨请求时候保持某些参数,比如在同一个session 实例发出的所有请求之间保持 cookie 。
    之前使用urllib库,是可以使用opener发送多个请求,多个请求是可以共享cookie的。那么如果使用requests,也要达到共享cookie的目的,那么可以说使用requsets库给我们提供的session对象。注意,这里的session不是web开发中的那个session,这个地方这是一个回话的对象而已。

3.6 【实战】使用requests库模拟登录人人网:

还是以登录人人网为例,使用requests来实现。实例代码为下:

import requests

url='http://www.renren.com/PLogin.do'
data = {
    'email' :'[email protected]',
    'password' : 'pythonspider'
}
headers={
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36'
}

#登录
session = requests.session()
session.post(url,data=data,headers=headers)

#访问大鹏个人主页
response=session.get("http://www.renren.com/880151247/profile")
with open('renren.html','w',encoding='utf-8') as fp:
    fp.write(response.text)

得到renren.html,用Google Chrome打开:
Python网络爬虫之网络请求_第6张图片

3.7 处理不信任的SSL证书

如果SSL证书验证不通过,或者不信任服务器的安全证书,则会报出SSLError:

SSLError: ("bad handshake: Error([('SSL routines', 'ssl3_get_server_certificate', 'certificate verify failed')],)",)

据说 12306 证书是自己做的(现在已经被信任了,不会报错)

import requests
response = requests.get("https://www.12306.cn/mormhweb/", verify = False)
print response.text

如果我们想跳过某网站的证书验证,把 verify 设置为 False 就可以正常请求了。

你可能感兴趣的:(Python网络爬虫之网络请求)