在网站设计中,纯粹
HTML
格式的网页通常被称为静态网页,早期的网站一般都是由静态网页制作的。
在网络爬虫中,静态网页的数据比较容易获取,因为所有数据都呈现在网页的HTML代码中。
相对而言,使用AJAX
动态加载网页的数据不一定会出现在HTML
代码中,这就给爬虫增加了困难。
在静态网页抓取中,有一个强大的Requests
库能够让你轻易地发送HTTP
请求。这篇文章主要介绍如何使用Requests库获取响应内容,最后可以通过定制Requests的一些参数来满足我们的需求。
pip install requests
import requests
r=requests.get('http://www.santostang.com/')
print("文本编码:", r.encoding)
print("响应状态码:", r.status_code)
print("字符串方式的响应体:", r.text)
print('字节方式的响应体:', r.content)
print('Request中内置的JSON解码器', r.json())
输出:
本编码: UTF-8
响应状态码: 200
字符串方式的响应体: <!DOCTYPE html>...
r.encoding
是服务器内容使用的文本编码。r.status_code
用于检测响应的状态码,如果返回200,就表示请求成功了;如果返回的是4xx,就表示客户端错误;返回5xx则表示服务器错误响应。我们可以用r.status_code
来检测请求是否正确响应。r.text
是服务器响应的内容,会自动根据响应头部的字符编码进行解码。r.content
是字节方式的响应体,会自动解码gzip
和deflate
编码的响应数据。r.json()
是Requests
中内置的JSON解码器
。有些网页需要对Requests的参数进行设置才能获取需要的数据,这包括传递URL参数params
、定制请求头headers
、发送POST请求data
、设置超时timeout
等。
params
如:http://httpbin.org/get?key1=value1&key2=value2
params
构建至URL中。例如,传递key1=value1
和key2=value2
到http://httpbin.org/get
,可以这样编写:
import requests
key_dict = {
'key1': 'value1', 'key2': 'value2'}
r = requests.get('http://httpbin.org/get', params=key_dict)
print('URL已经正确编码:', r.url)
print("文本编码:", r.encoding)
print("响应状态码:", r.status_code)
print('字符串方式的响应体:\n', r.text)
输出:
URL已经正确编码: http://httpbin.org/get?key1=value1&key2=value2
文本编码: utf-8
响应状态码: 200
字符串方式的响应体:
{
"args": {
# 使用get请求,此处的args的key1,key2值会被显示出来
"key1": "value1",
"key2": "value2"
},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Host": "httpbin.org",
"User-Agent": "python-requests/2.25.1",
"X-Amzn-Trace-Id": "Root=1-6026482c-41a9bd646c22ba00497a8a63"
},
"origin": "118.212.203.240",
"url": "http://httpbin.org/get?key1=value1&key2=value2"
}
headers
请求头
Headers
提供了关于请求、响应或其他发送实体的信息。
对于爬虫而言,请求头十分重要,如果没有指定请求头或请求的请求头和实际网页不一致,就可能无法返回正确的结果。
Requests
并不会基于定制的请求头Headers
的具体情况改变自己的行为,只是在最后的请求中,所有的请求头信息都会被传递进去
import requests
# key_dict = {'key1': 'value1', 'key2': 'value2'}
# 指定请求头
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36 Edg/88.0.705.63',
'Host': 'www.santostang.com'}
# r = requests.get('http://httpbin.org/get', params=key_dict)
r = requests.get('http://www.santostang.com/', headers=headers)
print('URL已经正确编码:', r.url)
print("文本编码:", r.encoding)
print("响应状态码:", r.status_code)
print('字符串方式的响应体:\n', r.text)
输出:
URL已经正确编码: http://www.santostang.com/
文本编码: UTF-8
响应状态码: 200
data
除了
GET
请求外,有时还需要发送一些编码为表单形式的数据,如在登录的时候请求就为POST
,因为如果用GET
请求,密码就会显示在URL
中,这是非常不安全的。
如果要实现POST
请求,只需要简单地传递一个字典给Requests
中的data
参数,这个数据字典就会在发出请求的时候自动编码为表单形式。
import requests
key_dict = {
'key': 'value1', 'key2': 'value2'}
r = requests.post('http://httpbin.org/post', data=key_dict)
print('URL已经正确编码:', r.url)
print("文本编码:", r.encoding)
print("响应状态码:", r.status_code)
print('字符串方式的响应体:\n', r.text)
输出:
URL已经正确编码: http://httpbin.org/post
文本编码: utf-8
响应状态码: 200
字符串方式的响应体:
{
"args": {
}, # 使用post请求,此处的args的key1,key2值会被隐藏
"data": "",
"files": {
},
"form": {
# form变量的值为key_dict输入的值
"key": "value1",
"key2": "value2"
},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Content-Length": "22",
"Content-Type": "application/x-www-form-urlencoded",
"Host": "httpbin.org",
"User-Agent": "python-requests/2.25.1",
"X-Amzn-Trace-Id": "Root=1-60264cca-63d77c2c1c8bcf8c1042057b"
},
"json": null,
"origin": "118.212.203.240",
"url": "http://httpbin.org/post"
}
timeout
有时爬虫会遇到服务器长时间不返回,这时爬虫程序就会一直等待,造成爬虫程序没有顺利地执行。
因此,可以用Requests
在timeout
参数设定的秒数结束之后停止等待响应。
意思就是,如果服务器在timeout
秒内没有应答,就返回异常。一般会把这个值设置为20秒。
静态网页抓取实践项目的目的是获取豆瓣电影TOP250的所有电影的名称,网页地址为:https://movie.douban.com/top250。在此爬虫中,将请求头定制为实际浏览器的请求头。
#! /usr/bin/python
# coding: UTF-8
import requests
from bs4 import BeautifulSoup
def get_movies():
# 定制请求头 requests
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36 Edg/88.0.705.63',
'Host': 'movie.douban.com'}
movie_list = []
# 1页25部电影,for循环获取250部
for i in range(0, 10):
link = 'https://movie.douban.com/top250?start=' + str(i*25)
# 发送get请求,设置超时 timeout
r = requests.get(link, headers=headers, timeout=10)
print('================================================================================================================')
# 检验状态
print(str(i+1), ' 页响应状态码:', r.status_code)
print('URL已经正确编码:', r.url)
print("文本编码:", r.encoding)
# print(r.text) # r.text里的内容为html文本形式
# 解析网页
soup = BeautifulSoup(r.text, 'lxml')
div_list = soup.find_all('div', class_='hd')
# div_info_list = soup.find_all('div', class_='item')
# 把电影名保存到movie_list列表中
for each in div_list:
movieName = each.a.span.text.strip()
movie_list.append(movieName) # 把电影都保存到字典后,由下边的打印语句打印出总的list
print(movie_list)
return movie_list
# 调用函数
movies = get_movies()