爬虫一:urllib模块

一、了解网页结构

比如百度输入656,网页地址为:https://www.baidu.com/s?wd=656&rsv_spt=1&rsv_iqid=0xe9b8751c008d4f26&issp=1&f=8&rsv_bp=1&rsv_idx=2&ie=utf-8&tn=baiduhome_pg&rsv_dl=tb&rsv_enter=1&rsv_sug3=3&rsv_sug1=3&rsv_sug7=100&rsv_sug2=0&rsv_btype=i&prefixsug=656&rsp=9&inputT=617&rsv_sug4=618

实际有用的为:https://www.baidu.com/s?wd=656;输入这个和上面那个一致,通过https请求www.baidu.com这台主机上面有关于656的数据信息;

二、请求和响应

url:Uniform Resource Locator,统一资源定位符;

基本格式:scheme://host[:port#]/path/..../[?query-string][#anchor]

scheme:协议(例如http、https、ftp)、host:服务器的IP地址或者域名(如192.168....)、port#:服务器的端口(如果是走协议默认端口,端口缺省为80)、path:访问资源的路径、query-string:参数,发送给服务器的数据、anchor:锚(跳转到网页的指定锚点位置)

get请求:从服务器上获取数据;get请求的参数都显示在url中,如上文所示的“656”就是get请求的参数,实际参数的话后面那部分都是,http协议根据该请求所包含的url中的参数来产生响应内容,即get的参数是url的一部分;         

post请求:向服务器传送数据;post请求的参数在请求体当中,消息长度没有限制而且以隐式的方式进行发送,通常用来向http服务器提交量比较大的数据(比如请求中包含许多参数或者文件上传操作等),请求的参数包含在“content-type”消息头里,指明该消息的媒体类型和编码;

注:提交密码时使用post请求,get请求没有安全性;在post请求中用户名和密码和请求信息会放在在Form Data中;

进入后选择network,当你进入网页时,会有很多的请求信息出来,如何从中选出我们需要的那条请求信息:需要在response中看有没有返回整个网页的返回信息;

*两种导入模块的方法:1、import urllib.request    #这种在后面的调用中,每次调用request都需要写成urllib.request

2、from urllib import request    #这种在调用request类时可以直接request;

三、开发者工具(浏览器上按f12)

元素(Elements):用于查看或修改HTML元素的属性、CSS属性、监听事件、断点等。
控制台(Console):控制台一般用于执行一次性代码,查看JavaScript对象,查看调试日志信息或异常信息。
源代码(Sources):该页面用于查看页面的HTML文件源代码、JavaScript源代码、CSS源代码,此外最重要的是可以调试JavaScript源代码,可以给JS代码添加断点等。
网络(Network):网络页面主要用于查看header等与网络连接相关的信息。
(1)元素(Elements)

查看元素代码:点击如图箭头(或用者用快捷键Ctrl+Shift+C)进入选择元素模式,然后从页面中选择需要查看的元素,然后可以在开发者工具元素(Elements)一栏中定位到该元素源代码的具体位置 。

查看元素属性:可从被定位的源码中查看部分,如class、src,也可在右边的侧栏中查看全部的属性,如下图位置查看

 

修改元素的代码与属性:可直接双击想要修改的部分,然后就进行修改,或者选中要修改部分后点击右键进行修改,如下图

注意:这个修改也仅对当前的页面渲染生效,不会修改服务器的源代码,故而这个功能也是作为调试页面效果而使用。

右边的侧栏个功能的介绍:如下图所示

(2)控制台(Console)

  • 查看JS对象的及其属性
  • 执行JS语句
  • 查看控制台日志:当网页的JS代码中使用了console.log()函数时,该函数输出的日志信息会在控制台中显示。日志信息一般在开发调试时启用,而当正式上线后,一般会将该函数去掉。

(3)源代码(Sources)其主要功能如下介绍

 

(4)网络(Network)

大体功能如下:

请求文件具体说明

一共分为四个模块:

Header:面板列出资源的请求url、HTTP方法、响应状态码、请求头和响应头及它们各自的值、请求参数等等
Preview:预览面板,用于资源的预览。
Response:响应信息面板包含资源还未进行格式处理的内容
Timing:资源请求的详细信息花费时间


