Python爬虫知识体系-----Urllib库的使用

news2024/11/23 11:11:17
数据科学、数据分析、人工智能必备知识汇总-----Python爬虫-----持续更新:https://blog.csdn.net/grd_java/article/details/140574349

文章目录

    • 1. 基本使用
    • 2. 请求对象的定制
    • 3. 编解码
      • 1. get请求方式:urllib.parse.quote()
      • 2. urllib.parse.urlencode()
    • 4. post请求方式
      • 1. 基本使用
      • 2. 处理第二种反爬手段
    • 5. ajax
      • 1. get请求
      • 2. 如何爬取多页数据
      • 3. post请求
    • 6. 异常URLError\HTTPError
    • 7. cookie登录
    • 8. handler处理器
      • 1. Handler处理器基本使用
      • 2. 代理
      • 3. 代理池

1. 基本使用

本库无需用pip安装,是python本身自带的库,可以直接使用

模拟浏览器访问服务器的数据
  1. 进入百度,查看网页源码
    在这里插入图片描述
  2. 这就是我们要获取的数据
    在这里插入图片描述
通过urllib获取数据,了解编码问题

在这里插入图片描述

  1. 首先我们先导包,我们需要用urllib模块的request
  2. 之后我需要用request中的urlopen函数访问对应url,并返回一个响应体,我们将其保存到response变量中
  3. 有了响应体对象后,通过read方法,将源码数据读取出来。上图中我们可以看到,确实读取出来了,但是是以b'开头的,表示读取的是字节形式的二进制文件,我们会发现读取的数据都不是正常用户可以看懂的字符,而是十六进制编码
response服务器返回的数据解析,返回结果乱码的原因
  1. response的数据类型是HttpResponse
  2. 我们需要将返回的数据由字节码转为我们能看懂的字符串,也就是解码decode操作,因为response自动进行了字符串转字节码,也就是编码encode操作
  3. responose对象常用的函数
read() #字节形式读取二进制 扩展:rede(5)返回前几个字节
readline() #读取一行
readlines() #一行一行读取 直至结束
getcode() #获取状态码
geturl() #获取url
getheaders() #获取headers,响应头,状态信息
urllib.request.urlretrieve() #请求网页,请求图片,请求视频
进行解码操作
  1. 我们可以在页面源码中,看到它的编码格式是utf-8
    在这里插入图片描述
  1. 所以我们只需要对其进行utf-8格式的解码即可
    在这里插入图片描述
# _*_ coding : utf-8 _*_
# @Time : 2024/7/21 星期日 16:12
# @Author : Taylor Sinclair(殷志鹏)
# @File : basicUsing
# @Project : test
# @Description : 使用urllib获取百度首页源码

'''导包(start)'''
import urllib.request;
'''导包(end)'''

# 1. 定义一个url,我们访问的地址
url = "http://www.baidu.com";
# 2. 模拟浏览器向服务器发送请求并获取响应体
response = urllib.request.urlopen(url);
# 3. 读取响应体内容,并对其进行utf-8解码
content = response.read().decode('utf-8');
print(content);
urllib.request.urlretrieve()下载

此函数有两个参数,url表示要下载的内容的url地址,而filename表示下载完成后,我们要保存的地址和文件类型(文件后缀名)

  1. 下载网页:我们将百度首页的html文件,下载到当前文件夹的百度.html文件中
    在这里插入图片描述
    在这里插入图片描述
'''导包(start)'''
import urllib.request;
'''导包(end)'''

# 1. 定义一个url,我们访问的地址
url = "http://www.baidu.com";
# 2. 模拟浏览器向服务器发送请求并将html文件下载保存到百度.html文件中
response = urllib.request.urlretrieve(url,"百度.html");
  1. 下载图片
  1. 因为我们现在还没有学到后面的知识,所以我们先手动获取一张图片的地址
    在这里插入图片描述
  2. 只需要将函数的url参数换为图片的地址即可
    在这里插入图片描述
    在这里插入图片描述
'''导包(start)'''
import urllib.request;
'''导包(end)'''
# 1. 定义一个url,我们访问的地址
url = "https://wxls-cms.oss-cn-hangzhou.aliyuncs.com/online/2024-04-18/218da022-f4bf-456a-99af-5cb8e157f7b8.jpg";
# 2. 模拟浏览器向服务器发送请求并将html文件下载保存到百度.html文件中
response = urllib.request.urlretrieve(url,"图片.jpg");
  1. 下载视频
  1. 还是找到一个视频(我们这里初学者,爬取时不要去找什么类似哔哩哔哩这样需要特殊处理的,我们就找一些简单的,直接用url可以爬取的,例如好看视频的),按下f12,选中视频控件,然后双击src中的视频路径,将其复制下来
    在这里插入图片描述
  2. 然后就可以通过url下载到这个视频
    在这里插入图片描述
    在这里插入图片描述
'''导包(start)'''
import urllib.request;
'''导包(end)'''

