【python分布爬虫】1-1.网络请求

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

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

from urllib import request

'''
get获取方式
'''
resp=request.urlopen('http://www.baidu.com')    # resp得到响应
# print(resp.read())  # read()将响应当中的数据读取出来
# print(resp.read(5))
# print(resp.readline())  # readline()只读取一行
# print(resp.readlines())
print(resp.getcode())   # 200  返回http状态码
'''
1.read(site):用于从文件读取指定的字节数,如果site未给定或为负则读取所有。
2.readline():每次读取一行内容
3.readlines():读取整个文件所有行,保存在一个列表(list)变量中
4,getcode():返回http状态码
'''
	实际上,使用浏览器访问百度,右键查看源代码。你会发现,跟我们刚才打印出来的数据是一模一样的。也就是说,上面的三行代码就已经帮我们把百度的首页的全部代码爬下来了。一个基本的url请求对应的python代码真的非常简单。

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

3. urlretrieve函数

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

from urllib import request

request.urlretrieve('http://www.baidu.com', 'baidu.html')   # 下载百度网页
# 前面参数是url,后面是保存的路径以及文件名

request.urlretrieve('https://img2.baidu.com/it/u=2348224141,235129573&fm=253&fmt=auto&app=120&f=JPEG?w=500&h=500','林俊杰.jpg')
# 网络上下载林俊杰图片

'''
urlretrieve() 方法可以方便的将网页上的一个文件下载并保存到本地
文件类型可以是网页的html文件、图片、视频等媒体文件
函数原型:urlretrieve(url, filename=None, reporthook=None, data=None)
参数 url 指定了要下载的文件的url
参数 finename 指定了保存本地路径(如果参数未指定,urllib会生成一个临时文件保存数据。)

'''

4. urlencode函数& parse_qs函数

from urllib import parse # 对于编码和解码是放在这一个模块中的,用的时候需要导入

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

parse_qs函数:
可以将经过编码后的url参数进行解码

from urllib import request  # request是存放网络请求相关的
from urllib import parse  # 对于编码解码是放在另一个模块中的

# urlencode函数的用法:进行编码

params = {'name': '张三', 'age': 18, 'greet': 'hello world'}
result = parse.urlencode(params)  # 将字符串进行编码
print(result)

# 编码结果: name=%E5%BC%A0%E4%B8%89&age=18&greet=hello+world   
# hello world 中间的空格使用加号进行区分

url = 'http://www.baidu.com/s'
# 百度上搜索刘德华网址:https://www.baidu.com/s**?**ie=UTF-8&wd=%E5%88%98%E5%BE%B7%E5%8D%8E

params = {"wd": "刘德华"}      # 拼接中文应该使用中文编码后的结果
qs = parse.urlencode(params)	# params是字典类型
print(qs)  # 结果:wd=%E5%88%98%E5%BE%B7%E5%8D%8E
url = url + "?" + qs  # 拼接
print(url)  # 结果:http://www.baidu.com/s?wd=%E5%88%98%E5%BE%B7%E5%8D%8E

resp=request.urlopen(url)
print(resp.read())	# 读取百度上刘德华html页面全部内容



# parse_qs函数的用法:进行解码

# 先进行编码
params = {'name': '张三', 'age': 18, 'greet': 'hello world'}	# 字典类型
qs = parse.urlencode(params)
# 再进行解码
result=parse.parse_qs(qs)
print(result)   # {'name': ['张三'], 'age': ['18'], 'greet': ['hello world']}

5.urlparse函数&urlsplit函数
url的组成成分:
http://www.aspxfans.com:8080/news/index.asp?boardID=5&ID=24618&page=1#name
1、传输协议(scheme):http
2、主机名/域名(host):www.aspxfans.com 服务器(www)+域名(aspxfans.com)
3、端口号(port):8080
5、路径(path):/news/
6、文件名:index.asp
7、查询字符串(query-string):boardID=5&ID=24618&page=1
8、片段(可省略):name
在浏览器中请求一个url,浏览器会对这个url进行一个编码。出英文字母,数字和部分符号外,其余的全部使用百分号+十六进制值进行编码

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

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

url = 'http://www.baidu.com/s?wd=python&username=abc#1'  # 随便给的例子

# result1 = parse.urlparse(url)  # 拿到url当中的每一部分
result2 = parse.urlsplit(url)  # 拿到url当中的每一部分    写法合适,可以直接使用这种写法

