爬虫原理
什么是爬虫
爬虫是一种自动化程序,用于在互联网上浏览和检索信息。其原理是通过模拟人类用户的行为在互联网上进行网页的访问并提取所需要的数据。
HTTP基本原理
1、什么是URL
即在浏览器地址栏填写目标网页的URL地址,例:python下载页面的URL地址是www.python.org/downloads 其中https表示网页的访问协议,www.python.org 表示访问的域名,downloads表示访问的路径。
2、HTTP协议
HTTP协议(HyperText Transfer Protocol)是一种应用层协议,用于在分布式、协作式和超媒体信息系统中传输超文本(HTML 文件、图片文件、查询结果等)。它是因特网上应用最为广泛的一种网络传输协议,所有的WWW文件都必须遵守这个标准。
HTTP是一个基于TCP/IP通信协议来传递数据,它指定了客户端可能发送给服务器什么样的消息以及得到什么样的响应。HTTP协议通常运行在TCP之上,通过使用网页浏览器、网络爬虫或者其他工具,客户端发起一个HTTP请求到服务器上指定的端口(默认端口为80),这个客户端被称为用户代理程序。HTTP假定其下层协议提供可靠的传输。具体详解可见:深入理解HTTP协议 - 知乎 (zhihu.com)
HTTP状态码的含义
详见:HTTP 响应状态码 - HTTP | MDN (mozilla.org)
HTTP与Web服务器
当在浏览器输入地址后,浏览器会先请求DNS服务器,获得请求站点的IP地址(根据URL地址"www.baidu.com" 获取其对用的IP地址,如101.201.120.85)然后发送一个http请求给拥有该IP的主机,接着就会接受到服务器返回的HTTP响应,浏览器经过渲染后,以一种较好的效果呈现给用户。
Web服务器的工作原理可以简单地归纳为以下几个步骤:
- 连接过程:Web服务器和其浏览器之间建立连接。(客户端通过TCP/IP协议(传输协议,网际协议))协议建立到服务器的TCP连接
- 请求过程:客户端向服务器发送HTTP协议请求包,请求服务器里的资源文档。
- 应答过程:运用HTTP协议把在请求过程中所提出来的请求传输到Web的服务器,进而实施任务处理,然后运用HTTP协议把任务处理的结果传输到Web的浏览器,同时在Web的浏览器上面展示所请求之界面。
- 关闭连接:当上一个过程应答过程完成以后,Web服务器和其浏览器之间断开连接。
urllib模块
现阶段我们学习的是关于urllib模块下的多个功能的子模块的功能具体分布如下:
urllib.request
:用于实现基本http请求的模块
- read():读取服务器相应的内容(字节流)
- urlopen():向网站发送一个请求并获取响应,不支持请求重构头User-Agent
- getcode():读取http的响应码
- Request():支持请求重构头
python
import urllib.request
url='https://www.baidu.com/'
headers={
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36 Edg/121.0.0.0'
}
response=urllib.request.urlopen(url)
print(response.code) # 输出200
res=response.read().decode('utf-8') # read()读取文件流 decode() 对读取到的文件进行解码以字节形式返回
print(res) # 输出的是没有添加请求头的内容
response=request.Request(url=url,headers=headers)
res=request.urlopen(response)
result=res.read().decode('utf-8')
print(result) # 输出的是带有请求头的响应内容
urllib.error异常处理模块,如果在发送网络请求时出现了错误,可以捕获的有效处理。
代码如下:
python
# 处理URLError异常
import urllib.request
import urllib.error
try:
# 向一个不存在的网址发起请求
response=urllib.request.urlopen('https://site2.rjkflm.com:666/123index.html')
except urllib.error.URLError as error:
print(error.reason) # 输出[Errno 11001] getaddrinfo failed
# 使用HTTPError类捕获异常
try:
response=urllib.request.urlopen('https://www.baidus.com/')
print(response.status)
except urllib.error.HTTPError as error:
print('状态码为:',error.code)
print('异常信息为:',error.reason)
print('请求头信息为:\n',error.headers)
# 双重异常捕获
import urllib.request
import urllib.error
try:
response=urllib.request.urlopen('https://www.baidu0.com/')
print(response.code)
except urllib.error.HTTPError as error:
print('状态码为:',error.code)
print('HTTPError异常信息为:',error.reason)
except urllib.error.URLError as error:
print('URLError异常信息为:',error.reason)
注意:
URLError和HTTPError都是urllib.error模块中定义的异常,用于处理在发送HTTP请求时可能发生的错误。它们之间的主要区别在于它们的触发条件不同。
URLError异常通常在以下情况下触发:
- 当无法连接到服务器时,例如服务器不可用或网络连接中断。
- 当请求的URL不存在或无法解析时。
- 当发生其他网络相关的问题时。
而HTTPError异常通常在以下情况下触发:
- 当服务器返回一个HTTP错误状态码时,例如404(页面未找到)或500(服务器内部错误)。
- 当HTTP请求失败,例如由于无效的请求方法或无效的请求头。
简单来说,URLError异常通常表示网络相关的问题,而HTTPError异常则表示与HTTP请求的具体内容或服务器响应的状态码相关的问题。
请注意,当发生URLError异常时,可能也会伴随HTTPError异常,因为在某些情况下,无法连接到服务器或服务器不可用也可能导致HTTP请求失败。在这种情况下,Python会先捕获URLError异常,然后再捕获HTTPError异常。因此,在编写处理异常的代码时,建议首先捕获更具体的异常(如HTTPError),然后再捕获更一般的异常(如URLError)。
urllib.parse和urllib.robotparse
urllib.parse用于解析URL的模块
这里我们讲两个知识点:代码如下
python
# 第一种 parse模块的quote()方法 对汉字进行编码
word = input('请输入要搜索的关键字:')
word=parse.quote(word)
url = 'http://www.baidu.com/s?wd={}'.format(word)
print(url)
# 第二种 parse模块的urlencode()方法 对字典进行编码
data = input('请输入要搜索的关键字:')
url=url+parse.urlencode({'wd': data})
print(url)
# 解码
print(urllib.parse.unquote('%E6%B1%9F%E8%A5%BF'))
urllib.robotparser:用于解析robots.txt文件,判断网站是否可以爬取信息。
robots.txt
(统一小写)是一种存放于网站根目录下的robots协议,通常用于告诉搜索引擎对网站的抓取规则。这个协议由一系列指令构成,这些指令指定了不同爬虫(user-agent)对网站资源的访问权限。 以下这段代码是我用AI生成的,这个方法我们只需要只知道就行,不用深究。
python
import urllib.robotparser
# 创建一个RobotFileParser对象
robot = urllib.robotparser.RobotFileParser()
# 指定robots.txt文件的URL
robot.set_url("http://www.baidu.com/robots.txt")
# 获取并解析robots.txt文件
robot.read()
# 打印解析结果
print("User-agent:", robot.can_fetch("*", "/")) # 输出: User-agent: True
print("User-agent:", robot.can_fetch("Googlebot", "/")) # 输出: User-agent: False
requests模块的基础了解
基本的请求方式GET和POST请求:
GET请求:
python
# GET请求 不需要带参请求
# 伪装浏览器
headers = {
"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36 Edg/119.0.0.0",
}
# 请求网址
url = 'https://www.baidu.com/s?wd=%E7%BC%96%E7%A8%8B'
# 获取响应
response = requests.get(url,headers=headers)
# 输出响应内容
print(response.text)
需要带参请求,一般用在用户登录时发送的请求
python
# post请求
url='https://fanyi.baidu.com/v2transapi'
headers = {
"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36 Edg/119.0.0.0",
'Cookie':
'REALTIME_TRANS_SWITCH=1; FANYI_WORD_SWITCH=1; HISTORY_SWITCH=1; SOUND_SPD_SWITCH=1; SOUND_PREFER_SWITCH=1; PSTM=1689838281; BAIDUID=1841F1CAA2C25272B9FC5F3628FDF5E0:FG=1; H_WISE_SIDS=213345_214802_110085_244712_236312_265881_267074_268593_269235_269904_271172_234295_234207_263618_260335_273146_273244_273385_272264_274423_275098_275001_275713_276196_275171_276448_276517_276733_253022_270102_277354_251972_274784_277643_277633_277785_275733_276665_275209_277997_259642_278056_278166_277322_278390_275167_278282_278578_278576_274576_278512_274779_278529_278791_278388_256739_278920_279021_279039_277522_278237_276573_279367_279385_246986_274948_276269_279435_276694_279613_279605_279620_277542_279678_279714_279740_279877_279307_279913_279695_279009_279711_279703_279974_279998_279673_278249_280208_277699_280161_280225_280447_280103_280484_270366_278414_276929_275855_280614_279201_256223_280635_280559_280767_280809_279845; H_WISE_SIDS_BFESS=213345_214802_110085_244712_236312_265881_267074_268593_269235_269904_271172_234295_234207_263618_260335_273146_273244_273385_272264_274423_275098_275001_275713_276196_275171_276448_276517_276733_253022_270102_277354_251972_274784_277643_277633_277785_275733_276665_275209_277997_259642_278056_278166_277322_278390_275167_278282_278578_278576_274576_278512_274779_278529_278791_278388_256739_278920_279021_279039_277522_278237_276573_279367_279385_246986_274948_276269_279435_276694_279613_279605_279620_277542_279678_279714_279740_279877_279307_279913_279695_279009_279711_279703_279974_279998_279673_278249_280208_277699_280161_280225_280447_280103_280484_270366_278414_276929_275855_280614_279201_256223_280635_280559_280767_280809_279845; BIDUPSID=2057491A131139656EB3A17792893F93; BDUSS=RObnBSZU5Semc3S0VtS0ZEbnUtaVhpQkh0dVN2U21NTFpFSnBBcjhSbG5HS1ZsSVFBQUFBJCQAAAAAAQAAAAEAAABHOJpEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGeLfWVni31laU; BDUSS_BFESS=RObnBSZU5Semc3S0VtS0ZEbnUtaVhpQkh0dVN2U21NTFpFSnBBcjhSbG5HS1ZsSVFBQUFBJCQAAAAAAQAAAAEAAABHOJpEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGeLfWVni31laU; H_PS_PSSID=39997_39919; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; newlogin=1; BDSFRCVID=zDDOJexroG3b-M5qGDJyM3N-b2KK0gOTDYrEOwXPsp3LGJLVYflvEG0Pt_NFmZK-oxmHogKKQgOTHRDF_2uxOjjg8UtVJeC6EG0Ptf8g0M5; H_BDCLCKID_SF=tRk8oK-atDvDqTrP-trf5DCShUFsBlOlB2Q-XPoO3KODKqCGKfJUBnLIDPIL5jjiWbRM2Mbgy4op8P3y0bb2DUA1y4vpX45QbeTxoUJ2XhrPDfcoqtnWhfkebPRiQ4b9QgbNKpQ7tt5W8ncFbT7l5hKpbt-q0x-jLTnhVn0MBCK0hD0wDT8hD6PVKgTa54cbb4o2WbCQH4bd8pcN2b5oQTtVqtFtbxbRX5ruohuEKDovOIJTXpOUWJDkXpJvQnJjt2JxaqRCyRQSfl5jDh3MBUCzhJ6ie4ROamby0hvcLR3cShn-QMjrDRLbXU6BK5vPbNcZ0l8K3l02V-bIe-t2XjQhDHt8J50ttJ3aQ5rtKRTffjrnhPF3MxFFXP6-hnjy3b7aslCa-l3U_UcEDUIV-6DUyN3MWh3Ry6r42-39LPO2hpRjyxv4WtKj54oxJpOJX2olWxccHR7WDqnvbURv0t-g3-7N0U5dtjTO2bc_5KnlfMQ_bf--QfbQ0hOhqP-jBRIEoC0XtK-hhCvPKITD-tFO5eT22-ustH6W2hcHMPoosIOPqfFhKf-vBnruJMCLKJriaKJjBMbUotoHXnJi0btQDPvxBf7pyCcQLq5TtUJM_prDhq6vqt4bht7yKMniLCv9-pn43pQrh459XP68bTkA5bjZKxtq3mkjbPbDfn028DKuDjtBDT30DGRabK6aKC5bL6rJabC3JlbeXU6q2bDeQNbaexut-mvRatTzthuVHCooyT3JXp0vWq54WbbvLT7johRTWqR4oJQ15xonDh83BPTl2lTiHCOOWlnO5hvvVJ3O3M7CQMKmDloOW-TB5bbPLUQF5l8-sq0x0bOte-bQXH_E5bj2qRIt_IL-3j; BDRCVFR[feWj1Vr5u3D]=I67x6TjHwwYf0; delPer=0; PSINO=3; BAIDUID_BFESS=1841F1CAA2C25272B9FC5F3628FDF5E0:FG=1; BDSFRCVID_BFESS=zDDOJexroG3b-M5qGDJyM3N-b2KK0gOTDYrEOwXPsp3LGJLVYflvEG0Pt_NFmZK-oxmHogKKQgOTHRDF_2uxOjjg8UtVJeC6EG0Ptf8g0M5; H_BDCLCKID_SF_BFESS=tRk8oK-atDvDqTrP-trf5DCShUFsBlOlB2Q-XPoO3KODKqCGKfJUBnLIDPIL5jjiWbRM2Mbgy4op8P3y0bb2DUA1y4vpX45QbeTxoUJ2XhrPDfcoqtnWhfkebPRiQ4b9QgbNKpQ7tt5W8ncFbT7l5hKpbt-q0x-jLTnhVn0MBCK0hD0wDT8hD6PVKgTa54cbb4o2WbCQH4bd8pcN2b5oQTtVqtFtbxbRX5ruohuEKDovOIJTXpOUWJDkXpJvQnJjt2JxaqRCyRQSfl5jDh3MBUCzhJ6ie4ROamby0hvcLR3cShn-QMjrDRLbXU6BK5vPbNcZ0l8K3l02V-bIe-t2XjQhDHt8J50ttJ3aQ5rtKRTffjrnhPF3MxFFXP6-hnjy3b7aslCa-l3U_UcEDUIV-6DUyN3MWh3Ry6r42-39LPO2hpRjyxv4WtKj54oxJpOJX2olWxccHR7WDqnvbURv0t-g3-7N0U5dtjTO2bc_5KnlfMQ_bf--QfbQ0hOhqP-jBRIEoC0XtK-hhCvPKITD-tFO5eT22-ustH6W2hcHMPoosIOPqfFhKf-vBnruJMCLKJriaKJjBMbUotoHXnJi0btQDPvxBf7pyCcQLq5TtUJM_prDhq6vqt4bht7yKMniLCv9-pn43pQrh459XP68bTkA5bjZKxtq3mkjbPbDfn028DKuDjtBDT30DGRabK6aKC5bL6rJabC3JlbeXU6q2bDeQNbaexut-mvRatTzthuVHCooyT3JXp0vWq54WbbvLT7johRTWqR4oJQ15xonDh83BPTl2lTiHCOOWlnO5hvvVJ3O3M7CQMKmDloOW-TB5bbPLUQF5l8-sq0x0bOte-bQXH_E5bj2qRIt_IL-3j; BA_HECTOR=ag218l0l25200g0505ahak8kp2bvdu1iqq41c1s; ZFY=JynYgZHBFPBy0epq6jVJYVJhDoUELNVCKP824f6uKyI:C; Hm_lvt_64ecd82404c51e03dc91cb9e8c025574=1705739978,1705840692; Hm_lpvt_64ecd82404c51e03dc91cb9e8c025574=1705840880; ab_sr=1.0.1_NTc5YmQwODU0NGVmODU3ZDY4OThlYWQwM2VlYTkxMDllYzIzMzBlN2M1ODM0YzkwN2U3ZDU3ZTU1MjY3OWM2YTExNmM2MWExNGExMzFjMjc2MWU0NzgxODJkMTc0YzYwN2QxNDkxM2ZiY2U2OTdmZGVlNzI1ZTRlNTEwZGRkZTFhMTQxYWEyM2Y1NWE1NThkNTE3ODdiNWEwMWU3MjlmNzg2MWY3ZDFiYzg5YzhiZmIwZjVmMmZlYjUyOWMzNWYx'
} # cookie 保存用户的登录信息
# data 请求数据,参数,表单的数据格式
data={
"from": "zh",
"to": "en",
"query": "猫",
"transtype": "realtime",
"simple_means_flag": "3",
"sign": "31275.301338",
"token": "e61fee9fcdfec06209ba1a5e2766806a",
"domain": "common",
"ts": "1705840893105"
}
response=requests.post(url=url,data=data,headers=headers)
print(response.status_code)
Requests响应内容
r.encoding
-------获取当前的编码
r.cookies
-------- 返回cookie
r.headers
-------- 以字典对象存储服务器响应头,但是这个字典比较特殊,字典键不区分大小写,若键不存在则返回None
r.status_code
---------- 响应状态码
r.text
------ 以获取到的编码解析响应内容。
r.json()
--------- Requests中内置的JSON解码器,以json形式返回,前提返回的内容确保是json格式的,不然解析出错会抛异常
r.content
-------- 以字节形式(二进制)解析响应内容