# 1. 定义一个url,我们访问的地址
url = "https://vdept3.bdstatic.com/mda-qdqxvr04ju7kwxez/cae_h264/1714102071853507436/mda-qdqxvr04ju7kwxez.mp4?v_from_s=hkapp-haokan-hbe&auth_key=1721564882-0-0-26db109d9d14804c8ba64ac44d474da6&bcevod_channel=searchbox_feed&pd=1&cr=0&cd=0&pt=3&logid=1682548574&vid=2405378101862107884&klogid=1682548574&abtest=101830_2-102148_2-17451_1"
# 2. 模拟浏览器向服务器发送请求并将html文件下载保存到百度.html文件中
response = urllib.request.urlretrieve(url,"视频.mp4");

2. 请求对象的定制

UA
  1. User Agent(用户代理):简称UA,它是一个特殊字符串头,使得服务器能够识别客户使用的操作系统及版本、CPU 类型、浏览器及版本、浏览器渲染引擎、浏览器语言、浏览器插件等

这是我们爬虫的第一道大关,简称UA校验,简单来说,如果我们不做特殊处理,他能识别到我们是假数据,而不是真实的用户,从而进行反爬

  1. 为了解决这个问题,我们需要进行伪装,获取正确的UA
如果不操作UA,直接访问https://www.baidu.com,就会被反爬

在这里插入图片描述

可以看到,我没有设置UA,爬取的数据是反爬处理过的数据,不是我们想要的

获取UA
  1. 打开我们想要爬取的url,按下f12,进入network,然后刷新页面,在network中找到对应url请求,在请求头中,找到UA
    在这里插入图片描述
  1. 复制UA,存放到python代码的字典中,注意,字典的名字并不硬性要求为headers,这里只是为了代码可读性而起名为headers
    在这里插入图片描述
请求对象的定制
  1. 有了headers后,我们就可以用url和headers定制一个请求对象,也就是Request请求对象
    在这里插入图片描述
  1. 有了这个对象,我们访问指定url时,直接使用这个request对象即可,可以发现,爬取到了想要的数据,而不是反爬处理的数据
    在这里插入图片描述
'''导包(start)'''
import urllib.request
'''导包(end)'''

# 1. 定义一个url,我们访问的地址,这里使用的协议是https,是加了ssh的安全协议,会直接反爬
url = "https://www.baidu.com"
# 2. 定制请求头header,将UA放入
headers = {"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:128.0) Gecko/20100101 Firefox/128.0"}
# 3. 定制请求对象,有了这个对象,我们就可以用这个请求对象访问指定url了,而这个请求对象,设置了我们定制的headers
request = urllib.request.Request(url, headers=headers)
# 4. 使用定制的请求对象访问
response = urllib.request.urlopen(request)
print(response.read().decode("utf8"))

3. 编解码

1. get请求方式:urllib.parse.quote()

问题
  1. 我们请求数据时,使用的是Unicode编码(也有例外),例如我们百度周杰伦时
  1. url应该是https://www.baidu.com/s?wd=%E5%91%A8%E6%9D%B0%E4%BC%A6,其中%E5%91%A8%E6%9D%B0%E4%BC%A6是周杰伦的Unicode编码
  2. 而不是https://www.baidu.com/s?wd=周杰伦
  1. 我们不知道某些字符的Unicode编码怎么办呢?就可以使用urllib.parse.quote()函数,这个函数会将字符转为Unicode编码
urllib.parse.quote("周杰伦")#结果为:%E5%91%A8%E6%9D%B0%E4%BC%A6
解决办法

将需要使用Unicode编码的部分,全部使用quote函数生成,然后拼接
在这里插入图片描述

'''导包(start)'''
import urllib.request
import urllib.parse
'''导包(end)'''
# 1. 定义一个url,我们访问的地址,这里使用的协议是https,是加了ssh的安全协议,会直接反爬
url = "https://www.baidu.com/s?wd="
paras = urllib.parse.quote("周杰伦")
url+=paras
# 2. 定制请求头header,将UA放入
headers = {"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:128.0) Gecko/20100101 Firefox/128.0"}
# 3. 定制请求对象,有了这个对象,我们就可以用这个请求对象访问指定url了,而这个请求对象,设置了我们定制的headers
request = urllib.request.Request(url="url", headers=headers)
# 4. 使用定制的请求对象访问
response = urllib.request.urlopen(request)
print(response.read().decode("utf8"))

2. urllib.parse.urlencode()

问题
  1. 当只有一个参数的时候,自然可以使用urllib.parse.quote()来解决
  2. 但是有多个参数呢?总不能一个个拼接吧
  3. 因此,urllib.parse.urlencode()就可以一次性转多个参数
    在这里插入图片描述
'''导包(start)'''
import urllib.request
import urllib.parse
'''导包(end)'''
# 1. 定义一个url,我们访问的地址,这里使用的协议是https,是加了ssh的安全协议,会直接反爬
url = "https://www.baidu.com/s?" # url中无需手动拼接参数了
data = {"wd":"周杰伦","sex":"男"} # 将需要的参数放在字典中
paras = urllib.parse.urlencode(data); # 使用函数将其转为Unicode编码
url+=paras # 拼接URL
print(url) 

4. post请求方式

1. 基本使用

以百度翻译为例
  1. 进入百度翻译进行抓包,我们输入单词spider,可以发现,每输入一个字母都会进行Post请求,返回文件时sug,里面我们请求的表单,就是我们输入的单词
    在这里插入图片描述
  1. 而响应体中,就是搜索到的翻译
    在这里插入图片描述