附1:

请求响应内容 Preview 和 Response 不一致,如下图

 

原因: js 解析 json 数据时,对于 long 类型数据长度有限制。此时的 long 类型数据 userId 长度超限,jsp 中解析时出现精度丢失,导致数据值出现误差。

解决: 修改返回数据 long 类型为 String 类型,作为字符处理。如上图 黑色框中字段 :userIdStr ,正常解析了该数据值。

 

附2:【HTTP】Request Header 和 Response Header字段详解

header主要是requests中用来伪装浏览器请求网页用的。请求头都一样的(对应机器不同会有变化),只要本机记录下来,以后就不用在找了,可以直接使用第一次找到的请求头。

Request Header

Header解释示例
Accept指定客户端能够接收的内容类型Accept: text/plain, text/html
Accept-Charset浏览器可以接受的字符编码集。Accept-Charset: iso-8859-5
Accept-Encoding指定浏览器可以支持的web服务器返回内容压缩编码类型。Accept-Encoding: compress, gzip
Accept-Language浏览器可接受的语言Accept-Language: en,zh
Accept-Ranges可以请求网页实体的一个或者多个子范围字段Accept-Ranges: bytes
AuthorizationHTTP授权的授权证书Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
Cache-Control指定请求和响应遵循的缓存机制Cache-Control: no-cache
Connection表示是否需要持久连接。(HTTP 1.1默认进行持久连接)Connection: close
CookieHTTP请求发送时,会把保存在该请求域名下的所有cookie值一起发送给web服务器。保存登录一段时间,用户信息加密方式保存。Cookie: $Version=1; Skin=new;
Content-Length请求的内容长度Content-Length: 348
Content-Type请求的与实体对应的MIME信息Content-Type: application/x-www-form-urlencoded
Date请求发送的日期和时间Date: Tue, 15 Nov 2010 08:12:31 GMT
Expect请求的特定的服务器行为Expect: 100-continue
From发出请求的用户的EmailFrom: user@email.com
Host指定请求的服务器的域名和端口号Host: www.zcmhi.com
If-Match只有请求内容与实体相匹配才有效If-Match: “737060cd8c284d8af7ad3082f209582d”
If-Modified-Since如果请求的部分在指定时间之后被修改则请求成功,未被修改则返回304代码If-Modified-Since: Sat, 29 Oct 2010 19:43:31 GMT
If-None-Match如果内容未改变返回304代码,参数为服务器先前发送的Etag,与服务器回应的Etag比较判断是否改变If-None-Match: “737060cd8c284d8af7ad3082f209582d”
If-Range如果实体未改变,服务器发送客户端丢失的部分,否则发送整个实体。参数也为EtagIf-Range: “737060cd8c284d8af7ad3082f209582d”
If-Unmodified-Since只在实体在指定时间之后未被修改才请求成功If-Unmodified-Since: Sat, 29 Oct 2010 19:43:31 GMT
Max-Forwards限制信息通过代理和网关传送的时间Max-Forwards: 10
Pragma用来包含实现特定的指令Pragma: no-cache
Proxy-Authorization连接到代理的授权证书Proxy-Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
Range只请求实体的一部分,指定范围Range: bytes=500-999
Referer先前网页的地址,当前请求网页紧随其后,即来路Referer: http://www.zcmhi.com/archives/71.html
TE客户端愿意接受的传输编码,并通知服务器接受接受尾加头信息TE: trailers,deflate;q=0.5
Upgrade向服务器指定某种传输协议以便服务器进行转换(如果支持)Upgrade: HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11
User-Agent浏览器名称,不同浏览器有不同的useagent信息;User-Agent: Mozilla/5.0 (Linux; X11)
Via通知中间网关或代理服务器地址,通信协议Via: 1.0 fred, 1.1 nowhere.com (Apache/1.1)
Warning关于消息实体的警告信息Warn: 199 Miscellaneous warning

Response Header

