目录
在网站设计中,纯粹HTML格式的网页通常被称为静态网页,早期的网站一般都是由静态网页制作的。在静态网页抓取中,有一个强大的Requests库能够让你轻易地发送HTTP请求。
1 获取响应内容
在Requests中,常用的功能是获取某个网页的内容。
import requests
r = requests.get('https://www.baidu.com/')
print("文本编码:", r.encoding)
print("响应状态码:", r.status_code)
print("字符串方式的响应体:", r.text)
注:
- r.text是服务器响应的内容,会自动根据响应头部的字符编码进行解码;
- r.encoding是服务器内容使用的文本编码;
- r.status_code用于检测响应的状态码,如果返回200,就表示请求成功了;如果返回的是4××,就表示客户端错误;如果返回的是5××,则表示服务器错误响应;
- r.content是字节方式的响应体,会自动解码gzip和deflate编码的响应数据;
- r.json()是Requests中内置的JSON解码器
2 定制Requests
有些网页需要对Requests的参数进行设置才能获取需要的数据,这包括传递URL参数、定制请求头、发送POST请求、设置超时等。
2.1 传递URL参数
为了请求特定的数据,我们需要在URL的查询字符串中加入某些数据。如果是自己构建URL,那么数据一般会跟在一个问号后面,并以键/值的形式放在URL中。
在Requests中,可以直接把这些参数保存在字典中,用params(参数)构建至URL中。
import requests
key_dict = {'key1': 'value1', 'key2': 'value2'}
r = requests.get('http://httpbin.org/get', params=key_dict)
print("URL已经正确编码:", r.url)
print("字符串方式的响应体:\n", r.text)
2.2 定制请求头
请求头Headers提供了关于请求、响应或其他发送实体的信息。对于爬虫而言,请求头十分重要,如果没有指定请求头或请求的请求头和实际网页不一致,就可能无法返回正确的结果。
Requests并不会基于定制的请求头Headers的具体情况改变自己的行为,只是在最后的请求中,所有的请求头信息都会被传递进去。
如何获取请求头:
使用Chrome浏览器的“检查”命令。使用Chrome浏览器打开要请求的网页,右击网页的任意位置,在弹出的快捷菜单中单击“检查”命令。
在随后打开的页面中单击Network选项。
图1 单击Network选项
在左侧的请求资源中找到需要请求的网页,(如果没有,则点击网页左上角的刷新按钮),本例为http://www.santostang.com。单击需要请求的网页,在Headers中可以看到Requests Headers的详细信息。
图2 找到需要请求网页的头信息
因此,我们可以看到请求头的信息为:
图3 请求网页的头信息
提取请求头中重要的部分,可以把代码改为:
import requests
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36',
'Host': 'www.santostang.com'}
r = requests.get('http://www.santostang.com/', headers=headers)
print("响应状态码:", r.status_code)
2.3 发送POST请求
除了GET请求外,有时还需要发送一些编码为表单形式的数据,如在登录的时候请求就为POST,因为如果用GET请求,密码就会显示在URL中,这是非常不安全的。如果要实现POST请求,简单地传递一个字典给Requests中的data参数,这个数据字典就会在发出请求的时候自动编码为表单形式。
可以看到,form变量的值为key_dict输入的值,这样POST请求就发送成功了。
2.4 超时
有时,爬虫会遇到服务器长时间不返回,这是爬虫程序就会一直等待,造成爬虫程序没有顺利地执行。因此,可以使用Requests在timeout参数设定的秒数结束之后停止等待响应。
import requests
link = "http://www.santostang.com/"
r = requests.get(link, timeout=0.001)
3 Requests爬虫实践:TOP250电影数据
本时间项目的目的是获取豆瓣电影TOP250的所有电影的名称,网页地址为:豆瓣电影 Top 250。在此爬虫中,将请求头定制为实际浏览器的请求头。
3.1 网站分析
按照2.2中的方法提取其中重要的请求头。
第一页只有25个电影,如果要获取所有的250个电影,就需要获取总共10页的内容。
通过单击第二页可以发现页码地址变成了https://movie.douban.com/top250?start=25&filter=
单击第三页可以发现页码地址为https://movie.douban.com/top250?start=50&filter=
即每多一页,就给网页地址的start参数加上25
3.2 项目实战
通过以上分析可以发现,使用requests获取电影网页的代码,并利用for循环翻页,其代码如下:
import requests
def get_movies():
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36',
'Host': 'movie.douban.com'}
for i in range(0, 10):
link = 'https://movie.douban.com/top250?start=' + str(i * 25) + '&filter='
r = requests.get(link, headers=headers, timeout=10)
print('第', str(i + 1), '页响应状态码: ', r.status_code)
print(r.text)
get_movies()
运行上述代码,得到的结果为:第 1 页响应状态码:200
这时,得到的结果知识网页的HTML代码,我们需要从中提取需要的电影名称,其代码如下:
import requests
from bs4 import BeautifulSoup
def get_movies():
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36',
'Host': 'movie.douban.com'}
movie_list = []
for i in range(0, 10):
link = 'https://movie.douban.com/top250?start=' + str(i * 25) + '&filter='
r = requests.get(link, headers=headers, timeout=10)
print('第', str(i + 1), '页响应状态码: ', r.status_code)
soup = BeautifulSoup(r.text, 'lxml')
div_list = soup.find_all('div', class_='hd')
for each in div_list:
movie = each.a.span.text.strip()
movie_list.append(movie)
return movie_list
movies = get_movies()
print(movies)
参考资料
[1] 唐松.2019.Python网络爬虫从入门到实践(第2版)[M].北京:机械工业出版社