一定要找对接口,这是爬虫的一大难点,如果无法找到正确的接口,就无法获取正确的数据

  1. 所以我们现在就有了爬虫的目标,url是https://fanyi.baidu.com/sug,请求方式是Post,请求参数是"kw":“spider”
    在这里插入图片描述
    在这里插入图片描述
具体实现

在这里插入图片描述

  1. 注意,Post请求需要额外提交表单,也就是代码中的data字典。所白了和get请求不同,参数不是拼接在url的?后面,而是需要放到请求体的data中
  2. data需要编码,首先urlencode将其编为Unicode,然后进行encode编码,编为utf-8
  3. 如果返回的是json数据,需要用json.loads函数进行转换才能不乱码
'''导包(start)'''
import urllib.request
import urllib.parse
import json
'''导包(end)'''
# 1. 定义一个url,我们访问的地址,这里使用的协议是https,是加了ssh的安全协议,会直接反爬
url = "https://fanyi.baidu.com/sug" # url中无需手动拼接参数了
data = {"kw":"spider"} # 将需要的参数放在字典中
# 2. 定制请求头header,将UA放入
headers = {"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, likeGecko) Chrome/74.0.3729.169 Safari/537.36"}
# 3. Post请求的参数必须编码,首先urlencode将其编为Unicode,然后进行encode编码,编为utf-8
data = urllib.parse.urlencode(data).encode("utf-8")
# 4. 定制Post请求头,需要额外传入data,请求参数表
request = urllib.request.Request(url=url, data=data,headers=headers)
# 5. 使用定制的请求对象访问
response = urllib.request.urlopen(request)
# 6. 获取读取到的数据
content = response.read().decode("utf-8")
# 7. 将返回数据转为json输出
print("直接输出会乱码",content)
obj = json.loads(content)
print("转为json数据输出即可",obj)

2. 处理第二种反爬手段

百度详细翻译为例
  1. 依然是百度翻译,只不过这次我们前往旧版本进行抓包,的抓包是https://fanyi.baidu.com/v2transapi?from=en&to=zh这个,它里面是单词更加详细的释义
    在这里插入图片描述
  1. 它的请求表单更多
    在这里插入图片描述
  1. 我们直接复制出来的数据是不规范的
    在这里插入图片描述
  2. 我们通过一些文本工具,例如Notepad++来进行正则表达式的查找和替换
    在这里插入图片描述
    (.*) (.*)代表前面有若干个任意字符,后面有若干个任意字符,中间是一堆空格(直接复制原数据中间的空格)“\1”:\2表示替换为前面第一个小括号匹配到的值加双引号,中间替换为冒号
"from":"en"
"to":"zh"
"query":"spider"
"simple_means_flag":"3"
"sign":"63766.268839"
"token":"f1ebb176f73e77bc705c404803d693c0"
"domain":"common"
"ts":"1721619631760"
现在我们用python发送请求

在这里插入图片描述

会发现被反爬了,只要被反爬,就考虑是不是他需要的东西我们没有给够

  1. 找到它的请求头
    在这里插入图片描述
  2. 用文本软件改成key:value格式
    在这里插入图片描述
  3. 放到代码的headers中,但是注意要将"Accept-Encoding":"gzip, deflate, br, zstd"注释掉,因为这句指定了编码格式,这里没有我们常用的utf-8格式
  1. 不将其注释掉会报这个错误
    在这里插入图片描述
  2. 所以一定要注释掉
    在这里插入图片描述
  1. 然后就可以爬到数据了
    在这里插入图片描述
