html
在学习爬虫前,我们需要对html中的标签有一个简单的了解
< table >:表格
< tr > :表格中的行
< td >:表格中的列
< ul > < li >无序列表 爬虫的使用场景非常之多–>
< ol >< li >有序列表
示例如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!-- table 表格
tr 行
td 列
-->
<table width="200px" height="200px" border="1px">
<tr>
<td>
姓名
</td>
<td>
年龄
</td>
<td>
性别
</td>
</tr>
<tr>
<td>
张三
</td>
<td>
18
</td>
<td>
男
</td>
</tr>
</table>
<!-- ul li 无序列表 爬虫的使用场景非常之多-->
<ul>
<li>铁锅炖大鹅</li>
<li>小鸡炖蘑菇</li>
<li>锅包肉</li>
</ul>
<!-- ol li-->
<ol>
<li>穿上衣服</li>
<li>下床</li>
<li>洗漱</li>
</ol>
<a href="http://www.baidu.com/">百度</a>
</body>
</html>
效果图如下
urllib库使用
urllib库是python本身自带的库函数
# 使用urllib来获取百度首页的源码
import urllib.request
# 定义一个Url 就是你要访问的地址
url='http://www.baidu.com'
#模拟浏览器向服务器发送请求 response响应
response=urllib.request.urlopen(url)
#获取页面的源码 使用content保存
content=response.read()
#打印数据
print(content)
read方法 返回的是字节形式的二进制数据
我们要将二进制的数据转换为字符串
解码
decode('编码的格式')
示例如下
# 使用urllib来获取百度首页的源码
import urllib.request
# 定义一个Url 就是你要访问的地址
url='http://www.baidu.com'
#模拟浏览器向服务器发送请求 response响应
response=urllib.request.urlopen(url)
#获取页面的源码 使用content保存
content=response.read().decode('utf-8')
#打印数据
print(content)
urllib的基本使用
服务器返回的类型
import urllib.request
url='http://www.baidu.com'
#模拟浏览器向服务器发送请求 response响应
respose=urllib.request.urlopen(url)
#类型
print(type(respose))
输出结果为
<class 'http.client.HTTPResponse'>
由此可知response的数据类型是HttpResponse
read
read() 字节形式读取二进制
扩展:rede(n)返回前n个字节
import urllib.request
url='http://www.baidu.com'
#模拟浏览器向服务器发送请求 response响应
respose=urllib.request.urlopen(url)
#按照一个字节一个字节的去读
content=respose.read()
print(content)
reline
readline() 读取一行
import urllib.request
url='http://www.baidu.com'
#模拟浏览器向服务器发送请求 response响应
respose=urllib.request.urlopen(url)
content=respose.readline()
print(content)
relines
readlines() 一行一行读取 直至结束
import urllib.request
url='http://www.baidu.com'
#模拟浏览器向服务器发送请求 response响应
respose=urllib.request.urlopen(url)
content=respose.readlines()
print(content)
getcode
getcode() 获取状态码
当输出是200时表示没有问题
import urllib.request
url='http://www.baidu.com'
#模拟浏览器向服务器发送请求 response响应
response=urllib.request.urlopen(url)
print(response.getcode())
geturl
geturl() 获取url
import urllib.request
url='http://www.baidu.com'
#模拟浏览器向服务器发送请求 response响应
response=urllib.request.urlopen(url)
print(response.geturl())
getheaders
getheaders() 获取一些状态信息
import urllib.request
url='http://www.baidu.com'
#模拟浏览器向服务器发送请求 response响应
response=urllib.request.urlopen(url)
print(response.getheaders())
urllib-下载
下载我们需要使用
urllib.request.urlretrieve()
网页
import urllib.request
#下载网页
url_page='http://www.baidu.com'
#参数1 url表示下载的地址 参数2 filename表示文件的名字
urllib.request.urlretrieve(url=url_page,filename='baidu.html')
图片
我们在网上找到想要下载的图片
复制图片链接后
使用urllib.request.urlretrieve()
import urllib.request
#参数1 url表示下载的地址 参数2 filename表示文件的名字
#下载图片
url_image='https://tse1-mm.cn.bing.net/th/id/OIP-C.nrP2Hi-wqMS2Xq4h3JvxAQHaNK?w=115&h=180&c=7&r=0&o=5&dpr=1.3&pid=1.7'
urllib.request.urlretrieve(url=url_image,filename='huoyin.jpg')#注意需要有后缀
视频
我们随意找到一个视频
找到视频之后我们需要暂停视频,
鼠标右键,点击检查
在检查页面找到这个图标
之后点击页面中的该视频
如图,我们已经定好了位置,视频中的src即为视频的地址
#下载视频
url_video='https://vdept3.bdstatic.com/mda-qdv3k5dkmivi7zr3/sc/cae_h264/1714876360957548870/mda-qdv3k5dkmivi7zr3.mp4?v_from_s=hkapp-haokan-hna&auth_key=1715453205-0-0-9205b31f8ea8e2324cad3c43f607c005&bcevod_channel=searchbox_feed&cr=2&cd=0&pd=1&pt=3&logid=2805875064&vid=9797222881313443257&klogid=2805875064&abtest='
urllib.request.urlretrieve(url=url_video,filename='shiping.mp4')
#注意后缀,同时注意pycharm中是没有视频播放器的,我们需要找到该文件的文件路径,去播放他
urllib-请求对象的定制
import urllib.request
url='https://www.baidu.com'
#url的组成
#https://www.baidu.com/s?wd=周杰伦
# 协议 主机 端口号 路径 参数 锚点
# http/https www.baidu.com 80/443 s wd=周杰伦 #
# http 80
# https 443
# mysql 3306
# oracle 1521
# redis 6379
# mongodb 27017
#https比http更加安全 https中加了一个叫ssl的东西
response=urllib.request.urlopen(url)
#获取网页源码
content=response.read().decode('utf-8')
print(content)
当我们使用https获取网页源码时,我们会发现我们获取的网页源码极少,原因是我们遭到了第一个反爬UA
UA介绍:User Agent中文名为用户代理,简称 UA,它是一个特殊字符串头,使得服务器能够识别客户使用的操作系统
及版本、CPU 类型、浏览器及版本。浏览器内核、浏览器渲染引擎、浏览器语言、浏览器插件等
语法:request = urllib.request.Request()
UA获取
-
可以百度UA大全,获取各个浏览器的UA
-
我们可以在浏览器页面右键找到检查
在检查页面找到network
刷新一下页面
找到我们接口/域名
我们点击我们接口/域名
然后点击headers划到headers页面的最下面
找到
User-Agent
里面可以看到我们的操作系统等各种信息
我们将其复制下来我们使用请求对象的定制对其进行伪装,让我们在爬虫时使浏览器能够辨识到操作系统等各个参数
import urllib.request
url='https://www.baidu.com'
#使用字典保存我们获取的ua数据
headers={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36'}
#因为urlopen方法中不能存储字典 所以headers不能传递进去
# 这时候我们就使用到了请求对象的定制,将其变成一个整体
# 注意 因为参数顺序问题 不能直接写url和headers 因为这两个参数中间还有data参数
# 所以我们使用的是关键字传参
request=urllib.request.Request(url=url,headers=headers)
response=urllib.request.urlopen(request)
#获取网页源码
content=response.read().decode('utf-8')
print(content)
编解码
如图我们收索一个歌星
我们将链接中歌星名字后面的地址删除掉后将链接复制到pycharm上
我们会发现在pycharm上变成了下面的形式
https://www.baidu.com/s?ie=utf-8&f=3&rsv_bp=1&rsv_idx=1&tn=baidu&wd=%E5%91%A8%E6%9D%B0%E4%BC%A6
将歌星的名字变成了其他的东西
其实他是将其变成了Unicode编码
==编码集的演变‐‐‐
由于计算机是美国人发明的,因此,最早只有127个字符被编码到计算机里,也就是大小写英文字母、数字和一些符号,
这个编码表被称为ASCII编码,比如大写字母A的编码是65,小写字母z的编码是122。
但是要处理中文显然一个字节是不够的,至少需要两个字节,而且还不能和ASCII编码冲突,
所以,中国制定了GB2312编码,用来把中文编进去。
你可以想得到的是,全世界有上百种语言,日本把日文编到Shift_JIS里,韩国把韩文编到Euc‐kr里,
各国有各国的标准,就会不可避免地出现冲突,结果就是,在多语言混合的文本中,显示出来会有乱码。
因此,Unicode应运而生。Unicode把所有语言都统一到一套编码里,这样就不会再有乱码问题了。
Unicode标准也在不断发展,但最常用的是用两个字节表示一个字符(如果要用到非常偏僻的字符,就需要4个字节)。
现代操作系统和大多数编程语言都直接支持Unicode。
1.get请求方式:urllib.parse.quote()
#需求 获取https://www.baidu.com/s?ie=utf-8&f=3&rsv_bp=1&rsv_idx=1&tn=baidu&wd=周杰伦的网页源码
import urllib.request
url='https://www.baidu.com/s?ie=utf-8&f=3&rsv_bp=1&rsv_idx=1&tn=baidu&wd=周杰伦'
#请求对象的定制是为了解决反爬的第一种手段
headers={
'User-Agent':
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36'
}#找到页面的ua
#请求对象的定制
request=urllib.request.Request(url=url,headers=headers)#关键字传参
#模拟浏览器向服务器发送请求
response=urllib.request.urlopen(request)
#获取响应的内容
content=response.read().decode('utf-8')
#打印数据
print(content)
我们运行上面的代码会发现报错了,原因是url链接后面的wd后面不能是汉字,需要变为Unicode编码
我们将汉字变为我们的Unicode编码需要使用到get的请求方法
get请求方式:urllib.parse.quote()
我们需要导入import urllib.parse
#需求 获取https://www.baidu.com/s?ie=utf-8&f=3&rsv_bp=1&rsv_idx=1&tn=baidu&wd=周杰伦的网页源码
import urllib.request
import urllib.parse
url='https://www.baidu.com/s?ie=utf-8&f=3&rsv_bp=1&rsv_idx=1&tn=baidu&wd='
#请求对象的定制是为了解决反爬的第一种手段
headers={
'User-Agent':
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36'
}#找到页面的ua
#将周杰伦三个字变成Unicode编码格式
#我们需要依赖于urllib.parse
name=urllib.parse.quote('周杰伦')
url=url+name
#请求对象的定制
request=urllib.request.Request(url=url,headers=headers)#关键字传参
#模拟浏览器向服务器发送请求
response=urllib.request.urlopen(request)
#获取响应的内容
content=response.read().decode('utf-8')
#打印数据
print(content)
2.get请求方式:urllib.parse.urlencode()
当链接中有多个中文参数时,使用quote可能会有些麻烦,这时候我们就可以使用urlencode方式
#urlencode应用场景:当链接中有多个中文参数时
#需求:将下面的汉字转换成unicode编码
#https://www.baidu.com/s?ie=utf-8&f=3&rsv_bp=1&rsv_idx=1&tn=baidu&wd=周杰伦&sex=男
import urllib.parse
data={
'wd':'周杰伦',
'sex':'男'
}
# 在转换为unicode中
# :对应=
# ,对应&
a=urllib.parse.urlencode(data)
print(a)
#需求: 获取https://www.baidu.com/s?ie=utf-8&f=3&rsv_bp=1&rsv_idx=1&tn=baidu&wd=%E5%91%A8%E6%9D%B0%E4%BC%A6&sex=%E7%94%B7的网页源码
import urllib.request
import urllib.parse
base_url='https://www.baidu.com/s?ie=utf-8&f=3&rsv_bp=1&rsv_idx=1&tn=baidu'
data={
'wd':'周杰伦',
'sex':'男'
}
new_data=urllib.parse.urlencode(data)
#请求资源路径
url=base_url+new_data
headers={
'User-Agent':
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36'
}#找到页面的ua
#请求对象的定制
request=urllib.request.Request(url=url,headers=headers)
#模拟浏览器向服务器发送请求
response=urllib.request.urlopen(request)
#获取网页源码的数据
content=response.read().decode('utf-8')
print(content)
3.post请求百度翻译
但我们打开百度翻译,右键检查,network,在翻译页面输入spider,我们会发现每输入一个字母network页面都会变化,我们会发现左侧有很多sug,我们依次点击每个sug和payload,我们会发现其逐渐组成了一个spider单词。
我们点击preview可以发现里面是spider的翻译
所以我们在爬虫中的难点就是哪个数据才是我想要的数据
我们可以使用post找到我们想要的数据
我们以百度翻译为例,找到我们输入的单词
我们在headers中找到Request URL,复制该地址
# post请求方式的参数 必须编码 data = urllib.parse.urlencode(data)
# 编码之后 必须调用encode方法 data = urllib.parse.urlencode(data).encode('utf-8')
# 参数是放在请求对象定制的方法中 request = urllib.request.Request(url=url,data=data,headers=headers)
# _*_ coding : utf-8 _*_
# @Time : 2024/5/12 下午8:54
# @Author : xtone
# @File : 059_尚硅谷_爬虫_urllib_post请求百度翻译
# @Project : pythonProject
import urllib.request
import urllib.parse
url='https://fanyi.baidu.com/sug'
headers={
'User-Agent':
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36'
}#找到页面的ua
#使用列表存储我们需要查找的单词
data={
'kw':'spider'
}
# Request参数中的data数据为字节类型,所以我们需要对data数据encode
# post请求的参数必须进行编码 encode()编码并指定编码的类型 decode()解码
data=urllib.parse.urlencode(data).encode('utf-8')
#post请求的参数 是不会拼接在url后面的 而是需要放在请求对象定制的参数中
#post请求的参数必须编码
request=urllib.request.Request(url=url,data=data,headers=headers)
#模拟浏览器向服务器发送请求
response=urllib.request.urlopen(request)
#获取响应的数据
content=response.read().decode('utf-8')
print(content)
print(type(content))#数据类型是str
输出结果为
我们可以发现数据类型是字符串类型
此时我们需要让字符串–>json对象
# _*_ coding : utf-8 _*_
# @Time : 2024/5/12 下午8:54
# @Author : xtone
# @File : 059_尚硅谷_爬虫_urllib_post请求百度翻译
# @Project : pythonProject
import urllib.request
import urllib.parse
url='https://fanyi.baidu.com/sug'
headers={
'User-Agent':
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36'
}#找到页面的ua
#使用列表存储我们需要查找的单词
data={
'kw':'spider'
}
# Request参数中的data数据为字节类型,所以我们需要对data数据encode
# post请求的参数必须进行编码 encode()编码并指定编码的类型 decode()解码
data=urllib.parse.urlencode(data).encode('utf-8')
#post请求的参数 是不会拼接在url后面的 而是需要放在请求对象定制的参数中
#post请求的参数必须编码
request=urllib.request.Request(url=url,data=data,headers=headers)
#模拟浏览器向服务器发送请求
response=urllib.request.urlopen(request)
#获取响应的数据
content=response.read().decode('utf-8')
#
# print(content)
# print(type(content))#数据类型是str
import json
obj=json.loads(content)
print(obj)
经过转换后,我们可以发现打印出了我们想要的preview了
4.post请求百度翻译之详细翻译
本小节内容出现错误,因为百度翻译的反爬手段升级了
我们打开百度翻译,我们来翻译love这个单词,跟上次一样我们右键检查,我们找到sug
我们关注sug的payload
我们点到translate找到详细翻译,我们查看详细翻译的payload我们发现比sug上多了很多数据
其实百度翻译中还有一个反爬手段,我们找到他的接口,我们将其复制过来
我们将其中的参数复制到pycharm中
# _*_ coding : utf-8 _*_
# @Time : 2024/5/13 下午6:07
# @Author : xtone
# @File : 060_尚硅谷_爬虫_urllib_post请求百度翻译之详细翻译
# @Project : pythonProject
import urllib.request
import urllib.parse
#将接口复制过来
url='https://fanyi.baidu.com/ait/text/translate'
headers={
'User-Agent':
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36'
}#找到页面的ua
#payload中的参数,使用正则替换
data={"query":"love",
"from":"en","to":"zh",
"reference":"",
"corpusIds":[],
"qcSettings":["1","2","3","4","5","6","7","8","9","10","11"],
"needPhonetic":"true","domain":"common","milliTimestamp":"1715595474705"
}
#post请求的参数 必须进行编码 并且要调用encode方法
data=urllib.parse.urlencode(data).encode('utf-8')
#请求对象的定制
request=urllib.request.Request(url=url,data=data,headers=headers)
#模拟浏览器向服务器发送请求
response=urllib.request.urlopen(request)
#获取响应的数据
content=response.read().decode('utf-8')
print(content)
我们发现上面代码只得到了部分的数据
我们试试使用json转换成为json对象
#使用json转换
import json
obj=json.loads(content)
print(obj)
发现出现了未知错误,其实是在headers我们需要给到cookie
import urllib.request
import urllib.parse
url = 'https://fanyi.baidu.com/v2transapi?from=en&to=zh'
headers = {
# 'Accept': '*/*',
# 'Accept-Encoding': 'gzip, deflate, br',
# 'Accept-Language': 'zh-CN,zh;q=0.9',
# 'Connection': 'keep-alive',
# 'Content-Length': '135',
# 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
'Cookie': 'BIDUPSID=DAA8F9F0BD801A2929D96D69CF7EBF50; PSTM=1597202227; BAIDUID=DAA8F9F0BD801A29B2813502000BF8E9:SL=0:NR=10:FG=1; __yjs_duid=1_c19765bd685fa6fa12c2853fc392f8db1618999058029; REALTIME_TRANS_SWITCH=1; FANYI_WORD_SWITCH=1; HISTORY_SWITCH=1; SOUND_SPD_SWITCH=1; SOUND_PREFER_SWITCH=1; BDUSS=R2bEZvTjFCNHQxdUV-cTZ-MzZrSGxhbUYwSkRkUWk2SkxxS3E2M2lqaFRLUlJoRVFBQUFBJCQAAAAAAAAAAAEAAAA3e~BTveK-9sHLZGF5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFOc7GBTnOxgaW; BDUSS_BFESS=R2bEZvTjFCNHQxdUV-cTZ-MzZrSGxhbUYwSkRkUWk2SkxxS3E2M2lqaFRLUlJoRVFBQUFBJCQAAAAAAAAAAAEAAAA3e~BTveK-9sHLZGF5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFOc7GBTnOxgaW; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; BAIDUID_BFESS=DAA8F9F0BD801A29B2813502000BF8E9:SL=0:NR=10:FG=1; BDRCVFR[feWj1Vr5u3D]=I67x6TjHwwYf0; PSINO=2; H_PS_PSSID=34435_31660_34405_34004_34073_34092_26350_34426_34323_22158_34390; delPer=1; BA_HECTOR=8185a12020018421b61gi6ka20q; BCLID=10943521300863382545; BDSFRCVID=boDOJexroG0YyvRHKn7hh7zlD_weG7bTDYLEOwXPsp3LGJLVJeC6EG0Pts1-dEu-EHtdogKK0mOTHv8F_2uxOjjg8UtVJeC6EG0Ptf8g0M5; H_BDCLCKID_SF=tR3aQ5rtKRTffjrnhPF3-44vXP6-hnjy3bRkX4Q4Wpv_Mnndjn6SQh4Wbttf5q3RymJ42-39LPO2hpRjyxv4y4Ldj4oxJpOJ-bCL0p5aHl51fbbvbURvD-ug3-7qqU5dtjTO2bc_5KnlfMQ_bf--QfbQ0hOhqP-jBRIE3-oJqC8hMIt43f; BCLID_BFESS=10943521300863382545; BDSFRCVID_BFESS=boDOJexroG0YyvRHKn7hh7zlD_weG7bTDYLEOwXPsp3LGJLVJeC6EG0Pts1-dEu-EHtdogKK0mOTHv8F_2uxOjjg8UtVJeC6EG0Ptf8g0M5; H_BDCLCKID_SF_BFESS=tR3aQ5rtKRTffjrnhPF3-44vXP6-hnjy3bRkX4Q4Wpv_Mnndjn6SQh4Wbttf5q3RymJ42-39LPO2hpRjyxv4y4Ldj4oxJpOJ-bCL0p5aHl51fbbvbURvD-ug3-7qqU5dtjTO2bc_5KnlfMQ_bf--QfbQ0hOhqP-jBRIE3-oJqC8hMIt43f; Hm_lvt_64ecd82404c51e03dc91cb9e8c025574=1629701482,1629702031,1629702343,1629704515; Hm_lpvt_64ecd82404c51e03dc91cb9e8c025574=1629704515; __yjs_st=2_MDBkZDdkNzg4YzYyZGU2NTM5NzBjZmQ0OTZiMWRmZGUxM2QwYzkwZTc2NTZmMmIxNDJkYzk4NzU1ZDUzN2U3Yjc4ZTJmYjE1YTUzMTljYWFkMWUwYmVmZGEzNmZjN2FlY2M3NDAzOThhZTY5NzI0MjVkMmQ0NWU3MWE1YTJmNGE5NDBhYjVlOWY3MTFiMWNjYTVhYWI0YThlMDVjODBkNWU2NjMwMzY2MjFhZDNkMzVhNGMzMGZkMWY2NjU5YzkxMDk3NTEzODJiZWUyMjEyYTk5YzY4ODUyYzNjZTJjMGM5MzhhMWE5YjU3NTM3NWZiOWQxNmU3MDVkODExYzFjN183XzliY2RhYjgz; ab_sr=1.0.1_ZTc2ZDFkMTU5ZTM0ZTM4MWVlNDU2MGEzYTM4MzZiY2I2MDIxNzY1Nzc1OWZjZGNiZWRhYjU5ZjYwZmNjMTE2ZjIzNmQxMTdiMzIzYTgzZjVjMTY0ZjM1YjMwZTdjMjhiNDRmN2QzMjMwNWRhZmUxYTJjZjZhNTViMGM2ODFlYjE5YTlmMWRjZDAwZGFmMDY4ZTFlNGJiZjU5YzE1MGIxN2FiYTU3NDgzZmI4MDdhMDM5NTQ0MjQxNDBiNzdhMDdl',
# 'Host': 'fanyi.baidu.com',
# 'Origin': 'https://fanyi.baidu.com',
# 'Referer': 'https://fanyi.baidu.com/?aldtype=16047',
# 'sec-ch-ua': '"Chromium";v="92", " Not A;Brand";v="99", "Google Chrome";v="92"',
# 'sec-ch-ua-mobile': '?0',
# 'Sec-Fetch-Dest': 'empty',
# 'Sec-Fetch-Mode': 'cors',
# 'Sec-Fetch-Site': 'same-origin',
# 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36',
# 'X-Requested-With': 'XMLHttpRequest',
}
data = {
'from': 'en',
'to': 'zh',
'query': 'love',
'transtype': 'realtime',
'simple_means_flag': '3',
'sign': '198772.518981',
'token': '5483bfa652979b41f9c90d91f3de875d',
'domain': 'common',
}
# post请求的参数 必须进行编码 并且要调用encode方法
data = urllib.parse.urlencode(data).encode('utf-8')
# 请求对象的定制
request = urllib.request.Request(url = url,data = data,headers = headers)
# 模拟浏览器向服务器发送请求
response = urllib.request.urlopen(request)
# 获取响应的数据
content = response.read().decode('utf-8')
import json
obj = json.loads(content)
print(obj)
ajax的get请求豆瓣电影的第一页
进入豆瓣电影的第一页,我们右键检查,刷新一下页面
我们寻找network的数据,找到我们想要的第一页电影的数据
我们发现数据的请求方式是使用get请求
代码如下
# get 请求
# 获取豆瓣电影的第一页的数据并且保存起来
import urllib.request
url = 'https://movie.douban.com/j/chart/top_list?type=5&interval_id=100%3A90&action=&start=0&limit=20'
headers = {
'User-Agent': ' Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36'
}
# 定制request
request = urllib.request.Request(url=url, headers=headers)
# 获取响应数据
response = urllib.request.urlopen(request)
context = response.read().decode('utf-8')
print(context)
我们还需要将数据下载到本地
完整代码如下,其中使用文件操作
使用open函数,可以打开一个已经存在的文件,或者创建一个新文件
再将content的内容写入文件中
# get请求
# 获取豆瓣电影的第一页的数据 并且保存起来
import urllib.request
url = 'https://movie.douban.com/j/chart/top_list?type=5&interval_id=100%3A90&action=&start=0&limit=20'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36'
}
# (1) 请求对象的定制
request = urllib.request.Request(url=url,headers=headers)
# (2)获取响应的数据
response = urllib.request.urlopen(request)
content = response.read().decode('utf-8')
# (3) 数据下载到本地
# open方法默认情况下使用的是gbk的编码 如果我们要想保存汉字 那么需要在open方法中指定编码格式为utf-8
# encoding = 'utf-8'
#第一种写法
# fp = open('douban.json','w',encoding='utf-8')
# fp.write(content)
#第二种写法
with open('douban1.json','w',encoding='utf-8') as fp:
fp.write(content)
ajax的get请求豆瓣电影的前十页
我们通过查看每一页的数据–>查看完该页的数据之后再清空,再查看下一页的内容,我们获取1,2,3,4页top_list的Request URL
# https://movie.douban.com/j/chart/top_list?type=5&interval_id=100%3A90&action=&
# start=0&limit=20
# https://movie.douban.com/j/chart/top_list?type=5&interval_id=100%3A90&action=&
# start=20&limit=20
# https://movie.douban.com/j/chart/top_list?type=5&interval_id=100%3A90&action=&
# start=40&limit=20
# https://movie.douban.com/j/chart/top_list?type=5&interval_id=100%3A90&action=&
# start=60&limit=20
我们发现,我们可以找到url的规律
# page(页数) 1 2 3 4
# start 0 20 40 60
# start ( 规律):(page - 1)*20
导入必要的库:
-
urllib.parse 用于构建 URL
urllib.request 用于发送 HTTP 请求和获取响应
定义三个函数: -
create_request(page):
构建每个页面的 URL,包括设置 start 和 limit 参数
设置请求头,模拟浏览器请求
get_content(request):
发送请求并获取响应内容
将响应内容解码为 UTF-8 格式
down_load(page, content):
将响应内容保存到以 douban_.json 命名的文件中 -
在主程序中:
提示用户输入起始页码和结束页码
遍历指定页码范围
对每个页码调用 create_request(), get_content(), down_load() 函数
完成对指定页码范围内的电影数据的爬取和保存
# _*_ coding : utf-8 _*_
# @Time : 2024/5/13 下午9:16
# @Author : xtone
# @File : 062_尚硅谷_爬虫_urllib_ajax请求豆瓣电影的前10页
# @Project : pythonProject
# https://movie.douban.com/j/chart/top_list?type=5&interval_id=100%3A90&action=&
# start=0&limit=20
# https://movie.douban.com/j/chart/top_list?type=5&interval_id=100%3A90&action=&
# start=20&limit=20
# https://movie.douban.com/j/chart/top_list?type=5&interval_id=100%3A90&action=&
# start=40&limit=20
# https://movie.douban.com/j/chart/top_list?type=5&interval_id=100%3A90&action=&
# start=60&limit=20
# page 1 2 3 4
# start 0 20 40 60
# start (page - 1)*20
# 下载豆瓣电影前10页的数据
# (1) 请求对象的定制
# (2) 获取响应的数据
# (3) 下载数据
import urllib.parse
import urllib.request
def create_request(page):
base_url='https://movie.douban.com/j/chart/top_list?type=5&interval_id=100%3A90&action=&'
new_page=(page-1)*20
dict={
'start':(page - 1) * 20,
'limit':20
}
body=urllib.parse.urlencode(dict)
#获取每一页的url
new_url=base_url+body
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36'
}#找到UA
#进行对象的定制
request=urllib.request.Request(url=new_url,headers=headers)
return request
def get_content(request):
#模拟浏览器向服务器发送请求
response=urllib.request.urlopen(request)
#获取响应的内容
content=response.read().decode('utf-8')
return content
def down_load(page,content):
with open('douban_' + str(page) + '.json','w',encoding='utf-8')as fp:
#如果需要和字符串进行拼接,+号的两端全都需要为字符串,所以我们对page进行强制类型转换
fp.write(content)
#程序的入口
if __name__=='__main__':
start_page=int(input('请输入起始的页码'))#输入的为字符串,我们需要进行对象的转换
end_page=int(input('请输入结束的页码'))
for page in range(start_page,end_page+1):
# 每一页都有自己的请求对象的定制
request = create_request(page)
# 获取响应的数据
content = get_content(request)
# 下载
down_load(page, content)
ajax的post请求肯德基官网
我们找到肯德基官网,我们获取北京的肯德基的前十页的餐厅
我们右键检查network可以看到其是一个post请求
其中我们标记的就是ajax的核心对象,由此我们可以知道我们需要使用ajax请求
我们分别获取每一页数据的url和每一页的payload,查找其中的共同的规律
#第一页
#https://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=cname
# cname: 北京
# pid:
# pageIndex: 1
# pageSize: 10
#第二页
#https://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=cname
# cname: 北京
# pid:
# pageIndex: 2
# pageSize: 10
#第三页
#https://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=cname
# cname: 北京
# pid:
# pageIndex: 3
# pageSize: 10
# _*_ coding : utf-8 _*_
# @Time : 2024/5/14 下午3:28
# @Author : xtone
# @File : 063_尚硅谷_爬虫_urllib_ajax请求肯德基官网
# @Project : pythonProject
#第一页
#https://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=cname
# cname: 北京
# pid:
# pageIndex: 1
# pageSize: 10
#第二页
#https://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=cname
# cname: 北京
# pid:
# pageIndex: 2
# pageSize: 10
#第三页
#https://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=cname
# cname: 北京
# pid:
# pageIndex: 3
# pageSize: 10
import urllib.request
import urllib.parse
def create_request(page):
base_url='https://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=cname'
data={
'cname': '北京',
'pid':'',
' pageIndex': page,
' pageSize': '10'
}
data=urllib.parse.urlencode(data).encode('utf-8')
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36'
}
request=urllib.request.Request(url=base_url,headers=headers,data=data)
return request
def get_content(request):
response=urllib.request.urlopen(request)
content=response.read().decode('utf-8')
return content
def down_load(page,content):
with open('kfc'+str(page)+'json','w',encoding='utf-8')as fp:
fp.write(content)
if __name__=='__main__':
start_page=int(input("请输入起始页码"))
end_page=int(input('请输入终止的页码'))
for page in range(start_page,end_page+1):
#请求对象的定制
request=create_request(page)
#获取网页源码
content=get_content(request)
#下载
down_load(page,content)
异常.URLError\HTTPError
简介:1.HTTPError类是URLError类的子类
2.导入的包urllib.error.HTTPError urllib.error.URLError
3.http错误:http错误是针对浏览器无法连接到服务器而增加出来的错误提示。引导并告诉浏览者该页是哪里出
了问题。
4.通过urllib发送请求的时候,有可能会发送失败,这个时候如果想让你的代码更加的健壮,可以通过try‐
except进行捕获异常,异常有两类,URLError\HTTPError
import urllib.request
import urllib.error
# url = 'https://blog.csdn.net/sulixu/article/details/1198189491'
url = 'http://www.doudan1111.com'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36'
}
try:
request = urllib.request.Request(url = url, headers = headers)
response = urllib.request.urlopen(request)
content = response.read().decode('utf-8')
print(content)
except urllib.error.HTTPError:#当出现HTTPError错误时提示
print('系统正在升级。。。')
except urllib.error.URLError:#当出现URLError错误时提示
print('我都说了 系统正在升级。。。')
cookie登录
当我们进入微博的个人信息页面,我们需要获取微博的个人信息页面
import urllib.request
url = 'https://weibo.cn/6451491586/info'
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36',
}
# 请求对象的定制
request = urllib.request.Request(url=url,headers=headers)
# 模拟浏览器向服务器发送请求
response = urllib.request.urlopen(request)
# 获取响应的数据
content = response.read().decode('utf-8')
# 将数据保存到本地
with open('weibo.html','w',encoding='utf-8')as fp:
fp.write(content)
我们发现代码报错了,报错原因是网页并不是utf-8
编码,我们右键查看网页源码,网页源码却显示该网页是utf-8
的编码
原因是
# 个人信息页面是utf-8 但是还报错了编码错误 因为并没有进入到个人信息页面 而是跳转到了登陆页面
# 那么登陆页面不是utf-8 所以报错
这个是页面的反爬手段之一,我们右键查看微博登入网页的源码,我们发现登入页面的编码是gb2312
编码,我们将编码和解码都改成gb2312
我们发现不报编码错误了,但当我们进入该网页时,登入页面一直在加载中。
那我们怎么绕过登入界面呢?
# 什么情况下访问不成功?
# 因为请求头的信息不够 所以访问不成功
我们将个人信息网页的请求头参数都给复制出来,我们一个一个去尝试看看哪个参数对解决反爬手段起决定性因素,我们发现起决定性因素的是参数中的cookie
cookie中携带着你的登陆信息
如果有登陆之后的cookie
那么我们就可以携带着cookie进入到任何页面
我们写入参数cookie一般结合referer
# referer 判断当前路径是不是由上一个路径进来的 一般情况下 是做图片防盗链
# 适用的场景:数据采集的时候 需要绕过登陆 然后进入到某个页面
# 个人信息页面是utf-8 但是还报错了编码错误 因为并没有进入到个人信息页面 而是跳转到了登陆页面
# 那么登陆页面不是utf-8 所以报错
# 什么情况下访问不成功?
# 因为请求头的信息不够 所以访问不成功
import urllib.request
url = 'https://weibo.cn/6451491586/info'
headers = {
# ':authority': 'weibo.cn',
# ':method': 'GET',
# ':path': '/6451491586/info',
# ':scheme': 'https',
'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
# 'accept-encoding': 'gzip, deflate, br',
'accept-language': 'zh-CN,zh;q=0.9',
'cache-control': 'max-age=0',
# cookie中携带着你的登陆信息 如果有登陆之后的cookie 那么我们就可以携带着cookie进入到任何页面
'cookie': '_T_WM=24c44910ba98d188fced94ba0da5960e; SUBP=0033WrSXqPxfM725Ws9jqgMF55529P9D9WFxxfgNNUmXi4YiaYZKr_J_5NHD95QcSh-pSh.pSKncWs4DqcjiqgSXIgvVPcpD; SUB=_2A25MKKG_DeRhGeBK7lMV-S_JwzqIHXVv0s_3rDV6PUJbktCOLXL2kW1NR6e0UHkCGcyvxTYyKB2OV9aloJJ7mUNz; SSOLoginState=1630327279',
# referer 判断当前路径是不是由上一个路径进来的 一般情况下 是做图片防盗链
'referer': 'https://weibo.cn/',
'sec-ch-ua': '"Chromium";v="92", " Not A;Brand";v="99", "Google Chrome";v="92"',
'sec-ch-ua-mobile': '?0',
'sec-fetch-dest': 'document',
'sec-fetch-mode': 'navigate',
'sec-fetch-site': 'same-origin',
'sec-fetch-user': '?1',
'upgrade-insecure-requests': '1',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36',
}
# 请求对象的定制
request = urllib.request.Request(url=url,headers=headers)
# 模拟浏览器向服务器发送请求
response = urllib.request.urlopen(request)
# 获取响应的数据
content = response.read().decode('utf-8')
# 将数据保存到本地
with open('weibo.html','w',encoding='utf-8')as fp:
fp.write(content)
Handler处理器
为什么要学习handler?
urllib.request.urlopen(url)
不能定制请求头
urllib.request.Request(url,headers,data)
可以定制请求头
Handler
定制更高级的请求头(随着业务逻辑的复杂 请求对象的定制已经满足不了我们的需求(动态cookie和代理
不能使用请求对象的定制)
# 需求 使用handler来访问百度 获取网页源码
import urllib.request
url = 'http://www.baidu.com'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36'
}
request = urllib.request.Request(url = url,headers = headers)
# handler build_opener open
# (1)获取hanlder对象
handler = urllib.request.HTTPHandler()
# (2)获取opener对象
opener = urllib.request.build_opener(handler)
# (3) 调用open方法
response = opener.open(request)
content = response.read().decode('utf-8')
print(content)
上面代码和直接使用response差不了太多
代理
1.代理的常用功能?
1.突破自身IP访问限制,访问国外站点。
2.访问一些单位或团体内部资源
扩展:某大学FTP(前提是该代理地址在该资源的允许访问范围之内),使用教育网内地址段免费代理服务
器,就可以用于对教育网开放的各类FTP下载上传,以及各类资料查询共享等服务。
3.提高访问速度
扩展:通常代理服务器都设置一个较大的硬盘缓冲区,当有外界的信息通过时,同时也将其保存到缓冲
区中,当其他用户再访问相同的信息时, 则直接由缓冲区中取出信息,传给用户,以提高访问速度。
4.隐藏真实IP
扩展:上网者也可以通过这种方法隐藏自己的IP,免受攻击。
2.代码配置代理
创建Reuqest对象
创建ProxyHandler对象
用handler对象创建opener对象
使用opener.open函数发送请求
代理proxies写法
#使用字典存储
proxies={
'key':'value'
'http':'主机(ip)+:+port'
}
import urllib.request
url = 'https://www.ip138.com/?jdfwkey=fkqhb1'
headers={
'User-Agent':
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36'
}#找到页面的ua
# 请求对象的定制
request = urllib.request.Request(url = url,headers= headers)
# 模拟浏览器访问服务器
# response = urllib.request.urlopen(request)
proxies = {
'http':'212.107.29.43:80'
}
# handler build_opener open
handler = urllib.request.ProxyHandler(proxies = proxies)
opener = urllib.request.build_opener(handler)
response = opener.open(request)
# 获取响应的信息
content = response.read().decode('utf-8')
# 保存
with open('daili.html','w',encoding='utf-8')as fp:
fp.write(content)
(1)高度匿名代理不改变客户机的请求,这样在服务器看来就像有个真正的客户浏览器在访问它,
这时客户的真实IP是隐藏的,服务器端不会认为我们使用了代理。
(2)普通匿名代理能隐藏客户机的真实IP,但会改变我们的请求信息,
服务器端有可能会认为我们使用了代理。不过使用此种代理时
,虽然被访问的网站不能知道你的ip地址,但仍然可以知道你在使用代理,
当然某些能够侦测ip的网页仍然可以查到你的ip。
(3)透明代理,它不但改变了我们的请求信息,还会传送真实的IP地址。
代理池
将多个代理放在一个列表中,当使用时,随机使用其中一个代理,这样可以避免只使用一个代理而导致ip被封
import urllib.request
proxies_pool = [
{'http':'118.24.219.151:16817111'},
{'http':'118.24.219.151:16817222'},
]
import random
proxies = random.choice(proxies_pool)#随机选择其中一个一个代理
url = 'http://www.baidu.com/s?wd=ip'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36'
}
request = urllib.request.Request(url = url,headers=headers)
handler = urllib.request.ProxyHandler(proxies=proxies)
opener = urllib.request.build_opener(handler)
response = opener.open(request)
content = response.read().decode('utf-8')
with open('daili.html','w',encoding='utf-8')as fp:
fp.write(content)