#print(result1)
# 结果:ParseResult(scheme='http', netloc='www.baidu.com', path='/s', params='', query='wd=python&username=abc', fragment='1')

'''
print('scheme:', result1.scheme)  # ctrl+d表示复制一份
print('netloc:', result1.netloc)
print('path:', result1.path)
print('query:', result1.query)
print('fragment:', result1.fragment)

上述运行结果:
    scheme: http
    netloc: www.baidu.com
    path: /s
    query: wd=python&username=abc
    fragment: 1
'''

print(result2)
# 结果:SplitResult(scheme='http', netloc='www.baidu.com', path='/s', query='wd=python&username=abc', fragment='1')

7. request.Request类
如果想要在请求的时候增加一些请求头,那么就必须使用request.Request类来实现。比如要增加一个User-Agent,示列代码如下:

from urllib import request

# url = 'https://www.lagou.com/wn/jobs?labelWords=&fromSearch=true&suginput=&kd=python'
url="https://movie.douban.com/top250?start="


'''
这里是get方式
'''
# resp=request.urlopen(url)
# print(resp.read().decode("utf-8"))
# 拉勾网具有反爬虫,返回的是一串乱码,只有定义headers让网站认为这不是爬虫程序,进行伪装

# 使用前先观察这个网站的请求方式是get还是post方式

'''
post方式/网站识别出为爬虫程序
'''
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.67 Safari/537.36"
}   # 是我们所要改动的值

# 创建请求对象(包装请求)-Request
req = request.Request(url, headers=headers)     # 与get方式相比就多了这一行

# 发请求,获取响应对象-urlopen
resp = request.urlopen(req)

# 读取内容read
print(resp.read().decode('utf-8'))


'''
url = 'https://www.lagou.com/wn/jobs?labelWords=&fromSearch=true&suginput=&kd=python'
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.67 Safari/537.36"
   
    # 当出现请求太频繁,请稍后再访问,表示网站还能识别是爬虫做的,还要进行伪装,伪装的像一点
    “Referer”: ”https://www.lagou.com/“
    
}
data={
    'first':'true',
    'pn':1,
    'kd'='python'
}
# data数据需要urlencode才能传进 request.Request里面去。通过encode方式转换为byte类型

req = request.Request(url, headers=headers,data=parse.urlencod(data).encode('utf-8'),method='POST')     
# 如果网站还能识别是爬虫,不能返回数据,证明伪装性不高,还要进行高度伪装。加上data,heders里面加上refer, request.Request里加上method
resp = request.urlopen(req)
print(resp.read().decode('utf-8'))
# decode('utf-8')是将byte类型解码成Unicode类型

'''