Header解释示例
Accept-Ranges表明服务器是否支持指定范围请求及哪种类型的分段请求Accept-Ranges: bytes
Age从原始服务器到代理缓存形成的估算时间(以秒计,非负)Age: 12
Allow对某网络资源的有效的请求行为,不允许则返回405Allow: GET, HEAD
Cache-Control告诉所有的缓存机制是否可以缓存及哪种类型Cache-Control: no-cache
Content-Encodingweb服务器支持的返回内容压缩编码类型。Content-Encoding: gzip
Content-Language响应体的语言Content-Language: en,zh
Content-Length响应体的长度Content-Length: 348
Content-Location请求资源可替代的备用的另一地址Content-Location: /index.htm
Content-MD5返回资源的MD5校验值Content-MD5: Q2hlY2sgSW50ZWdyaXR5IQ==
Content-Range在整个返回体中本部分的字节位置Content-Range: bytes 21010-47021/47022
Content-Type返回内容的MIME类型Content-Type: text/html; charset=utf-8
Date原始服务器消息发出的时间Date: Tue, 15 Nov 2010 08:12:31 GMT
ETag请求变量的实体标签的当前值ETag: “737060cd8c284d8af7ad3082f209582d”
Expires响应过期的日期和时间Expires: Thu, 01 Dec 2010 16:00:00 GMT
Last-Modified请求资源的最后修改时间Last-Modified: Tue, 15 Nov 2010 12:45:26 GMT
Location用来重定向接收方到非请求URL的位置来完成请求或标识新的资源Location: http://www.zcmhi.com/archives/94.html
Pragma包括实现特定的指令,它可应用到响应链上的任何接收方Pragma: no-cache
Proxy-Authenticate它指出认证方案和可应用到代理的该URL上的参数Proxy-Authenticate: Basic
refresh应用于重定向或一个新的资源被创造,在5秒之后重定向(由网景提出,被大部分浏览器支持)

 

 

Refresh: 5; url=

http://www.zcmhi.com/archives/94.html

Retry-After如果实体暂时不可取,通知客户端在指定时间之后再次尝试Retry-After: 120
Serverweb服务器软件名称Server: Apache/1.3.27 (Unix) (Red-Hat/Linux)
Set-Cookie设置Http CookieSet-Cookie: UserID=JohnDoe; Max-Age=3600; Version=1
Trailer指出头域在分块传输编码的尾部存在Trailer: Max-Forwards
Transfer-Encoding文件传输编码Transfer-Encoding:chunked
Vary告诉下游代理是使用缓存响应还是从原始服务器请求Vary: *
Via告知代理客户端响应是通过哪里发送的Via: 1.0 fred, 1.1 nowhere.com (Apache/1.1)
Warning警告实体可能存在的问题Warning: 199 Miscellaneous warning
WWW-Authenticate表明客户端请求实体应该使用的授权方案WWW-Authenticate: Basic

Request Header常见配置参数

  • Cache
  1. Cache-Control: no-cache

  2. Pragma: no-cache

  • Client
  1. Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8

  2. Accept-Encoding: gzip, deflate, sdch

  3. Accept-Language: zh-CN,zh;q=0.8

  4. User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36

  • Security
Upgrade-Insecure-Requests: 1
  • Transport
  1. Connection: keep-alive

  2. Host: xnj.aijee

Response Header常见配置参数

  • Cache
  1. Cache-Control: public, max-age=8

  2. Date: Sun, 28 Aug 2016 09:51:16 GMT

  3. Expires: Sun, 28 Aug 2016 04:06:12 GMT

  4. Vary: *

  • Entity
  1. Content-Length: 19165

  2. Content-Type: text/html

  3. ETag: "57a01700-4add"

  4. Last-Modified: Tue, 02 Aug 2016 03:44:00 GMT

  • Miscellaneous
  1. Accept-Ranges: bytes

  2. Server: nginx/1.8.1

  • Transport
Connection: keep-alive

Cache-Control(网页缓存)

  • public:所有内容都将被缓存(客户端和代理服务器都可缓存)。
  • private:内容只缓存到私有缓存中(仅客户端可以缓存,代理服务器不可缓存)。
  • no-cache:协商缓存。必须先与服务器确认返回的响应是否被更改,然后才能使用该响应来满足后续对同一个网址的请求。