'''导包(start)'''
import urllib.request
import urllib.parse
import json
'''导包(end)'''
# 1. 定义一个url,我们访问的地址,这里使用的协议是https,是加了ssh的安全协议,会直接反爬
url = "https://fanyi.baidu.com/v2transapi?from=en&to=zh" # url中无需手动拼接参数了
data = {"from":"en",
"to":"zh",
"query":"spider",
"simple_means_flag":"3",
"sign":"63766.268839",
"token":"f1ebb176f73e77bc705c404803d693c0",
"domain":"common",
"ts":"1721619631760"} # 将需要的参数放在字典中
# 2. 定制请求头header,将UA放入
headers = {"Host":"fanyi.baidu.com",
"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:128.0) Gecko/20100101 Firefox/128.0",
"Accept":"*/*",
"Accept-Language":"zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2",
# "Accept-Encoding":"gzip, deflate, br, zstd",
"Content-Type":"application/x-www-form-urlencoded; charset=UTF-8",
"Acs-Token":"1721545207246_1721619631762_cdhky/lsyn0MwcIYubxg6g+yGB7DWVkvHHhzEF4G/zcEHCTNSb+RWz1TzDIehhT0nRMmJ9iOG0UTlCwvejzWeFbqDj0oiIHda9ly0lnIom+SdYR9JWNykRa5+vLO2b5OOpNmeq7DzPRxGnhopulH0pTglWMPVnViHVFDQI5dKr3/IXBRVuAmdI3Be0YchzL49xTKBc2T46mceMQXmYBsRKMc7VJg+/+yMSqPPD5ukSCJ+ulvWC6cVgzdbyg3hXuOK6NgROzB1BB2PdzzTBrhRVWS/iOKWwcB1y1/YmMrVGWavgMMYB+IYqm8wp0pB00qCD1/RXRyn+tlWHhHyUsmsyQmFg5YRyesvTHE08RE+KRRcGAGQ07jtfRAeOKqzHlVihlaYs8xaqcyoMi2ihGIHpq0gUB4xV2R2Og+5d2dzcUuVCUwTknsvHTiKkci3QKFK8VVKHQqGzBfab+JYgZfTA==",
"X-Requested-With":"XMLHttpRequest",
"Content-Length":"134",
"Origin":"https://fanyi.baidu.com",
"Connection":"keep-alive",
"Referer":"https://fanyi.baidu.com/",
"Cookie":'BIDUPSID=014FB2528D0EFCB53D0516AA9DDB229D; PSTM=1708246679; H_PS_PSSID=60359_60465_60492_60502; BAIDUID=014FB2528D0EFCB53D0516AA9DDB229D:SL=0:NR=10:FG=1; BDUSS=25VSy16NGhRV0xIfk5Kcy02SVdPaDZBWW9CcUNTNkM5UFdPZzJXTmthQn5kZnBsRVFBQUFBJCQAAAAAAAAAAAEAAAC9HTU-ztLM~czs0uIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH~o0mV~6NJlT; H_WISE_SIDS=60359_60465_60492_60502; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; ZFY=Qxrlg:B2RssHj4jywgOL:BJKmhUwoOwa7GUA2JeI:BD0Xc:C; BA_HECTOR=81a48425a401212l212h202l8i6npi1j9pgid1u; RT="z=1&dm=baidu.com&si=d748cf44-d8fb-4cf8-bfe9-88bf5213250c&ss=lywevcbe&sl=a&tt=goe&bcn=https%3A%2F%2Ffclog.baidu.com%2Flog%2Fweirwood%3Ftype%3Dperf&ld=yve1&ul=z3kl&hd=z3tg"; delPer=0; PSINO=2; BDRCVFR[feWj1Vr5u3D]=I67x6TjHwwYf0; ab_sr=1.0.1_NjNiODA3MTZjNzE4ZjA2YjUyNWFhNGU1ODc2ZDQ0MTQ1YmE4ODUzYTE4YzJkYjkzMWVhNWFhMmJkNDFlZWMwN2Q4YjU2YWQyOTdmZmE4MjE1YjY2YzQ3YjIzODM2NGEwYTY2NjM1YmI3MjRjODYyNGQ1M2RhZjA4NzUzYjQ3NjVlNjM4ZGY5MzJkYTllOTEwNmYxMDFlYzBmNzViNzFiYTU3MzBjNDljYzYzYWZkZDZkM2E3OWM5ZWVkNDE4YzdmYjQwNTRjM2E4YWM5ZDQwZmVmNWQ3ZWYxZDM2OWRiMmY1ZjgwM2YxYzNhYTAzZDA4YmE4Yzc2MzIxM2U5ZDM4Mg==; smallFlowVersion=old; Hm_lvt_64ecd82404c51e03dc91cb9e8c025574=1721619578; Hm_lpvt_64ecd82404c51e03dc91cb9e8c025574=1721619578; REALTIME_TRANS_SWITCH=1; FANYI_WORD_SWITCH=1; HISTORY_SWITCH=1; SOUND_SPD_SWITCH=1; SOUND_PREFER_SWITCH=1',
"Sec-Fetch-Dest":"empty",
"Sec-Fetch-Mode":"cors",
"Sec-Fetch-Site":"same-origin"}
# 3. Post请求的参数必须编码,首先urlencode将其编为Unicode,然后进行encode编码,编为utf-8
data = urllib.parse.urlencode(data).encode("utf-8")
# 4. 定制Post请求头,需要额外传入data,请求参数表
request = urllib.request.Request(url=url, data=data,headers=headers)
# 5. 使用定制的请求对象访问
response = urllib.request.urlopen(request)
# 6. 获取读取到的数据
content = response.read().decode("utf-8")
# 7. 将返回数据转为json输出
obj = json.loads(content)
print("转为json数据输出即可",obj)
  1. 但是,我们其实只需要Cookie就够了,甚至有了它,UA都可以不用
    在这里插入图片描述

5. ajax

1. get请求

以豆瓣电影榜单为例
  1. 进入豆瓣电影,点击排行榜,点击动作分类,就会出现动作类电影的榜单,而这些数据可见来源于https://movie.douban.com/j/chart/top_list?type=5&interval_id=100:90&action=&start=0&limit=20这个请求
    在这里插入图片描述
  1. 同时可以发现,它的响应体是ajax数据,也就是json数据
将第一页的json数据保存到本地

在这里插入图片描述
在这里插入图片描述

json数据在pycharm中可以通过快捷键Ctrl + Alt + L来快速进行排版,方便我们查看

'''导包(start)'''
import urllib.request
import urllib.parse
import json
'''导包(end)'''
url = "https://movie.douban.com/j/chart/top_list?type=5&interval_id=100:90&action=&start=0&limit=20"
# 2. 定制请求头header,将UA放入
headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:128.0) Gecko/20100101 Firefox/128.0'
}

