python-爬虫-网络请求(二)

系统 1510 0

网络请求

urlopen函数用法

urllib库

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

urlopen函数

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

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

实际上,使用浏览器访问百度,右键查看源代码。就会发现,打印处理的内容就是和请求的内容一摸一样的,也就是说,上面的三行代码已经帮我们将百度首页的内容全部爬下来了
这里对urlopen函数进行详细讲解:

  1. url:请求的url
  2. data:请求的data,如果设置了这个值,那么请求将会变成post请求
  3. 返回值:返回值是一个http.client.HTTPResponse对象,这个对象是一个类文件句柄对象有read(size)、readline、readlines以及getcode等方法

urlretrieve函数

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

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

使用这个函数,可以方便我们将图片或者其他的内容下载到本地

urlencode函数

用浏览器发送请求的时候,如果url中包含了中文或者其他特殊符号,那么浏览器会自动给我们进行编码,而如果使用代码发送请求,那么就必须手动进行编码,这时候就应该使用urlencode函数来实现,urlencode可以把字典数据转换为URL编码的数据,示例代码如下:

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

parse_qs函数

可以将经过编码后的url参数进行解码(这个是配合上面urlencode函数配合使用的),示例代码如下:

            
              
                from
              
               urllib 
              
                import
              
               parse

	params 
              
                =
              
              
                {
              
              
                'name'
              
              
                :
              
              
                '张三'
              
              
                ,
              
              
                'age'
              
              
                :
              
              
                18
              
              
                ,
              
              
                'greet'
              
              
                :
              
              
                'hello world'
              
              
                }
              
              
	qs 
              
                =
              
               parse
              
                .
              
              urlencode
              
                (
              
              params
              
                )
              
              
                print
              
              
                (
              
              qs
              
                )
              
              

	result 
              
                =
              
               parse
              
                .
              
              parse_qs
              
                (
              
              qs
              
                )
              
              
                print
              
              
                (
              
              result
              
                )
              
              

	name
              
                =
              
              
                %
              
              E5
              
                %
              
              BC
              
                %
              
              A0
              
                %
              
              E4
              
                %
              
              B8
              
                %
              
              
                89
              
              
                &
              
              age
              
                =
              
              
                18
              
              
                &
              
              greet
              
                =
              
              hello
              
                +
              
              world
	
              
                {
              
              
                'name'
              
              
                :
              
              
                [
              
              
                '张三'
              
              
                ]
              
              
                ,
              
              
                'age'
              
              
                :
              
              
                [
              
              
                '18'
              
              
                ]
              
              
                ,
              
              
                'greet'
              
              
                :
              
              
                [
              
              
                'hello world'
              
              
                ]
              
              
                }
              
            
          

urlparse和urlsplit

有时候拿到一个url,想要对这个url中的各个组成部分进行分割,那么这时候就可以使用urlparse或者urlsplit来进行分割
首先来看下urlparse

            
              
                from
              
               urllib 
              
                import
              
               parse
	
	url 
              
                =
              
              
                'http://www.baidu.com/s?wb=python&username=abc#1'
              
              
	result 
              
                =
              
               parse
              
                .
              
              urlparse
              
                (
              
              url
              
                )
              
              
                print
              
              
                (
              
              result
              
                )
              
              
	
	ParseResult
              
                (
              
              scheme
              
                =
              
              
                'http'
              
              
                ,
              
               netloc
              
                =
              
              
                'www.baidu.com'
              
              
                ,
              
               path
              
                =
              
              
                '/s'
              
              
                ,
              
               params
              
                =
              
              
                ''
              
              
                ,
              
               query
              
                =
              
              
                'wb=python&username=abc'
              
              
                ,
              
               fragment
              
                =
              
              
                '1'
              
              
                )
              
            
          

如果仅仅只想获取中间某一个内容,可以使用如下的方式来进行获取

            
              
                print
              
              
                (
              
              result
              
                .
              
              scheme
              
                )
              
              
	http

            
          