8. ProxyHandler处理器(代理设置)
很多网站会检测某一段时间某个IP的访问次数(通过流量统计,系统日志等),如果访问次数多的不像正常人,它会禁止这个IP的访问。所以我们可以设置一些代理服务器,每隔一段时间换一个代理,就算IP被禁止,依然可以换个IP继续爬取。(简单来说就是利用别人的ip进行爬取数据)
urllib中通过ProxyHandler来设置使用代理服务器,下面代码说明如何使用自定义opener来使用代理:
(http://httpbin.org/ip:这个网站可以查看自己的ip信息)

from urllib import request

# 没有使用代理的

'''
url='http://httpbin.org/ip' # 该网站可以查看没有使用代理时自己的ip地址
resp=request.urlopen(url)   # 返回一个响应
print(resp.read())      # 结果:b'{\n  "origin": "39.*.*.*"\n}\n'
'''

# 使用代理的

url = 'http://httpbin.org/ip'
# 1.使用ProxyHeader,传入代理构建一个handler
handler = request.ProxyHandler({"http": "120.220.220.95:8085"})
# 这个代理是一个字典,字典的key依赖于代理服务器能够接收的类型,一般是“http”或者“https”,值是“ip:port”
# 2.使用上面创建的handler构建一个opener
opener = request.build_opener(handler)
# 3.使用opener去发送一个请求
resp = opener.open(url)
print(resp.read())   # 结果:b'{\n  "origin": "120.220.220.95"\n}\n',ip地址变了,让别人的ip代理了

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

使用http://httpbin.org/ip可以查看没有使用代理时自己的ip地址

'''
总结ProxyHeaderch处理器(代理):
    1、代理的原理:在请求目的网站之前,先请求代理服务器,然后让代理服务器去请求目的网站,代理服务器拿到目的网站的数据后,再转发给我们的代码。
    2.http://httpbin.org/ip:这个网站可以方便的查看http请求的一些参数
    3.在代码中使用代理:
        1.使用“urllib.request.ProxyHandler”,传入一个代理,这个代理是一个字典,字典的key依赖于代理服务器能够接收的类型,一般是“http”
        或者“https”,值是“ip:port”
        2.使用上一步创建的“handler”,以及“request.build_opener”创建一个“opener”对象
        3.使用上一步创建的“opener”,调用“open”函数,发起请求
    示例代码如上----使用代理的:
    
'''

9. 什么是cookie:
在网站中,http请求是无状态的。也就是说即使第一次和服务器连接后并且登录成功后,第二次请求服务器依然不能知道当前请求是哪个用户。cookie的出现就是为了解决这个问题,第一次登录后服务器返回一些数据〈cookie〉给浏览器,然后浏览器保存在本地,当该用户发送第二次请求的时候,就会自动的把上次请求存储的 cookie数据自动的携带给服务器,服务器通过浏览器携带的数据就能判断当前用户是哪个了。cookie存储的数据量有限,不同的浏览器有不同的存储大小,但一般不超过4KB。因此使用cookie只能存储一些小量的数据。
(在以后的开发中,网站的开发80~90%都是使用cookie来实现,在以后写爬虫,需要爬取一些需要登录才能获得的数据,那就必须要和这个cookie打交道)

cookie的格式:

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

参考格式

10. 使用cookielib库和HTTPCookieProcessor模拟登录:
Cookie是指网站服务器为了辨别用户身份和进行Session跟踪,而储存在用户浏览器上的文本文件,Cookie可以保持登录信息到用户下次与服务器的会话。
这里以人人网为例。人人网中,要访问某个人的主页,必须先登录才能访问(必须处于一种登录状态才能访问),登录说白了就是要有cookie信息。那么如果我们想要用代码的方式访问,就必须要有正确的cookie信息才能访问。解决方案有两种,第一种是使用浏览器览访问,然后将cookie信息复制下来,放到headers中。示例代码如下:
*(**注意:*大家以后在写爬虫的时候,不管对方的网站做没做反爬虫机制,最好的方式就是把user-Agent这个东西加到请求头上去,这是最安全的)

11.http.dookiejar模块:

该模块主要的类有CookieJar、FileCookieJar、MozillaCookieJar、LWPCookieJar。这四个类的作用分别如下:
1.CookieJar:管理HTTP cookie值、存储HTTP请求生成的cookie、向传出的HTTP请求添加cookie的对象。整个cookie都存储在内存中,对CookieJar实例进行垃圾回收后cookie也将丢失。

2.FileCookieJar (flename,delayload=None,policy=None):从CookieJar派生而来,用来创建FileCookieJar实例,检索cookie信息并将cookie存储到文件中。filename是存储cookie的文伴名。delayload为True时支持延迟访问访问文件,即只有在需要时才读取文件或在文件中存储数据。

3.MozillaCookieJar (filename,delayload=None.,policy=None):从FileCookieJar派生而来,创建与Mozilla浏览器cookies.txt兼容的FileCookieJar实例。(保存在内存当中)

4.LWPCookieJar (filename.delayload=None.,policy=None):从FileCookieJar派生而来,创建与libwww-perl标准的Set-Cookle3文件格式兼容的FileCookieJar实例。

利用http.cockiejar和request.HTTPCookieProcessor登录人人网。相关示例代码如下:

12.cookie信息的加载与保存

# 保存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)

resp=opener.open('http://www.baidu.com')

cookiejar.save()

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

from urllib import  request
from http.cookiejar import MozillaCookieJar

cookiejar=MozillaCookieJar('cookie.txt')
cookiejar.load(ignore_discard=True)    # 加载cookie。  ignore_discard=True:里面将过期的cookie的信息保存下来
handler=request.HTTPCookieProcessor(cookiejar)
opener=request.build_opener(handler)

resp=opener.open('http://baidu.com')
# resp=opener.open('http://httpbin.org/cookies/set?course=abc')
for cookie in cookiejar:
    print(cookie)

# cookiejar.save()

生成cookie.txt文件

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值