request = urllib.request.Request(url=url,headers=headers)
response = urllib.request.urlopen(request)
content = response.read().decode("utf-8")

# 3. 将爬取的数据保存到本地
with open('douban.json','w',encoding='utf-8') as fp:
    fp.write(content)

2. 如何爬取多页数据

找接口规律
  1. 上面我们获取了第一页的数据,一共20部电影,接口为https://movie.douban.com/j/chart/top_list?type=5&interval_id=100:90&action=&start=0&limit=20
  2. 然后我们清空network,向下滑页面,让其获取第二页数据,也就是21开始。我们发现接口为https://movie.douban.com/j/chart/top_list?type=5&interval_id=100:90&action=&start=20&limit=20
    在这里插入图片描述
  1. 除了最后的一个参数start不同以外,其余都是相同的。所以我们找到了规律,不同页的数据,只是最后两个参数以20为一页进行变化罢了
    在这里插入图片描述
获取前10页数据
  1. 用一个for循环,url的start参数0开始,不断递增20即可
    在这里插入图片描述
'''导包(start)'''
import urllib.request
import urllib.parse
import json
'''导包(end)'''
# 定制请求头header,将UA放入
headers = {
    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:128.0) Gecko/20100101 Firefox/128.0'
}
# 根据page生成url
def create_requestUrl_byPage(page):
    base_url = "https://movie.douban.com/j/chart/top_list?type=5&interval_id=100:90&action=&"
    data = {
        "start": page*20,
        "limit": 20,
    }
    data = urllib.parse.urlencode(data)
    url = base_url + data
    return url
# 根据url请求响应
def get_content(url):
    request = urllib.request.Request(url=url, headers=headers)
    response = urllib.request.urlopen(request)
    content = response.read().decode("utf-8")
    return content
# 将爬取的数据保存到本地
def output_to_file(content,page):
    with open("第" + str(page) + '页数据.json', 'w', encoding='utf-8') as fp:
        fp.write(content)

# 程序入口
if __name__ == '__main__':
    startPage = 0
    endPage = 10
    for page in range(startPage, endPage):
        url = create_requestUrl_byPage(page)# 根据页码获取url
        print(url)
        content = get_content(url) # 根据url发送get请求,请求内容
        output_to_file(content,page+1) # 根据content,将其保存到文件
  1. 第一页数据,可见爬取到的数据是正确的
    在这里插入图片描述
  1. 第二页数据,也是正确的
    在这里插入图片描述
  1. 最后一页数据
    在这里插入图片描述

3. post请求

以肯德基为例,我们进行餐厅查询

在这里插入图片描述

可以发现数据来源于一个Post接口http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=cname
在这里插入图片描述

我们查看请求头,会发现X-Requested-With:XMLHttpRequest这个参数,表示这个是ajax请求

分析不同页的表单数据,可以发现,只是页码pageIndex不一样而已
在这里插入图片描述

在这里插入图片描述

获取前10页数据
  1. 和前面Post一样,只不过这里返回的是ajax
    在这里插入图片描述
'''导包(start)'''
import urllib.request
import urllib.parse
import json
'''导包(end)'''
# 定制请求头header,将UA放入
headers = {
    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:128.0) Gecko/20100101 Firefox/128.0'
}
# 根据page生成url
def create_requestUrl_byPage(page):
    base_url = "http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=cname"
    data = {
        'cname':'呼和浩特',
        'pid':'',
        'pageIndex':page,
        'pageSize':'10'
    }
    # post请求参数必须编码encode
    data = urllib.parse.urlencode(data).encode('utf-8')
    return [base_url,data];
# 根据url请求响应
def get_content(url,data):
    request = urllib.request.Request(url=url,data=data,headers=headers)
    response = urllib.request.urlopen(request)
    content = response.read().decode("utf-8")
    return content
# 将爬取的数据保存到本地
def output_to_file(content,page):
    with open("第" + str(page) + '页数据.json', 'w', encoding='utf-8') as fp:
        fp.write(content)

# 程序入口
if __name__ == '__main__':
    startPage = 1
    endPage = 10
    for page in range(startPage, endPage+1):
        list = create_requestUrl_byPage(page)# 根据页码获取url
        print(list)
        content = get_content(list[0],list[1]) # 根据url发送get请求,请求内容
        output_to_file(content,page) # 根据content,将其保存到文件
  1. 第一页数据对应
    在这里插入图片描述
  2. 第7页数据
    在这里插入图片描述
  3. 因为一共只有7页,所以后面几页是空
    在这里插入图片描述

6. 异常URLError\HTTPError

  1. HTTPError类是URLError类的子类
  2. 导入的包是urllib.error.HTTPError和urllib.error.URLError
  3. http错误:http错误是针对浏览器无法连接到服务器而增加出来的错误提示。引导并告诉浏览者该页是哪里出了问题
  4. 通过urllib发送请求的时候,有可能会发送失败,这个时候如果想让你的代码更加的健壮,可以通过try‐except进行捕获异常,异常有两类,URLError\HTTPError
