前面介绍了如何在浏览器中获取和查看网页的源代码,那么如何在Python中获取网页的源代码呢?这里介绍Python的一个第三方模块Requests,它可以模拟浏览器发起网络请求,从而获取网页源代码。该模块的安装命令为“pip install requests”。
发起网络请求、获取网页源代码主要使用的是Requests模块中的get()函数。下面以获取百度首页的网页源代码为例讲解get()函数的用法。演示代码如下:
1 import requests 2 headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36'} 3 url = 'https://www.baidu.com' 4 response = requests.get(url=url, headers=headers) 5 result = response.text 6 print(result)
第1行代码用于导入Requests模块。
第2行代码中的变量headers是一个字典,它只有一个键值对:键为“User-Agent”,意思是用户代理;值代表以哪种浏览器的身份访问网页,不同浏览器的User-Agent值不同,这里使用的“Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36”是谷歌浏览器的User-Agent值。
这里以谷歌浏览器为例讲解User-Agent值的获取方法。打开谷歌浏览器,在地址栏中输入“chrome://version”(注意要用英文冒号),按【Enter】键,在打开的页面中找到“用户代理”项,后面的字符串就是User-Agent值,如下图所示。
第3行代码将百度首页的网址赋给变量url。需要注意的是,网址要完整。可以在浏览器中访问要获取网页源代码的网址,成功打开页面后,复制地址栏中的完整网址,粘贴到代码中。
第4行代码使用Requests模块中的get()函数对指定的网址发起请求,服务器会根据请求的网址返回一个response对象。参数url用于指定网址,参数headers则用于指定以哪种浏览器的身份发起请求。如果省略参数headers,对有些网页也能获得源代码,但是对相当多的网页则会爬取失败,因此,最好还是不要省略该参数。
除了url和headers,get()函数还有其他参数,最常用的是params、timeout、proxies。在实践中可根据遇到的问题添加对应的参数。
参数params用于在发送请求时携带动态参数。
参数timeout用于设置请求超时的时间。由于网络原因或其他原因,不是每次请求都能被网站服务器接收到,如果一段时间内还未返回响应,Requests模块会重复发起同一个请求,多次请求未成功就会报错,程序停止运行。如果不设置参数timeout,程序可能会挂起很长时间来等待响应结果的返回。
参数proxies用于为爬虫程序设置代理IP地址。网站服务器在接收请求的同时可以获知发起请求的计算机的IP地址。如果服务器检测到同一IP地址在短时间内发起了大量请求,就会认为该IP地址的用户是爬虫程序,并对该IP地址的访问采取限制措施。使用参数proxies为爬虫程序设置代理IP地址,代替本地计算机发起请求,就能绕过服务器的限制措施。
第5行代码通过response对象的text属性获取网页源代码,第6行代码使用print()函数输出获取的网页源代码。
运行上述代码,即可输出百度首页的源代码,如下图所示。
有时用Python获得的网页源代码中会有多处乱码,这些乱码原本应该是中文字符,但是由于Python获得的网页源代码的编码格式和网页实际的编码格式不一致,从而变成了乱码。要解决乱码问题,需要分析编码格式,并重新编码和解码。
以获取新浪网首页( https://www.sina.com.cn )的网页源代码为例,演示代码如下:
1 import requests 2 headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36'} 3 url = 'https://www.sina.com.cn' 4 response = requests.get(url=url, headers=headers) 5 result = response.text 6 print(result)
代码运行结果如下图所示,可以看到有多处乱码。
先来查看网页实际的编码格式。用谷歌浏览器打开新浪网首页,按【F12】键打开开发者工具,展开位于网页源代码开头部分的<head>标签(该标签主要用于存储编码格式、网页标题等信息),如下图所示。<head>标签下的<meta>标签中的参数charset对应的就是网页实际的编码格式。
可以看到新浪网首页的实际编码格式为UTF-8。接着利用response对象的encoding属性查看Python获得的网页源代码的编码格式,演示代码如下:
1 import requests 2 headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36'} 3 url = 'https://www.sina.com.cn' 4 response = requests.get(url=url, headers=headers) 5 print(response.encoding)
代码运行结果如下:
1 ISO-8859-1
可以看到,Python获得的网页源代码的编码格式为ISO-8859-1,与网页的实际编码格式UTF-8不一致。UTF-8和ISO-8859-1都是文本的编码格式,前者支持中文字符,而后者属于单字节编码,适用于英文字符,无法表示中文字符,这就是Python获得的内容中中文字符变成乱码的原因。
要解决乱码问题,可以通过为response对象的encoding属性赋值来指定正确的编码格式。演示代码如下:
1 import requests 2 headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36'} 3 url = 'https://www.sina.com.cn' 4 response = requests.get(url=url, headers=headers) 5 response.encoding = 'utf-8' 6 result = response.text 7 print(result)
前面在开发者工具中看到网页的实际编码格式为UTF-8,所以第5行代码将response对象的encoding属性赋值为'utf-8'。代码运行结果如下图所示,可以看到成功解决了乱码问题。
除了UTF-8,中文网页常见的编码格式还有GBK和GB2312。对于使用这两种编码格式的网页,可将上述第5行代码中的'utf-8'修改为'gbk'。
除了利用开发者工具查看网页的实际编码格式,还可以通过调用response对象的apparent_encoding属性,让Requests模块根据网页内容自动推测编码格式,再将推测结果赋给response对象的encoding属性,即将上述第5行代码修改为如下代码:
1 response.encoding = response.apparent_encoding
至此,用Requests模块获取网页源代码的知识就讲解完毕了。但这只是完成了爬虫任务的第一步,这些源代码中通常只有部分内容是我们需要的数据,所以爬虫任务的第二步就是从网页源代码中提取数据。具体的方法有很多,2.3节和2.4节将分别介绍常用的两种:正则表达式和BeautifulSoup模块。