如果存在合适的验证令牌 (ETag),no-cache 会发起往返通信来验证缓存的响应,如果资源未被更改,可以避免下载。

  • no-store:所有内容都不会被缓存到缓存或 Internet 临时文件中。
  • must-revalidation/proxy-revalidation:如果缓存的内容失效,请求必须发送到服务器/代理以进行重新验证。
  • max-age=xxx:缓存的内容将在 xxx 秒后失效, 这个选项只在HTTP 1.1可用, 并如果和Last-Modified一起使用时, 优先级较高。

 

四、爬虫模块的使用

Ⅰ、urllib

(1)主要使用的模块为urllib.request(urllib模块下的request模块)

引入方式:1、import urllib.request

                    2、from urllib import request

(2)示例

1、爬取baidu.com

reponse=urllib.request.urlopen(url). read()   #请求url网站

print(reqonse)   #打印二进制的返回值

reponse=urllib.request.urlopen(url). read().decode()   #解码,为了能识别中文;

#urlopen给()方法用来访问url网址对应的内容;read()方法用来读取所访问到的内容,访问到的信息为二进制字节码信息,中文无法正常显示;decode()以指定的格式来解码,默认为字符串编码,这里用来将字节码以字符串解码方式来解码,中文可以正常显示。

urlopen局限:urlopen函数原型为

data 这个是发送求请需要传递的参数。如果要传递data参数,urlopen将使用post方式请求。
timeout 这个是求请超时时长。我们可以设置时长,如果请求时间过长,则会抛出异常。
cafile 这个是CA证书。
capath 这个是CA证书路径。
cadefault=Flase 这个已经被弃用了,不用关注这个了。
context 这个可以指定SSL安装验证设置,比如我们可以设置忽略证书验证等等。
所以urlopen中无法加入headers等请求头参数信息,需要带上更多的参数的话就需要使用req=request. Request(url,headers=header)类似的,用来包装请求,然后在用urlopen(req)来获取请求;

2.创建自定义请求

req=request. Request(url)

response=request. urlopen(req). read(). decode()

request表示模块名,Request表示方法名。

使用自定义请求的意义:括号中可以自定义加上use-agent等信息,能模拟浏览器行为,防止反爬机制。

3、反爬虫机制

机制1:判断用户是否是浏览器访问;

对策:通过伪装成浏览器进行访问,用user-Agent来伪装(不同的浏览器use-Agent不同);

构造请求头信息:header={“User-Agent”="Mozilla/5.0......."

                                }

创建的请求也需要改变:req=request. Request(url,headers=header)

                                            response=request. urlopen(req). read(). decode()

机制2:使用多个user-agent来随机取一个使用,用随机数来实现。

更高级的反爬机制。

机制3:判断请求源的IP地址,如果某个IP访问过多过于频繁可能被封掉,解决办法是使用代理IP。

               免费代理IP:直接百度搜索,复制下IP地址和端口号。

                使用方法:使用多个代理ip,每次随机选择其中一个ip进行访问

                代码示例 :proxylist={

                                            "http":"ip1:port1"

                                             http":"ip2:port2"

                                             ....}

                                        proxy=random. choice(proxylist)#选择随机一个代理ip来使用

                                        #构建代理处理器对象

                                         proxyHandler=request.ProxyHandler(proxy)

                                         #ProxyHandler方法是用来构建一个代理请求的处理器对象

                                          #创建自定义opener

                                           opener=request.build_opener(proxyHandler)

                                           req=request. Request(url)

                                           response=opener. open(req)

                                           print(response.read())

4、创建自定义opener(因为urlopen函数不支持验证、cookie或其他http高级功能,所以需要使用build_opener来创建opener对象)

(1)构建http处理器对象

http_hander=request.Httphandler()

(2)创建自定义opener

opener=request.build_opener(http_hander)

(3)创建自定义请求对象

req=request. Request("url")

(4)发送请求,获取响应

response=opener. open(req). read()

print(response)

5、设置opener为全局(为了能使用urlopen还能使用opener支持的高级功能,设置为全局后urlopen发送的请求也会使用自定义的opener)