HTTPError
  1. 假设访问CSDN上的一篇文章https://blog.csdn.net/grd_java/article/details/140174015,我故意往后面加几个666666,此时这个请求就是错误的,执行代码会直接报错
    在这里插入图片描述
  1. 直接返回报错信息,用户体验很差,因此我们需要捕获异常返回合理的信息
    在这里插入图片描述
# 捕获异常
try:
    request = urllib.request.Request(url, headers=headers)
    response = urllib.request.urlopen(request)
    print(response.read().decode("utf8"))
except urllib.error.HTTPError as e:
    print("请检查访问地址,错误码:",e.code)
URLError
  1. 假设访问百度,但是将域名写错了,此时就会报URL错误,而我们捕获HTTP错误是不行的,因为URLError是HTTPError的父类
    在这里插入图片描述
  1. 捕获
    在这里插入图片描述
'''导包(start)'''
import urllib.request
import urllib.error
'''导包(end)'''
url = "https://www.baidu.coms"
headers = {"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:128.0) Gecko/20100101 Firefox/128.0"}
# 捕获异常
try:
    request = urllib.request.Request(url, headers=headers)
    response = urllib.request.urlopen(request)
    print(response.read().decode("utf8"))
except urllib.error.URLError as e:
    print("URL地址出错:",e.reason)

7. cookie登录

有些数据是必须登录后才能获取的,这种应该如何爬取呢?

  1. 我们先登录,然后进入个人主页,发现个人数据来源于https://weibo.com/ajax/user/popcard/get?id=5458187191
    在这里插入图片描述
  1. 我们直接爬取会提示编码错误,但是我们个人主页确实是utf-8,这是常用的反爬手段,你没有登录,会自动跳转页面,例如跳转到登录页面,而这个页面的编码不是utf-8,一般是gb2312
    在这里插入图片描述
  1. 此时将编码改为gb2312就会发现,爬取到的页面是验证页面
    在这里插入图片描述

此时,我们选择将请求头里面的东西,放在headers中再做尝试,其实依然只需要Cookie而已
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

'''导包(start)'''
import urllib.request
import urllib.error
'''导包(end)'''
url = "https://weibo.com/ajax/user/popcard/get?id=你的id"
headers = {
# 有些网站,是需要判断你的referer是不是从上一个页面进来的,不是的话,也会对你反爬处理
'Referer':'https://weibo.com/u/5458187191',
'Cookie':'你的cookie',
}
# 捕获异常
request = urllib.request.Request(url, headers=headers)
response = urllib.request.urlopen(request)
content = response.read().decode("utf-8")
with open('test.json','w',encoding='utf-8') as f:
    f.write(content)
额外的反爬手段
  1. 请求头中有一个参数’Referer’:‘https://weibo.com/u/5458187191’,
  2. 虽然这个案例不需要,但是有些网站是需要的,这个参数代表上一个页面
  3. 也就是有些网站,是需要判断你的referer是不是从上一个页面进来的,不是的话,也会对你反爬处理
  4. 这个参数一般用于做图片防盗链的,所以我们需要注意这个问题

8. handler处理器

问题
  1. urllib.request.urlopen(url)是不能定制请求头的
  2. urllib.request.Request(url,headers,data)是可以定制请求头的
  3. Handler:可以定制更高级的请求头,随着业务逻辑逐渐复杂,请求对象的定制是无法满足需求的,例如动态cookie和代理都无法使用我们上面学到的定制请求对象来处理

1. Handler处理器基本使用

在这里插入图片描述

'''导包(start)'''
import urllib.request
import urllib.error
'''导包(end)'''
url = "https://www.baidu.com"
headers = {
"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:128.0) Gecko/20100101 Firefox/128.0"
}
# request对象依然需要
request = urllib.request.Request(url, headers=headers)
# 1. 获取handler对象
handler = urllib.request.HTTPHandler()
# 2. 获取openner对象,是构建者设计模式,用handler构建一个openner对象
openner = urllib.request.build_opener(handler)
# 3. openner的open方法
response = openner.open(request)
result = response.read().decode('utf-8')
print(result)

2. 代理

代理的常用功能
  1. 突破自身IP访问限制,访问国外站点
  2. 访问一些单位或团体内部资源

扩展:某大学FTP(前提是该代理地址在该资源的允许访问范围之内),使用教育网内地址段免费代理服务器,就可以用于对教育网开放的各类FTP下载上传,以及各类资料查询共享等服务

  1. 提高访问速度

扩展:通常代理服务器都设置一个较大的硬盘缓冲区,当有外界的信息通过时,同时也将其保存到缓冲区中,当其他用户再访问相同的信息时, 则直接由缓冲区中取出信息,传给用户,以提高访问速度。

  1. 隐藏真实IP

扩展:上网者也可以通过这种方法隐藏自己的IP,免受攻击。

代码配置代理
  1. 创建Reuqest对象
  2. 创建ProxyHandler对象
  3. 用handler对象创建opener对象
  4. 使用opener.open函数发送请求
代理需要的ip去哪找

在这里插入图片描述

百度快代理,会给我们提供很多免费代理ip

