网络爬虫之网络请求
说明:此博客有关爬虫的内容均学习自B站:up主:神奇的老黄。视频链接:
urllib库
安装urllib库
- pip命令pip install urllib
- pycharm->菜单栏的file->setting->Project Interpreter->点击”+”号->搜索urllib库安装即可
使用
- urlopen打开网址并读取内容
1 | #encoding: utf-8 |
urlretrieve函数保存数据到文件
1
2
3
# 保存文件
ret = request.urlretrieve("http://www.baidu.com","baidu.html")编码与解码
1 | # 编码与解码 |
运行结果:1
2
3name=%E5%BC%A0%E4%B8%89&age=18&greet=hallo+word
http://www.baidu.com/s?name=%E5%BC%A0%E4%B8%89&age=18&greet=hallo+word
{'http://www.baidu.com/s?name': ['张三'], 'age': ['18'], 'greet': ['hallo word']}
- urlparse和urlsplit函数分割网址
1 | # 网址分割 |
运行结果:
1 | ParseResult(scheme='http', netloc='www.baidu.com', path='/s', params='', query='wd=python&username=abc', fragment='1') |
让你的爬虫更加人性化
这里要从urllib库中导入request
添加headers
标头 (header) 是服务器以HTTP协议传HTML资料到浏览器前所送出的字串Referer也是包括在Request Headers里面的信息,添加此选项,可以让你的爬虫更人性化
添加data数据,GET请求的请求参数是直接包含在URL中了,而POST请求的请求参数则不会出现在URL中,而是要经过单独的封装处理,这就用到data了。
以下是包括上述的一个爬取电驴登录界面的例子
代码如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24#encoding: utf-8
from urllib import request,parse
url = 'http://secure.verycd.com/signin'
headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.26 Safari/537.36 Core/1.63.5944.400 LBBROWSER/10.1.3378.400',
'Referer':'http://secure.verycd.com/signin'
}
data = {
'username':'11111',
'password':'1e312r',
'continue':'http://www.verycd.com',
'fk':'',
'save_cookie':'1',
'login_submit':'登录'
}
req = request.Request(url,headers=headers,
data = parse.urlencode(data).encode('utf-8'),method = 'POST')
# 也可以通过Request.add_header()来添加
resp = request.urlopen(req)
print(resp.read().decode('utf-8'))
ProxyHandler处理器(代理):
- 代理的原理:在请求目的网站之前,我们先请求代理服务器,然后让代理服务器去请求目的网站,代理服务器拿到目的网站的数据后,再转发给我们。
- 一些好用的网站:
- http://httpbin.org:这个网站可以方便的查看http请求的一些参数。
- 西刺免费代理IP: http://www.xicidaili.com/
- 快代理: http://www. kuaidaili.com/
- 代理云: http://www.dailiyun.com/
- 在代码中使用代理:
- 使用
urllib.request.ProxyHandler
,传入一个代理,这个代理是一个字典,字典的key依赖于代理服务器能够接收的类型,一般是http
或者https
,值是ip:port
。 - 使用上一步创建的
handler
,以及request.build_opener
创建一个opener
对象。 - 使用上一步创建的
opener
,调用open
函数,发起请求。
示例代码如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14from urllib import request
# 未使用代理
url = 'http://httpbin.org/ip'
req = request.urlopen(url)
print(req.read())
# 使用代理
url = 'http://httpbin.org/ip'
#下面的代理ip是通过我们网站得到的一些免费代理ip
handler = request.ProxyHandler({"http":"114.113.220.192:80"})
opener = request.build_opener(handler)
req = opener.open(url)
print(req.read())
- 使用
你用的免费代理可能不会成功访问,所以要多试几个哦
Cookie
Cookie模拟登录
Cookie,指某些网站为了辨别用户身份、进行session跟踪而储存在用户本地终端上的数据(通常经过加密)。在网站中,http请求是无状态的。也就是说即使第一次和服务器连接后并且登录成功后,第二次请求服务器依然不能知道当前请求是哪个用户。cookie 的出现就是为了解决这个问题,第一次登录后服务器返回一些数据(cookie) 给浏览器,然后浏览器保存在本地,当该用户发送第二次请求的时候,就会自动的把上次请求存储的cookie 数据自动的携带给服务器,服务器通过浏览器携带的数据就能判断当前用户是哪个了。cookie 存储的数据量有限,不同的浏览器有不同的存储大小,但-般不超过4KB。因此使用cookie只能存储一些小量的数据。
cookie的格式:
1 | 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协议下起作用。
比如说有些网站需要登录后才能访问某个页面,在登录之前,你想抓取某个页面内容是不允许的,他会给你自动跳转到登录或注册页面了。那么我们可以利用Urllib2库保存我们登录的Cookie,然后再抓取其他页面就达到目的了。
- 第一种解决方案:在headers里添加key:Cookie成员,value:也是包括在Request Headers里面的。
这里用cookie爬取某一微博博主界面1
2
3
4
5
6
7
8
9
10
11
12
13
14# coding:utf-8
from urllib import request
url = 'https://weibo.com/seize?refer_flag=0000015010_&from=feed&loc=avatar&is_all=1'
headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.26 Safari/537.36 Core/1.63.5944.400 LBBROWSER/10.1.3378.400',
'Cookie':'数据太多省略'
}
req = request.Request(url = url,headers= headers)
resp = request.urlopen(req)
with open('weibo.html','w',encoding='utf-8') as fp:
fp.write(resp.read().decode('utf-8','ignore'))
虽然最后结果是返回给你的是一个假的代码,但方法就是这样。
还要说明一点:这里的write函数写入的必须是str类型(read()读出来是一个bytes类型),bytes通过decode变成str,str通过encode变成bytes类型
- 第二种方法:http.cookiejar模板
http.cookiejar模块:
该模块主要的类有CookieJary FileCookieJar、 MoillaCookieJar、 LWPCookieJar。这四个类的作用分别如下:
- CookieJar:管理HTTP cookie值、存储HTTP请求生成的cookie、向传出的HTTP请求添加cookie的对象。整个cookie都存储在内存中,对CookieJar实例进行垃圾回收后cookie也将丢失。
- FileCookieJar (flename,delayload=None,policy=None):从CookieJar派生而来,用来创建FileCookieJar实例,检索cookie信息并将cookie存储到文件中。filename是存储cookie的文件名。delayload为True时支持延迟访问访问文件,即只有在需要时才读取文件或在文件中存储数据。
- MoillaCookieJar (filename,delayload=None,policy=None):从FileCookieJa派生而来,创建与Mozilla浏览器cookies.txt兼容的FileCookieJar实例。
- LWPCookieJar (filename,delayload=None,policy=None):从FileCookieJar派生 而来,创建与libwww-perl标准的Set-Cookie3文件格式兼容的FileCookieJar实例。
下面利用http.cookiejar和request .HTTPCookieProcessor登录人人网,代码如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49#encoding: utf-8
from urllib import request
from urllib import 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():
# 1. 登录
# 1.1 创建一个cookiejar对象
cookiejar = CookieJar()
# 1.2 使用cookiejar创建一个HTTPCookieProcess对象
handler = request.HTTPCookieProcessor(cookiejar)
# 1.3 使用上一步创建的handler创建一个opener
opener = request.build_opener(handler)
return opener
def login_renren(opener):
# 1.4 使用opener发送登录的请求(人人网的邮箱和密码)
# 把这些cookie数据写到opener里面
data = {
'email':"970138074@qq.com",
'password': "pythonspider"
}
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)
def visit_profile(opener):
# 2. 访问个人主页
dapeng_url = "http://www.renren.com/880151247/profile"
# 获取个人主页的页面的时候,不要新建一个opener
# 而应该使用之前的那个opener,因为之前的那个opener已经包含了登录所需要的cookie信息
req = request.Request(dapeng_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)
保存cookie到本地
1 | #encoding: utf-8 |
加载本地的cookie信息并使用
1 | #encoding: utf-8 |
Requests库
发送get请求:
发送get请求,直接调用requests.get
就可以了。想要发送什么类型的请求,就调用什么方法。1
response = requests.get("https://www.baidu.com/")
response的一些属性:
1 | import requests |
response.text和response.content的区别:
- response.content:这个是直接从网络上面抓取的数据。没有经过任何解码。所以是一个bytes类型。其实在硬盘上和在网络上传输的字符串都是bytes类型。
- response.text:这个是str的数据类型,是requests库将response.content进行解码的字符串。解码需要指定一个编码方式,requests会根据自己的猜测来判断编码的方式。所以有时候可能会猜测错误,就会导致解码产生乱码。这时候就应该使用
response.content.decode('utf-8')
进行手动解码。这里不一定是’utf-8’,你可以检查元素网页的编码格式
发送post请求:
发送post请求非常简单。直接调用requests.post()
方法就可以了。
如果返回的是json数据。那么可以调用response.json()
来将json字符串转换为字典或者列表。
使用代理:
在请求方法中,传递proxies
参数就可以了。例示代码如下:1
2
3
4
5
6
7
8
9
10
11
12
13import requests
url = 'http://httpbin.org/get'
headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.26 Safari/537.36 Core/1.63.5944.400 LBBROWSER/10.1.3378.400'
}
proxy = {
'http':'163.204.243.182:9999'
}
resp = requests.get(url ,headers = headers,proxies = proxy)
print(resp.text)
处理cookie:
如果想要在多次请求中共享cookie。那么应该使用session。示例代码如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14import requests
url = "http://www.renren.com/PLogin.do"
data = {"email":"970138074@qq.com",'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()
# 访问登录页面,并把信息存储在seesion里面
session.post(url,data=data,headers=headers)
# 用这个session去获取需要登录后才能访问的界面
response = session.get('http://www.renren.com/880151247/profile')
with open('renren.html','w',encoding='utf-8') as fp:
fp.write(response.text)
处理没有授权的https协议:
对于那些已经不被信任的SSL整数的网站,添加一个verify参数,示例代码如下:1
2resp = requests . get( http://www.12386. cn/mormhweb/' ,verify=False)
print(resp. content . decode("utf-8'))