其次来看下urlsplit

            
              	url 
              
                =
              
              
                'http://www.baidu.com/s?wb=python&username=abc#1'
              
              
	result 
              
                =
              
               parse
              
                .
              
              urlsplit
              
                (
              
              url
              
                )
              
              
                print
              
              
                (
              
              result
              
                )
              
              
	SplitResult
              
                (
              
              scheme
              
                =
              
              
                'http'
              
              
                ,
              
               netloc
              
                =
              
              
                'www.baidu.com'
              
              
                ,
              
               path
              
                =
              
              
                '/s'
              
              
                ,
              
               query
              
                =
              
              
                'wb=python&username=abc'
              
              
                ,
              
               fragment
              
                =
              
              
                '1'
              
              
                )
              
            
          

对比可以发现,在使用urlsplit的时候,中间缺少了一个params的参数,这里的params在现在的爬虫中间用到的比较少,这里获取的内容就是 ;和?之间的内容,如下所示

            
              
                from
              
               urllib 
              
                import
              
               parse
	
	url 
              
                =
              
              
                'http://www.baidu.com/s;hello?wb=python&username=abc#1'
              
              
	result 
              
                =
              
               parse
              
                .
              
              urlparse
              
                (
              
              url
              
                )
              
              
                print
              
              
                (
              
              result
              
                )
              
              
	ParseResult
              
                (
              
              scheme
              
                =
              
              
                'http'
              
              
                ,
              
               netloc
              
                =
              
              
                'www.baidu.com'
              
              
                ,
              
               path
              
                =
              
              
                '/s'
              
              
                ,
              
               params
              
                =
              
              
                'hello'
              
              
                ,
              
               query
              
                =
              
              
                'wb=python&username=abc'
              
              
                ,
              
               fragment
              
                =
              
              
                '1'
              
              
                )
              
            
          

通常情况下,使用urlparse和urlsplit是一样的,唯一不一样的地方就是,urlparse中间多一个params属性,而urlsplit没有这个属性

request.Request类

如果想要在请求的时候增加一些请求头,那么就必须使用request.Request来实现。如果要增加一个User-Agent

            
              
                from
              
               urllib 
              
                import
              
               request
	
	url 
              
                =
              
              
                'https://www.lagou.com/jobs/list_python?labelWords=&fromSearch=true&suginput='
              
              
                # resp = request.urlopen(url)
              
              
                # print(resp.read())
              
              
	
	headers 
              
                =
              
              
                {
              
              
                'User-Agent'
              
              
                :
              
              
                'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36'
              
              
                }
              
              
	
	req 
              
                =
              
               request
              
                .
              
              Request
              
                (
              
              url
              
                ,
              
              headers
              
                =
              
              headers
              
                )
              
              
	resp 
              
                =
              
               request
              
                .
              
              urlopen
              
                (
              
              req
              
                )
              
              
                print
              
              
                (
              
              resp
              
                .
              
              read
              
                (
              
              
                )
              
              
                )
              
            
          

在上面的代码中,如果想要给请求的url加上一个请求头的话,就需要使用request.Request这个方式将请求的内容进行一个封装,这里封装的请求头是User-Agent这个请求头,这里将这里面的内容写上浏览器的标识;这里需要注意,这里封装好了之后,是还并没有发起请求的,最后还是调用的request.urlopen方法发起请求的
注意:这里的这个request.Request方法除了能够传递User-Agent外,还能够传递data和method
如下:
python-爬虫-网络请求(二)_第1张图片

ProxyHandler处理器(代理设置)