实现过程
  1. 我们已知一个代理ip为202.101.213.154,端口号为18014
    在这里插入图片描述
  2. 代码中规定proxies字典时,其中一个代理的格式就是’http’: ‘202.101.213.154:18014’
  1. 可见使用免费代理访问成功,如果免费都不行,那就只能买一个了
    在这里插入图片描述

代码和上面Handler基本使用的唯一区别就是HttpHandler()换成ProxyHandler(proxies= proxies),额外需要指定一个proxies字典

'''导包(start)'''
import urllib.request
import urllib.error
'''导包(end)'''
url = "https://www.baidu.com"
headers = {
"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:128.0) Gecko/20100101 Firefox/128.0"
}
# request对象依然需要
request = urllib.request.Request(url, headers=headers)
# 1. 获取代理handler对象,并指定代理ip字典proxies
proxies = {
    'http': '202.101.213.154:18014',
}
handler = urllib.request.ProxyHandler(proxies= proxies)
# 2. 获取openner对象,是构建者设计模式,用handler构建一个openner对象
openner = urllib.request.build_opener(handler)
# 3. openner的open方法
response = openner.open(request)
result = response.read().decode('utf-8')
print(result)
自己买代理ip
  1. 先生成API链接
    在这里插入图片描述
  2. 点击生成链接后将链接复制到浏览器执行
    在这里插入图片描述
  1. 此时就会给你一个高密的代理ip和端口号
    在这里插入图片描述
  1. 此时,你查询自己的ip时,就会变成代理ip
    在这里插入图片描述

3. 代理池

问题
  1. 就算有一个代理ip,如果你使用这个ip高频次访问一个网站,依然会被封掉
  2. 因此需要一个代理池,多个ip轮番访问,也就是用一堆高密的代理ip进行爬虫,而不是只用几个ip,很快就会被识别为爬虫
随机选择代理ip

在这里插入图片描述

可见上图中,会在代理池中随机挑选ip

'''导包(start)'''
import random
'''导包(end)'''
# 代理池
proxies_pool = [
{'http': '202.101.213.154:1801411111111'},
{'http': '202.101.213.154:1801422222222'},
{'http': '202.101.213.154:1801433333333'}
]
# 随机选中代理池中的一个代理ip
proxies = random.choice(proxies_pool)
proxies1 = random.choice(proxies_pool)
proxies2 = random.choice(proxies_pool)
# 使用代理ip
print(proxies)
print(proxies1)
print(proxies2)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1942401.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数驭未来,景联文科技构建高质大模型数据库

国内应用层面的需求推动AI产业的加速发展。根据IDC数据预测,预计2026年中国人工智能软件及应用市场规模会达到211亿美元。 数据、算法、算力是AI发展的驱动力,其中数据是AI发展的基石,中国的数据规模增长速度预期将领跑全球。 2024年《政府工…

【WAF剖析】10种XSS某狗waf绕过姿势,以及思路分析

原文:【WAF 剖析】10 种 XSS 绕过姿势,以及思路分析 xss基础教程参考:https://mp.weixin.qq.com/s/RJcOZuscU07BEPgK89LSrQ sql注入waf绕过文章参考: https://mp.weixin.qq.com/s/Dhtc-8I2lBp95cqSwr0YQw 复现 网站安全狗最新…

[数据集][目标检测]野猪检测数据集VOC+YOLO格式1000张1类别

数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):1000 标注数量(xml文件个数):1000 标注数量(txt文件个数):1000 标注…

如何查看jvm资源占用情况

如何设置jar的内存 java -XX:MetaspaceSize256M -XX:MaxMetaspaceSize256M -XX:AlwaysPreTouch -XX:ReservedCodeCacheSize128m -XX:InitialCodeCacheSize128m -Xss512k -Xmx2g -Xms2g -XX:UseG1GC -XX:G1HeapRegionSize4M -jar your-application.jar以上配置为堆内存4G jar项…

Web前端:HTML篇(二)元素属性

HTML 属性 属性是 HTML 元素提供的附加信息。 HTML 元素可以设置属性属性可以在元素中添加附加信息属性一般描述于开始标签属性总是以名称/值对的形式出现&#xff0c;比如&#xff1a;name"value"。 属性实例 HTML 链接由 <a> 标签定义。链接的地址在 href …

如何开启或者关闭 Windows 安全登录?

什么是安全登录 什么是 Windows 安全登录呢&#xff1f;安全登录是 Windows 附加的一个组件&#xff0c;它可以在用户需要登录的之前先将登录界面隐藏&#xff0c;只有当用户按下 CtrlAltDelete 之后才出现登录屏幕&#xff0c;这样可以防止那些模拟登录界面的程序获取密码信息…

来聊聊redis集群数据迁移

写在文章开头 本文将是笔者对于redis源码分析的一个阶段的最后一篇&#xff0c;将从源码分析的角度让读者深入了解redis节点迁移的工作流程&#xff0c;希望对你有帮助。 Hi&#xff0c;我是 sharkChili &#xff0c;是个不断在硬核技术上作死的 java coder &#xff0c;是 CS…

JavaScript青少年简明教程:赋值语句

