在开始之前,请确保你的电脑上已经安装好了BeautifulSoup库,可以通过在命令行中输入pip install beautifulsoup4来进行安装 。
一、数据解析在爬取之前,我们需要检测下响应状态码是否为200,如果请求失败,我们将爬取不到任何数据:
import requestsre = requests.get('https://book.douban.com/top250')if re.status_code == 200:print('请求成功!')else:print('请求失败!响应状态码为{}'.format(re.status_code))
响应状态码为418,我们请求失败了,这是为什么呢?因为豆瓣有反爬虫机制,我们无法通过直接请求服务器来爬取数据,必须在发起请求之前将自己伪装起来 。
1.1 反爬虫反爬虫是网站限制爬虫的一种策略 。它并不是禁止爬虫(完全禁止爬虫几乎不可能,也可能误伤正常用户),而是限制爬虫,让爬虫在网站可接受的范围内爬取数据,不至于导致网站瘫痪无法运行 。常见的反爬虫方式有判别身份和IP限制两种,这里我们先介绍前者,后者稍后再提及 。
有些网站在识别出爬虫后,会拒绝爬虫进行访问,比如之前提到的豆瓣 。那我们怎样做才能不被识别出来呢?在此之前,我们先尝试一下直接爬取:
import requestsre = requests.get('https://book.douban.com/top250')print(re.text)
结果是什么都没有输出,因为豆瓣将我们的爬虫识别了出来并拒绝提供内容 。你可能会有疑问,爬虫不是模拟浏览器访问网站、获取网页源代码的吗?为什么就被识别出来了呢?事实上,无论是浏览器还是爬虫,访问网站时都会带上一些信息用于身份识别,而这些信息都被存储在一个叫请求头(request headers)的地方 。
服务器会通过请求头里的信息来判别访问者的身份 。请求头里的字段有很多,我们暂时只需了解user-agent(用户代理)即可 。user-agent里包含了操作系统、浏览器类型、版本等信息,通过修改它我们就能成功地伪装成浏览器并爬取我们想要的数据 。
那么如何找到user-agent呢?操作步骤如下:
- 首先按F12(或Fn+F12),然后单击上方的Network标签 。
- 此时打开https://book.douban.com/top250,在Name一列中找到top250并单击 。
- 在右边的Headers中找到Request Headers,User-Agent就在其中 。
我们只需定义一个字典(请求头字段作为键,字段内容作为值)传递给headers参数即可,方法如下:
import requestsheaders = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36'}re = requests.get('https://book.douban.com/top250', headers=headers)print(re.text)
这样就能正常输出内容了(结果太长这里不展示) 。除了user-agent之外的其他请求头字段也能以同样的方式添加进去,但大部分情况下我们只需要添加user-agent字段即可 。当我们加了user-agent字段还是无法获取到数据时,说明该网站还通过别的信息来验证身份,我们可以将请求头里的字段都添加进去再尝试 。1.2 BeautifulSoup 对象接下来我们将网页源代码解析成BeautifulSoup对象:
import requestsfrom bs4 import BeautifulSoupheaders = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36'}re = requests.get('https://book.douban.com/top250', headers=headers)soup = BeautifulSoup(re.text, 'html.parser')
需要注意的是,创建BeautifulSoup对象时需要传入两个参数,第一个参数是要解析的HTML文本,即网站源代码的字符串形式re.text 。第二个参数是解析HTML的解析器,html.parser是Python中内置的解析器,较为简单方便 。接下来我们分别打印soup和re.text,观察其内容有无区别:
import requestsfrom bs4 import BeautifulSoupheaders = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36'}re = requests.get('https://book.douban.com/top250', headers=headers)soup = BeautifulSoup(re.text, 'html.parser')print(soup)print(re.text)
仔细观察后会发现两次打印的内容完全一样!既然都一样,我们何苦费这么大力将网页源代码解析成BeautifulSoup对象呢?为什么不直接打印re.text呢?
推荐阅读
- Python多线程死锁问题的巧妙解决方法
- 3种方法实现python-matplotlib显示中文
- python第三方库uiautomator2 操作方法汇总
- 不要怕,告别乱如麻的Python报错输出,一行代码就够了
- 每天一个爬虫练习,爬取天气数据,适合新手
- Python 中如何实现参数化测试?
- 快速理解并口、串口、COM口的区别
- Python 为什么没有 void 关键字?
- 快速掌握shell脚本的各种循环语句
- 用Python识别图片中的文字