很多网站会检测某一段时间某个ip的访问次数(通过流量统计,系统日志等),如果访问次数多的不像正常人,就会禁止这个ip的访问,所有我们可以设置一些代理服务器,每隔一段时间换一个代理,就算ip被禁止,依然可以换个ip继续爬取
urllib中通过ProxyHandler来设置使用代理服务器,下面代码说明如果使用自定义opener来使用代理

            
              
                from
              
               urllib 
              
                import
              
               request
	
	
              
                # 未使用代理
              
              
                # url = 'http://httpbin.org/ip'
              
              
                #
              
              
                # resp = request.urlopen(url)
              
              
                # print(resp.read())
              
              
                # -----------------------
              
              
                # 使用代理的
              
              
	url 
              
                =
              
              
                'http://httpbin.org/ip'
              
              
                # 1、使用ProxyHandler,传入代理构建一个handler
              
              
	handler 
              
                =
              
               request
              
                .
              
              ProxyHandler
              
                (
              
              
                {
              
              
                'http'
              
              
                :
              
              
                '125.110.75.152:9000'
              
              
                }
              
              
                )
              
              
                # 2、使用上面创建的handler构建一个opener
              
              
	opener 
              
                =
              
               request
              
                .
              
              build_opener
              
                (
              
              handler
              
                )
              
              
                # 3、使用opener去发送一个请求
              
              
	resp 
              
                =
              
               opener
              
                .
              
              
                open
              
              
                (
              
              url
              
                )
              
              
                print
              
              
                (
              
              resp
              
                .
              
              read
              
                (
              
              
                )
              
              
                )
              
            
          

这里需要了解到的就是在使用urlopen的时候,其实也是完成构建一个handler之后再创建了一个opener,最后发起的请求,这个过程只是在openurl中间隐藏了

常用的代理有:
西刺免费代理IP:https://www.xicidaili.com/nt/
快代理:https://www.kuaidaili.com/
代理云:http://www.dailiyun.com/

在需要测试发送请求的机器对应的外网地址,可以使用http://httpbin.org/ip方式获取

小结

1、代理的原理:在请求目的服务器之前,先请求代理服务器,然后让代理服务器去请求目的网站,代理服务器拿到目的网站的数据后,再转发给我们的代码
2、http://httpbin.org:这个网站可以方便的查看http请求的一些请求
3、在代码中使用代理:
3.1 使用 urllib.request.ProxyHandler
3.2 传入一个代理,这个代理是一个字典,字典的key是http或者https,value是ip:port
3.2 使用上一步创建的handler,以及request.build_handler创建一个opener对象
3.3 使用上一步创建的opener,使用open函数,发起请求

什么是cookie

在网站中,http请求是无状态的,也就是说即使第一次和服务器连接后并且登陆成功后,第二次请求服务器依然不能知道当前是哪个用户。cookie的出现就是为了解决这个问题,第一次登陆后服务器返回一些数据(cookie)给浏览器,然后浏览器保存在本地,当该用户发送第二次请求的时候,就会自动的把上传请求存储的cookie数据自动的携带给服务器,服务器通过浏览器携带的数据就能判断当前用户是哪个了。cookie存储的数据量有限,不同的浏览器有不同的存储大小,但一般不操过4KB,因此使用cookie只能存储一些小量的数据

cookie的格式

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

            
          

参数含义:
NAME:cookie的名字
VALUE:cookie的制
Expires:cookie的过期时间
Path:cookie作用的域名
Domain:cookie作用的域名
SECURE:是否只在https写一下起作用

下面以访问百度为例
python-爬虫-网络请求(二)_第2张图片
可以看到,cookie都是放在Response Headers中间的

使用cookielib库和HTTPCookieProcessor模拟登陆

Cookie是指网站服务器为了辨别用户身份和进行Session跟踪,而存储在用户用户浏览器上的文本文件,Cookie可以保持登陆信息到用户下次与服务器的会话
这里讲点题外话:
要将byte类型转为str类型,转换过程是byte -> decode -> str
要将str类型转为byte类型,转换过程是str -> encode -> byte
示例:
python-爬虫-网络请求(二)_第3张图片
以上的方式是通过浏览器首先登陆成功之后,在后面页面访问的时候,通过Request Header中间获取到的Cookie,将这个Cookie放在请求头中间,使用代码进行访问
其实这样的方式还不是最好的,Cookie是服务端发出的,此时还是copy的浏览器的Cookie,更好的方式则是通过模拟登陆之后自动保存Cookie,最后携带这个Cookie发起后面的请求


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论