JavaScript青少年简明教程&#xff1a;赋值语句 赋值语句&#xff08;assignment statement&#xff09; JavaScript的赋值语句用于给变量、对象属性或数组元素赋值。赋值语句的基本语法是使用符号 () 将右侧的值&#xff08;称为“源操作数”&#xff09;赋给左侧的变量、属…

Docker Minio rclone数据迁移

docker minio进行数据迁移 使用rclone进行数据迁移是一种非常灵活且强大的方式&#xff0c;特别是在处理大规模数据集或跨云平台迁移时。rclone是一款开源的命令行工具&#xff0c;用于同步文件和目录到多种云存储服务&#xff0c;包括MinIO。下面是使用rclone进行数据迁移至Mi…

【RT摩拳擦掌】RT600 4路音频同步输入1路TDM输出方案

【RT摩拳擦掌】RT600 4路音频同步输入1路TDM输出方案 一&#xff0c; 文章简介二&#xff0c;硬件平台构建2.1 音频源板2.2 音频收发板2.3 双板硬件连接 三&#xff0c;软件方案与软件实现3.1 方案实现3.2 软件代码实现3.2.1 4路I2S接收3.2.2 I2S DMA pingpong配置3.2.3 音频数…

卧室激光投影仪推荐一下哪款效果最好?当贝X5S亮度卧室开灯照样清晰

现在家庭卧室装投影仪也不是什么稀奇的事情了&#xff0c;外面客厅看电视机&#xff0c;里面卧室投影仪直接投白墙各有各的优势。躺在卧室的床上&#xff0c;看超大屏投影真的很惬意。卧室投影的品类比较多&#xff0c;有些价格便宜的投影宣传说卧室看很适合&#xff0c;其实不…

设计模式12-构建器

设计模式12-构建器 由来和动机原理思想构建器模式的C代码实现构建器模式中的各个组件详解1. 产品类&#xff08;Product&#xff09;2. 构建类&#xff08;Builder&#xff09;3. 具体构建类&#xff08;ConcreteBuilder&#xff09;4. 指挥者类&#xff08;Director&#xff0…

实战:OpenFeign使用以及易踩坑说明

OpenFeign是SpringCloud中的重要组件&#xff0c;它是一种声明式的HTTP客户端。使用OpenFeign调用远程服务就像调用本地方法一样&#xff0c;但是如果使用不当&#xff0c;很容易踩到坑。 Feign 和OpenFeign Feign Feign是Spring Cloud组件中的一个轻量级RESTful的HTTP服务客…

rabbitmq生产与消费

一、rabbitmq发送消息 一、简单模式 概述 一个生产者一个消费者模型 代码 //没有交换机&#xff0c;两个参数为routingKey和消息内容 rabbitTemplate.convertAndSend("test1_Queue","haha");二、工作队列模式 概述 一个生产者&#xff0c;多个消费者&a…

C4D2024软件下载+自学C4D 从入门到精通【学习视频教程全集】+【素材笔记】

软件介绍与下载&#xff1a; 链接&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1n8cripcv6ZTx4TBNj5N04g?pwdhfg5 提取码&#xff1a;hfg5 基础命令的讲解&#xff1a; 掌握软件界面和基础操作界面。学习常用的基础命令&#xff0c;如建模、材质、灯光、摄像机…

设计模式-领域逻辑模式-结构映射模式

对象和关系之间的映射&#xff0c;关键问题在于二者处理连接的方式不同。 表现出两个问题&#xff1a; 表现方法不同。对象是通过在运行时&#xff08;内存管理环境或内存地址&#xff09;中保存引用的方式来处理连接的&#xff0c;关系数据库则通过创建到另外一个表的键值来处…

昇思25天学习打卡营第19天|munger85

Diffusion扩散模型 它并没有那么复杂&#xff0c;它们都将噪声从一些简单分布转换为数据样本&#xff0c;Diffusion也是从纯噪声开始通过一个神经网络学习逐步去噪&#xff0c;最终得到一个实际图像 def rearrange(head, inputs): b, hc, x, y inputs.shape c hc // head r…

大数据平台之HBase

HBase是一个高可靠性、高性能、面向列、可伸缩的分布式存储系统&#xff0c;是Apache Hadoop生态系统的重要组成部分。它特别适合大规模结构化和半结构化数据的存储和检索&#xff0c;能够处理实时读写和批处理工作负载。以下是对HBase的详细介绍。 1. 核心概念 1.1 表&#x…

TIA博途V19无法勾选来自远程对象的PUT/GET访问的解决办法

TIA博途V19无法勾选来自远程对象的PUT/GET访问的解决办法 TIA博途升级到V19之后,1500CPU也升级到了V3.1的固件,1200CPU升级到了V4.6.1的固件, 固件升级之后,又出现了很多问题,如下图所示,在组态的时候会多出一些东西, 添加CPU之后,在属性界面可以看到“允许来自远程对象…

第二讲:NJ网络配置

Ethernet/IP网络拓扑结构 一. NJ EtherNet/IP 1、网络端口位置 NJ的CPU上面有两个RJ45的网络接口,其中一个是EtherNet/IP网络端口(另一个是EtherCAT的网络端口) 2、网络作用 如图所示,EtherNet/IP网络既可以做控制器与控制器之间的通信,也可以实现与上位机系统的对接通…