request.install_opener(open)

response=request.urlopen(req).read()#这两行来代替第4步中的(4)中的代码;

6、urllib.request中Handler处理器

(1)、定义
  自定义的urlopen()方法,urlopen()方法是一个特殊的opener(模块已定义好),不支持代理等功能,通过Handler处理器对象来自定义opener对象
(2)、常用方法
  1、build_opener(Handler处理器对象) :创建opener对象
  2、opener.open(url,参数)
(3)、使用流程
  1、创建相关的Handler处理器对象
    http_handler = urllib.request.HTTPHandler()
  2、创建自定义opener对象
    opener = urllib.request.build_opener(http_handler)
  3、利用opener对象打开url
    req = urllib.request.Request(url,headers=headers)
    res = opener.open(req)
    result = res.read().decode("utf-8")
(4)、Handler处理器分类
  1、HTTPHandler() :没有任何特殊功能
  2、ProxyHandler(普通代理)
    代理: {"协议":"IP地址:端口号"}
  3、ProxyBasicAuthHandler(密码管理器对象) :私密代理
  4、HTTPBasicAuthHandler(密码管理器对象) : web客户端认证
(5)、密码管理器对象作用
  1、私密代理
  2、Web客户端认证
  3、程序实现流程
    1、创建密码管理器对象
      pwdmg = urllib.request.HTTPPasswordMgrWithDefaultRealm()
    2、把认证信息添加到密码管理器对象
      pwdmg.add_password(None,webserver,user,passwd)
    3、创建Handler处理器对象
      1、私密代理
        proxy = urllib.request.ProxyAuthBasicHandler(pwdmg)
      2、Web客户端
        webbasic = urllib.request.HTTPBasicAuthHandler(pwdmg)

7、处理get请求(所以请求信息都在url当中)

http://www.baidu.com/s?ie=utf-&8wd=%Ed%8C%97%E4%BA%AC   此为url编码,实际上我们真正可以用的是

http://www.baidu.com/s?wd=%Ed%8C%97%E4%BA%AC这些,在s和?后找到wd,wd=的内容就是我们请求的内容。在url编码中,我们输入的文字会变成二进制字节码,所以需要将请求给编码一下,构造出一个浏览器可以认识的url)

wd={"wd":"北京"}

url="http://baidu. come/s?"

wdd=urllib. parse. url encode(wd)

url=url+wdd

req=request. Request(url)

response=request. urlopen(req). red(). decode()

8、处理post请求(请求信息中包含私密信息,不放在url中;请求和响应不直接在url中显示,一般在form data中显示,用户名和密码也是)

处理post的请求主要处理form data数据:

formdata = {
"i": "中国",
"from": "AUTO",
"to": "AUTO",
"smartresult": "dict",
"client": "fanyideskweb",
"salt": "16223412495373",
"sign": "166038e44c4ab5094305a55bc5c7fe9e",
"lts": "1622341249537",
"bv": "b396e111b686137a6ec711ea651ad37c",
"doctype": "json",
"version": "2.1",
"keyfrom": "fanyi.web",
"action": "FY_BY_REALTlME",
}    

data = urllib.parse.urlencode(formdata).encode(encoding='UTF-8')

request = urllib.request.Request(url, data = data, headers = headers)

post请求和get请求:如果request方法中data参数有值即为post请求,否则为get请求;

9、cookie模拟登陆

当url中没有用户名和密码,formdata中也没有用户名和密码,那么密码就会放在cookie中。

cookie是由服务端生成,发送给useragent(即浏览器)的,浏览器会将cookie的key/value存放在某个目录下的文本文件内(保存在客户端);cookie最常用的功能就是保持登陆状态;

具体流程:登陆动作发生后,客户端本地会把服务端发过来的cookie信息保存在本地的一个文本文件内,而相应的服务端也会生成一个session文件,session文件与cookie信息相对应。当下一次打开这个网页时,服务端会将session信息和客户端的cookie信息进行比对,如果用户名、密码都正确,且cookie还在存活周期内则直接登陆;

要使用cookie时,直接把cookie拷如headers中即可;

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

木头人123。

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值