1. 概念
爬虫不是动物,而是一种计算机程序。
这种程序有自己特定的功能,能按照使用者给定的一系列规则自行浏览万维网并获取需要的信息。此类程序被称为 网络爬虫(web crawler) 或 网络蜘蛛(spider)。
它具有智能分析能力,也称为 机器人程序 。
爬虫的应用应用领域:
如百度、谷歌等以搜索为主的公司,就是利用其自行研发的爬虫程序在互联网上对网页中的数据进行爬取、分析、归类、存储……再提供给用户使用。
新闻聚合应用也是利用爬虫程序爬取各新闻网站上的新闻信息,进行分检归类后提供给使用者。
爬虫程序可运用于各种需要数据分析的应用领域。如价格分析,根据商品关键字爬取各商城中商品价格,对价格进行比较、分析后展示给用户一个直观的对比表。
爬虫程序从网络上爬取数据时,需要遵守 Rebots 协议。
Rebots 协议是网站拟定的资源共享清单,规定爬虫在本网站爬取数据时,哪些资源可以爬取,哪些资源不可以爬取。
爬虫程序的工作流程:
- 确定目标网页。此页为起始页或叫入口页面。
- 获取页面的数据,通过某种方式(如正则表达式)获取页面中的相关信息。并可提取页面中链接,以递归方式继续对页面数据进行分析,提取。
- 将信息持久化存储,可备后续的处理。
2. Python 爬虫模块
爬虫程序的核心逻辑之一便是通过网络请求模式,下载指定页面的数据。
爬虫程序的本质就是一个网络应用程序。
Python 提供了丰富的库或模块可协助开发者快速开发此类网络应用程序。
2.1 urllib 库
urllib 库是 python 内置库,不需要另外安装。完整的 urllib 库包括如下 5 大模块:
- urllib.request :可使用不同的协议发送请求包并获取请求之后的响应结果。
- urllib.response :用来解析响应包数据。
- urllib.error: 包含了 urllib.request 产生的异常。
- urllib.parse: 用来解析和处理 URL。
- urllib.robotparse: 用来解析页面的 robots.txt 文件。
使用 urllib.request 模块发送网络请求:
import urllib.request
# 基于 https 协议的 url 地址
url = "https://www.cnblogs.com/guo-ke/p/15951196.html"
# 构建一个请求对象
req = urllib.request.Request(url)
# 使用 urlopen 方法发送请求包
with urllib.request.urlopen(req) as resp:
# 解析数据
data = resp.read()
print(data.decode())
- urllib.request.Request() 类说明:构建请求包。
类原型声明:
class Request:
def __init__(self, url, data=None, headers={},origin_req_host=None, unverifiable=False,method=None):
#…… 其它代码块
构造方法参数说明
- url: 要请求的 url 地址 。
- data: data 必须是bytes(字节流)类型,如果是字典,可以用 urllib.parse 模块里的 urlencode( ) 编码
headers: headers 是一个字典类型,用来描述请求头信息。
可在构造方法中指定,也可以通过调用 add_header( ) 方法添加
默认 User-Agent 是 Python-urllib
- origin_req_host: 指定请求方的 host 名称或者 ip 地址。
- unverifiable:设置网页是否需要验证,默认是 False。
- method: 用来指定请求使用的方法,如 GET、POST 或 PUT 等。
很多网站具有反爬虫设置,除了浏览器之外的访问均认定为非法请求。所以爬虫程序需要把自己伪装成浏览器。
from urllib import request, parse
url = 'http://www.guo-ke.com/post'
headers = {
# 伪装成谷歌浏览器
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36',
'Host': 'guo-ke.org'
}
dict = {
'name': 'guoke',
'key':'python'
}
# 数据必须是字节流
data = bytes(parse.urlencode(dict), encoding='utf8')
'''
# 转换成 URL 格式的字符串
data = parse.urlencode(dict)
# 编码成字节流数据
data = data.encode()
'''
request = request.Request(url=url, data=data, headers=headers, method='POST')
# req.add_header('User-Agent', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36')
with request.urlopen(req) as response:
res=(response.read()
print(res.decode('utf-8'))
Tip: 当使用了 data 参数或指定 method="POST" 则为POST 请求。
GET 请求也能附加请求参数:https://www.baidu.com/s?wd=java
- urllib.request.urlopen( ) 方法说明:发送网络请求。
def urlopen(url, data=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT,
*, cafile=None, capath=None, cadefault=False, context=None):
参数说明:
- url: 可以接收一个 URL 字符串 或一个 urllib.request.Request 对象。
- data: POST 请求时的数据,GET 请求设置为 None。
- timeout: 设置网站的访问超时时间。仅仅用于使用 HTTP、HTTPS、FTP 协议请求连接时。
cafile、capath: 当使用 HTTPS 请求时,用来指定 CA 数字证书。
cafile 指定数字证书文件。
capath 指定包含的数字认证文件的目录。
返回类型说明: 无论使用何种协议发送请求后返回的对象都会包括 3 个通用方法。
- geturl( ) 返回请求的资源URL。
- info( ) 返回元数据信息,如消息头。
- getcode( ) 返回响应的状态码. 如果有错误则会抛出 URLError 异常。
当使用 http 或 https 协议请求后返回的是一个 http.client.HTTPResponse 对象,此对象除了上面的 3 个方法,还包括:
- read( ): 获取响应返回的 bytes 类型数据,只能使用一次,输出时需要使用 decode() 解码。
- getheaders( ): 获取返回的响应头信息。
使用 urllib.request 下载一张图片:
爬虫程序强大之处在于能批量、递归下载用户所需要的数据,一个强大的逻辑背后的思想可能就是一个简单的原理支撑的。我们可以先试着下载一张图片以小窥大。
import urllib.request
# 图片URL
url = "https://img2022.cnblogs.com/blog/2749732/202202/2749732-20220222195931956-448995015.jpg"
with urllib.request.urlopen(url) as resp:
data = resp.read()
with open("d:/my_file.jpg", "wb") as f:
f.write(data)
打开对应盘符,可以查阅到图片已经下载成功。
urllib.request 还提供有一个更方便的 urlretrieve( ) 方法。可直接以文件方式存储下载下来的字节流数据。
from urllib import request
url = "https://img2022.cnblogs.com/blog/2749732/202202/2749732-20220222195931956-448995015.jpg"
# urlretrieve() 方法传入的第二个参数为文件保存的位置,以及文件名。
request.urlretrieve(url, 'd:/temp.jpg')
2.2. requests 库
requests 是基于urllib 编写的第三方库,使用时,需要下载安装:
pip3 install requests
主要提供了 2 个方法:
1. get( ) 方法用来发送 GET 请求。
def get(url, params=None, **kwargs):
#……
参数说明:
- url:需要请求的 url 资源(字符串类型)。
- params:查询数据,可以是字典、列表、元组、字节类型。
- kwargs:以键值对描述的请求消息头参数。
基本 GET 使用:
import requests
# 用get方式发送请求并获得响应
response = requests.get('https://www.cnblogs.com/guo-ke/p/15925214.html')
# 用text查看响应内容
print(response.text)
带参数 get 请求
import requests
response = requests.get('https://www.baidu.com/s?wd=java')
# 将参数拼接到url后面,用问号分隔,参数间用&来分隔
print(response.text)
字典格式的参数
import requests
data = {
'wd': 'java'
}
response = requests.get('https://www.baidu.com/s', params=data)
# 用字典的形式传递给params参数,不需要自己写url编码
print(response.text)
GET 方法返回一个 Responese 对象,此对象提供有相应属性或方法解析响应包中的数据。
- response.encoding:获取当前的编码。
- response.encoding = 'utf-8':设置编码。
- response.text:自动根据响应头部的字符编码进行解码。
- response.content:以字节形式(二进制)返回。
- response.headers:以字典对象存储服务器响应头,字典键不区分大小写,若键不存在则返回 None。
- response.status_code:响应状态码。
- response.raw:返回原始响应体,也就是 urllib 的 response 对象,使用 response.raw.read()
- response.json() :Requests 中内置的JSON解码器,以json形式返回,前提返回的内容确保是json格式的,不然解析出错会抛异常。
下载一张图片
import requests
#;图片地址
url = "https://img2022.cnblogs.com/blog/2749732/202202/2749732-20220222195931956-448995015.jpg"
#请求头元数据
headers = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36'
}
response = requests.get(url, headers=headers)
# 获取字节流数据
data = response.content
#保存字节流数据
with open("d:/test.jpg", "wb") as f:
f.write(data)
2. post() 方法:以 post 方式发送请求
def post(url, data=None, json=None, **kwargs):
参数说明:
- url:字符串类型的需要请求的 url 资源。
- data:发送数据,可以是字典、列表、元组、字节类型
- json:json 格式的数据。
- kwargs:以键值对描述的请求头参数。
基本使用方式
import requests
data={'name':'zhuzhu','age':'23'}
headers={
'User-Agent':'Mozilla/5.0(Macintosh;Intel Mac OS X 10_11_4)AppleWebKit/537.36(KHTML,like Gecko)Chrome/52.0.2743.116 Safari/537.36'
}
response=requests.post("http://httpbin.org/post",data=data,headers=headers)
#数据必须是json 封装
print(response.json())
3. 总结
requests 在基于 urllib 编写的第三方库,相比较 urllib 使用起来更简单。对其 API 介绍 ,本文只做了些简单描述。更多方法或使用可查阅文档。