个人 网站备案,兰州官网优化服务,如何做泛解析网站,室内装修设计图片网络爬虫#xff08;Python#xff1a;Requests、Beautiful Soup笔记#xff09; 网络协议简要介绍一。OSI参考模型二、TCP/IP参考模型对应关系TCP/IP各层实现的协议应用层传输层网络层 HTTP协议HTTP请求HTTP响应HTTP状态码 Requests#xff08;Python#xff09;Requests… 网络爬虫PythonRequests、Beautiful Soup笔记 网络协议简要介绍一。OSI参考模型二、TCP/IP参考模型对应关系TCP/IP各层实现的协议应用层传输层网络层 HTTP协议HTTP请求HTTP响应HTTP状态码 RequestsPythonRequests模块支持的http方法GETHEADPOSTPUTDELETETRACEOPTIONSCONNECT 异常Requests库请求时需要注意的事项 Python正则表达式re模块Beautiful Soupbs4Beautiful Soup支持的解析器选择子节点、父节点和兄弟节点方法选择器find_all方法find方法 CSS选择器 lxmlPython 网络协议简要介绍
一。OSI参考模型 七层功能应用层7提供应用程序间通信表示层6处理数据格式、数据加密等会话层5建立、维护和管理会话传输层4建立主机端到端连接网络层3寻址和路由选择数据链路层2提供介质访问、链路管理等物理层1比特流传输
二、TCP/IP参考模型
TCP/IP协议栈应用层提供应该程序网络接口传输层建立端到端连接网络层寻址和路由选择数据链路层物理介质访问物理层二进制数据流传输
对应关系 TCP/IP各层实现的协议
应用层
HTTP超文本传输协议基于TCP使用80号端口是用于从www服务器传输超文本到本地浏览器的传输协议。SMTP简单邮件传输协议基于TCP使用25号端口是一组用于由源地址到目的地址传送邮件的规则用来控制信件的发送、中转。FTP文件传输协议基于TCP一般上传下载用FTP服务数据端口是20号控制端口是21号。TELNET:远程登录协议基于TCP使用23号端口是Internet远程登陆服务的标准协议和主要方式。为用户提供了在本地计算机上完成远程主机工作的能力。在终端使用者的电脑上使用telnet程序连接到服务器。使用明码传送保密性差、简单方便。SSH:安全外壳协议基于TCP使用22号端口为建立在应用层和传输层基础上的安全协议。SSH是目前较可靠专为远程登录会话和其他网络服务提供安全性的协议。
传输层
TCP传输控制协议。一种面向连接的、可靠的、基于字节流的传输层通信协议。UDP用户数据报协议。一种面向无连接的通讯协议不可靠的、基于报文的传输层通信协议。SCTP:流量传输控制协议。一种面向连接的流传输协议。MPTCP:多路径传输控制协议。TCP的多路径版本。SCTP虽然在首发两端有多条路径但实际只是使用一条路径传输当该条路径出现故障时不需要断开连接而是转移到其他路径。MPTCP真正意义上实现了多路径并行传输在连接建立阶段建立多条路径然后使用多条路径同时传输数据。
网络层
lPInternet 协议。通过路由选择将下一条IP封装后交给接口层。IP数据报是无连接服务。ICMPInternet 控制报文协议。是网络层的补充。用于在P主机、路由器之间传递控制消息检测网络通不通、主机是否可达、路由是否可用等网络本身的消息。ARP地址解析协议。通过目标设备的IP地址查询目标设备的MAC地址以保证通信的顺利进行。RARP反向地址解析协议。
HTTP协议
HTTP (HyperText Transfer Protocol,超文本传输协议)是互联网上应用最为广泛的一种网络协议它是基于TCP的应用层协议 客户端和服务端进行通信的一种规则它的模式非常简单就是客户端发起请求服务端响应请求
HTTP请求
请求行:包含请求方法、请求地址和HTTP协议版本消息报头:包含一系列的键值对请求正文可选)︰注意和消息报头之间有一个空行 谷歌浏览器开发者工具 preserve log 在我们开发页面时点击按钮触发了某个接口并跳转了页面这时Network中的信息会刷新不做保留这个时候我们只需要勾选上谷歌开发者工具的preserve log就可以保留上一个页面接口调用信息从而方便我们查看。
GET 从服务器获取指定请求地址的资源的信息它通常只用于读取数据就像数据库查询一样不会对资源进行修改。
POST 向指定资源提交数据比如提交表单上传文件)请求服务器进行处理。数据被包含在请求正文中这个请求可能会创建新的资源或更新现有的资源。
PUT 通过指定资源的唯一标识在服务器上的具体存放位置)请求服务器创建或更新资源。
DELETE 请求服务器删除指定资源。
HEAD 与GET方法类似从服务器获取资源信息,和GET方法不同的是HEAD不含有呈现数据仅仅是HTTP头信息。HEAD 的好处在于使用这个方法可以在不必传输全部内容的情况下就可以获得资源的元信息或元数据)。
OPTIONS 该方法可使服务器传回资源所支持的所有HTTP请求方法。
HTTP响应
状态行:包含HTTP协议版本、状态码和状态描述以空格分隔响应头:即消息报头包含一系列的键值对响应正文:返回内容注意和响应头之间有一个空行 HTTP状态码
1XX 消息–请求已被服务接收继续处理
2XX 成功–请求已成功被服务器接收、理解、并接受
200 OK202 Accepted接收202 Accepted接收203 Non-Authoritative lnformation非认证信息204 No Content无内容
3XX 重定向–需要后续操作才能完成这一请求
301 Moved Permanently请求永久重定向302 Moved Temporarily请求临时重定向304 Not Modified文件未修改可以直接使用缓存的文件305 Use Proxy 使用代理
4XX 请求错误–请求含有词法错误或者无法被执行
400 Bad Request由于客户端请求有语法错误不能被服务器所理解401 Unauthorized请求未经授权。这个状态代码必须和WWW-Authenticate报头域一起使用403 Forbidden服务器收到请求但是拒绝提供服务。服务器通常会在响应正文中给出不提供服务的原因404 Not Found请求的资源不存在例如输入了错误的URL
5XX 服务器错误–服务器在处理某个正确请求时发生错误
500 Internal Server Error服务器发生不可预期的错误导致无法完成客户端的请求503 Service Unavailable服务器当前不能够处理客户端的请求在一段时间之后服务器可能会恢复正常504 Gateway Time-out 网关超时 简述HTTP和HTTPS协议区别?
HTTP协议是使用明文数据传输的网络协议。端口80HTTPS协议。HTTP协议的安全升级版在HTTP的基础上增加了数据加密。端口443
列举请求头中常见的字段?
User-Agent客户端请求标识Accept传输文件类型Referer请求来源cookie登录凭据
RequestsPython
Requests模块支持的http方法
GET
当客户端向Web服务器请求一个资源的时候使用它被用来访问静态资源比如HTML文档和图片等
本机ip地址查询http://httpbin.org/ip
通过requests.get(url, headersNone, paramsNone)方法可以发送GET请求其中url为请求地址headers为请求头部params为请求参数。
import requestsheaders {User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36
}
response requests.get(http://www.example.com, headersheaders)
print(response.text)
# content参数返回HTTP响应的二进制数据源形式为bytes。
# status_code参数返回HTTP响应的状态码形式为整数。可以设置verify参数为False来跳过SSL证书验证。可以设置timeout参数来设置请求超时时间避免长时间等待无响应。可以使用proxies参数来设置代理服务器。
import requests
#构造的URL的数据一定要和Post请求做好区分
data {key1:value1,key2:value2}
#使用的是GET请求的方法,params关键字一定要做好区分
response requests.get(http://httpbin.org/get,paramsdata)
#查看了是哪个URL给我们返回的数据
print(response.url)
#查看返回头,注意是headers不是header
print(response.headers)
#查看返回体
print(response.text)cookies
import requests
url https://www.baidu.com
#定制请求头,使用了一个标准的浏览器的UA
header {user-agent:Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3610.2 Safari/537.36}
response requests.get(urlurl,headersheader)
print(response.headers)
#cookie是一个对象RequestsCookieJar行为和字典类似
print(response.cookies)
print(response.cookies[BIDUPSID])IP池和隧道代理的区别
动态IP池中获取的是大量的IP需要爬虫自己切换代理IP并发送请求。只需要将请求发给隧道由隧道自行选择可用代理并转发请求。
proxy {# http://用户名:密码代理的接口信息http: http://uesrname:password代理地址:端口,https: http://uesrname:password代理地址:端口
}cookie和session的区别?
cookie和session都是用来跟踪浏览器用户身份的会话方式cookie数据保存在客户端,session数据保存在服务器端。Cookie过期看生成时设置的值session过期看服务器设定。
HEAD
当客户端向Web服务器请求一个资源的一些信息而不是资源的全部信息的时候使用主要用于确认URL的有效性以及资源更新的日期时间等
POST
当客户端向服务端发送信息或者数据的时候使用表单提交向Web服务器发送大量的复杂的数据)
requests.post(url, dataNone, jsonNone, headersNone, timeoutNone)data发送的数据字典或者元组列表形式json发送JSON格式的数据headers请求头信息timeout请求的最长等待时间
PUT
当客户端向Web服务端指定URL发送一个替换的文档或者上传一个新文档的时侯使用
DELETE
当客户端尝试从Web服务端删除一个由请求URL唯一标识的文档的时候使用
TRACE
当客户端要求可用的代理服务器或者中间服务更改请求来宣布自己的时候使用
OPTIONS
当客户端想要决定其他可用的方法来检索或者处理Web服务端的一个文档时使用
CONNECT
当客户端想要确定一个明确的连接到远程主机的时候使用通常便于通过Http代理服务器进行SSL加密通信( Https )连接使用
session
import requests#在requests模块中有session方法# 为什么没有携带请求头
# 不需要提供定制化的请求头直接使用python默认的请求头就可以# 需要提供请求的数据
login_data {email: dazhuang_pythonsina.com,password: abcd1234
}# 实例化session方法用于自动化的记录session信息
session requests.session()# 发送了一个POST请求并且提供了login_data数据
# login_response requests.post(urlhttp://yushu.talelin.com/login, datalogin_data)
# 1.需要把原来的requests替换为实例化好的session
login_response session.post(urlhttp://yushu.talelin.com/login, datalogin_data)
# print(login_response.text)
# 登录之后请求个人信息页的时候是失败的
# 可以在请求头中提供cookies就可以访问个人信息页面了
# personal_response requests.get(urlhttp://yushu.talelin.com/personal)
# 自动化的带上session,个人的登录凭据信息
personal_response session.get(urlhttp://yushu.talelin.com/personal)
print(personal_response.text)异常
遇到网络问题如:DNS查询失败、拒绝连接等)时Requests会 抛出一个 ConnectionError 异常如果HTTP请求返回了不成功的状态码,Response.raise_for_status()会抛出一个HTTPError异常遇到网络问题如:DNS查询失败、拒绝连接等)时Requests会抛出一个ConnectionError 异常如果HTTP请求返回了不成功的状态码Response.raise_for_status()会抛出一个HTTPError异常若请求超时则抛出一个 Timeout异常若请求超过了设定的最大重定向次数则会抛出一个TooManyRedirects异常
所有Requests显式抛出的异常都继承自requests.exceptions.RequestException。
IP代理有哪些分类区别是什么?
透明代理的意思是爬虫请求数据的时候会携带真实IP普通匿名代理会改变请求信息高匿代理隐藏真实IP
Requests库请求时需要注意的事项
当请求频率较高时可能会出现请求失败响应码为429的情况。这是由于目标网站的反爬虫模块对请求频率进行了限制。常见的应对措施包括
设置请求头信息。请求头中包括User-Agent、Referer等信息用于欺骗反爬模块尽量模拟浏览器的行为。设置请求延时。请求之间加入一定的延时避免请求频率过高。使用代理。使用代理服务器进行请求使反爬虫模块难以跟踪。分布式爬虫。将爬虫程序部署到不同的服务器上。遵循robots协议。robots协议是一种规范爬虫采集方式的协议爬虫必须遵循这个协议。
总的来说爬虫程序要注意遵守网站的规定遵守一定的爬虫道德准则避免对网站造成过大的负担。此外也要避免过度使用爬虫以免被封禁或被针对。
参考https://requests.readthedocs.io/en/latest/
Python正则表达式re模块
Python正则表达式re模块
import requests
import re# 请求图书列表页的链接
# 获取每一条图书信息
# 格式化每一条图书信息def handle_detail_re(content):处理列表页返回数据:param content: response.text:return: print# 图书条目正则表达式,re.S可以进行全文匹配item_search re.compile(description-font.*?/div, re.S)# 获取每一页图书条目数据all_item item_search.findall(content)# 图书的名称title_search re.compile(title(.*?)/span)# 获取图书的作者出版社价格author_press_price_search re.compile(rspan(.*?)/span)# 图书的描述desc_search re.compile(rsummary(.*?)/span)for item in all_item:# 获取到了作者出版社价格 的列表信息author_press_price author_press_price_search.search(item).group(1).split(/)if len(author_press_price) 3:print({title: title_search.search(item).group(1),author: author_press_price[0],press: author_press_price[1],price: author_press_price[2],desc: desc_search.search(item).group(1)})def main():header {User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.72 Safari/537.36}for i in range(1, 5):url http://*****.*******.com/book/search?qpythonpage{}.format(i)response requests.get(urlurl, headersheader)handle_detail_re(response.text)if __name__ __main__:main()Beautiful Soupbs4
Beautiful Soup 是 Python 用于解析 HTML 和 XML 文件的第三方库可以从 HTML 和 XML 文件中提取数据。
Beautiful Soup支持的解析器 基本元素说明Tag标签基本信息组织单元分别用和/标明开头和结尾Name标签的名字p/p的名字是‘p’格式:tag.nameAttributes标签的属性字典形式组织格式:tag.attrsNavigableString标签内非属性字符串…中字符串格式:tag.stringCommeent标签内字符串的注释部分一种特殊的 Comment类型
# 安装的是beautifulsoup4但是导包的时候是通过bs4来导入的并且导入的是大写的BeautifulSoup
from bs4 import BeautifulSouphtml
htmlheadtitleThe Dormouses story/title/head
body
p classtitle namedromousebThe Dormouses story/b/p
p classstoryOnce upon a time there were three little sisters; and their names were
a hrefhttp://example.com/elsie classsister idlink1!-- Elsie --/a,
a hrefhttp://example.com/lacie classsister idlink2Lacie/a and
a hrefhttp://example.com/tillie classsister idlink3Tillie/a;
and they lived at the bottom of a well./p
p classstory.../p# lxml提前安装好pip install lxml,第一个参数是html代码段第二个参数是解析器
soup BeautifulSoup(html, lxml)
# 查看经过bs4实例化初始化的代码段
print(soup.prettify())
# 获取到的是数据结构tagtag有很多方法如string
print(type(soup.title))
# 来查看文档中title的属性值
print(soup.title.string)
print(soup.head)
# 当有多个节点的时候我们当前的这种选择模式只能匹配到第一个节点其他节点会被忽略
print(soup.p)
# 获取节点的名称
print(soup.title.name)
# attrs会返回标签的所有属性值,返回的是一个字典
print(soup.p.attrs)
print(soup.p.attrs[name])
# 返回的节点属性可能是列表也可能是字符串需要进行实际的判断
print(soup.p[name])
print(soup.p[class])
### 输出
htmlheadtitleThe Dormouses story/title/headbodyp classtitle namedromousebThe Dormouses story/b/pp classstoryOnce upon a time there were three little sisters; and their names werea classsister hrefhttp://example.com/elsie idlink1!-- Elsie --/a,a classsister hrefhttp://example.com/lacie idlink2Lacie/aanda classsister hrefhttp://example.com/tillie idlink3Tillie/a;
and they lived at the bottom of a well./pp classstory.../p/body
/html
class bs4.element.Tag
The Dormouses story
headtitleThe Dormouses story/title/head
p classtitle namedromousebThe Dormouses story/b/p
title
{class: [title], name: dromouse}
dromouse
dromouse
[title]选择子节点、父节点和兄弟节点
contents获取直接子节点该属性返回一个列表list类的实例children获取直接子节点该属性返回list_iterator类的实例这个可迭代对象可以用for循环进行迭代descendants获取所有的子孙节点该属性返回一个产生器generator)for循环迭代才可输出产生器的值parent获取某个节点的直接父节点返回当前节点的父节点的Tag对象parents获取某个节点的所有父节点返回当前节点所有父节点的可迭代对象for循环迭代出所有父节点Tag对象next_sibling获取当前节点的下一个兄弟节点previous_sibling获取当前节点的上一个兄弟节点next_siblings获取当前节点后面的所有兄弟节点返回一个可迭代对象previous_siblings获取当前节点前面的所有兄弟节点返回一个可迭代对象
注节点之间的换行符或其他文本会被当成文本节点处理是bs4.element.NavigableString类的实例而普通节点是bs4.element.Tag类的实例
方法选择器
find_all方法
根据节点名、属性、文本内容等选择所有符合要求的节点该方法属于Tag对象又由于BeautifulSoup是Tag的子类所以find_all方法在BeautifulSoup对象上也可以调用find_all方法以当前Tag对象对应的节点作为根开始继续选取节点嵌套查询。
def find_all(self, nameNone, attrs {}, recursive True, text None, limit None, **kwargs):name参数用于指定节点名会选取所有节点名与name参数相同的节点返回一个bs4.element.ResultSet对象该对象是可迭代的通过迭代获取每一个符合条件的节点Tag对象attrs参数通过节点的属性查找attrs参数是一个字典类型key是节点属性名value是节点属性值text参数搜索匹配的文本节点传入的参数可以是字符串也可以是正则表达式对象
find方法
用于查询满足条件的第一个节点返回的是bs4.element.Tag对象
#通过属性来进行查询
#通过text文本来获取匹配的文本import re
from bs4 import BeautifulSouphtml
div classpaneldiv classpanel-headingh4Hello/h4/divdiv classpanel-bodyul classlist idlist-1 nameelementsli classelementFoo/lili classelementBar/lili classelementJay/li/ulul classlist idlist-1li classelementFoo2/lili classelementBar2/lili classelementJay2/li/ulul classlist list-small idlist-2li classelementFoo/lili classelementBar/li/ul/div
/div
soup BeautifulSoup(html,lxml)
#attrs传入的是属性参数,类型是字典,attrs{id:list-1}
# print(soup.find_all(attrs{id:list-1}))
# print(soup.find_all(attrs{name:elements}))
#也可以直接传入ID这个参数
# print(soup.find_all(idlist-1))
#class在Python中是一个关键字find_all方法里面要用class的时候后面加上一个下划线
# print(soup.find_all(class_list))#可以通过text参数来获取文本的值可以传递正则表达式返回是一个列表
# print(soup.find_all(textre.compile(Foo\d)))#find方法,返回的是一个单个的元素,第一个匹配的元素,而find_all返回的是所有值的列表
# print(soup.find(nameul))
find_parents 和 find_parent前者返回所有祖先节点后者返回直接父节点。
find_next_siblings 和 find_next_sibling前者返回后面所有的兄弟节点后者返回后面第一个兄弟节点。
find_previous_siblings 和 find_previous_sibling前者返回前面所有的兄弟节点后者返回前面第一个兄弟节点。
find_all_next 和 find_next前者返回节点后所有符合条件的节点后者返回第一个符合条件的节点。
find_all_previous 和 find_previous前者返回节点前所有符合条件的节点后者返回第一个符合条件的节点。CSS选择器
使用CSS选择器需要使用Tag对象的select方法该方法接收一个字符串类型的CSS选择器选择器如
.classname选取样式名为classname的节点也就是class属性值是classname的节点nodename选取节点名为nodename的节点#idname选取id属性值为idname的节点
嵌套选择节点可以将节点选择器、方法选择器和CSS选择器混合使用 获取属性值与文本select方法返回Tag对象的集合可以用Tag对象的方式获取节点属性值和文本内容获取属性值可以使用attrs也可以直接使用[…]方式引用节点的属性获取节点的文本内容可以使用get_text方法也可以使用string属性。
#使用css选择器只需要呢调用select方法传入css选择器即可from bs4 import BeautifulSouphtml
div classpaneldiv classpanel-headingh4Hello/h4/divdiv classpanel-bodyul classlist idlist-1li classelementFoo/lili classelementBar/lili classelementJay/li/ulul classlist list-small idlist-2li classelementFoo/lili classelementBar/li/ul/div
/div
soup BeautifulSoup(html,lxml)
#需要调用select方法传入css选择器
# print(soup.select(.panel .panel-heading))#获取ul标签下所有Li标签
# print(soup.select(ul li))#获取id为list-2class为element两个Li标签
# print(type(soup.select(#list-2 .element)[0]))#支持嵌套选择
#先获取到ul标签tag类型,for 调用select方法在次传入css选择器
for ul in soup.select(ul):for li in ul.select(li):#调用tag类型里面的方法string方法来获取文本内容# print(li.string)print(li[class])#支持使用属性获取元素
# for ul in soup.select(ul):
# print(ul[id])#建议大家使用find find_all查询匹配单个结果或多个结果
#css选择器非常的熟悉那么就可以使用css选择器参考https://beautifulsoup.cn/
lxmlPython
Python读写xmlxmllxml
#导入lxml库,etree
from lxml import etree#准备的html数据,不完整html,body,li不完整
html_data
divulli classitem-0a hreflink1.htmlfirst item/a/lili classitem-1a hreflink2.htmlsecond item/a/lili classitem-inactivea hreflink3.htmlspan classboldthird item/span/a/lili classitem-1a hreflink4.htmlfourth item/a/lili classitem-0a hreflink5.htmlfifth item/a/ul
/div#使用etree.HTML
html etree.HTML(html_data)
#etree.tostring,decode()
# htmlbodydiv
# ul
# li classitem-0a hreflink1.htmlfirst item/a/li
# li classitem-1a hreflink2.htmlsecond item/a/li
# li classitem-inactivea hreflink3.htmlspan classboldthird item/span/a/li
# li classitem-1a hreflink4.htmlfourth item/a/li
# li classitem-0a hreflink5.htmlfifth item/a
# /li/ul
# /div
# /body/html
# print(etree.tostring(html).decode())
#返回_Element就是整个xml树的根节点
# print(type(html))
#使用的是双斜杠,返回是一个列表每一个元素都是element类型,列表里面的每一个element类型的元素就
#代表我们获取到的标签元素
# result html.xpath(//li/a/text())
#获取li标签下面所有的class属性值
# result html.xpath(//li/class)
#获取的li标签href值为link1.html这个a标签,使用了单引号如果外面使用的是
#双引号内部一定要使用单引号,大家一定要注意
# result html.xpath(//li/a[hreflink1.html]/text())
#我们需要获取span标签一定要注意span他是a标签的子元素,而不是li标签的子元素,使用双斜杠
# result html.xpath(//li//span)
#我们使用了last()函数最后一个标签-1代表倒数第二个标签
result html.xpath(//li[last()]/a/href)
print(result)批量下载图片
import os
import requests
from bs4 import BeautifulSoupdef download_images(url, headers)::param url::param headers::return:# 发送HTTP请求并获取网页内容response requests.get(url, headersheaders)soup BeautifulSoup(response.text, html.parser)# 图片保存路径for title in soup.find_all(title):title title.contents[0].split()[0]save_folder os.path.join(.\images, title)if not os.path.exists(save_folder):os.makedirs(save_folder)# 获取所有图片的标签img_tags soup.find_all(img)# 遍历图片标签并下载图片for img_tag in img_tags:try:img_url img_tag[src]# 如果图片URL是相对路径则拼接完整URL# if img_url.startswith(/):# img_url url img_url# 发送HTTP请求并保存图片img_response requests.get(img_url)img_data img_response.content# 提取图片文件名img_filename img_url.split(/)[-1]# 拼接保存路径save_path os.path.join(save_folder, img_filename)# 保存图片with open(save_path, wb) as img_file:img_file.write(img_data)print(f已保存图片: {save_path})except Exception as error:print(error)continueheaders {User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36}
for i in range(1843443, 1843445, 1):# 替换为目标网站的URLurl https://dxs.moe.gov.cn/zx/a/hd_sxjm_sxjmlw_2022qgdxssxjmjslwzs_2022ctlw/230613/{}.shtml?sourcehd_sxjm_sxjmlw_2022qgdxssxjmjslwzs.format(i)# 调用函数进行图片下载download_images(url, headers)for i in range(1820271, 1820297, 2):# 替换为目标网站的URLurl https://dxs.moe.gov.cn/zx/a/hd_sxjm_sxjmlw_2022qgdxssxjmjslwzs/221106/{}.shtml?sourcehd_sxjm_sxjmlw_2022qgdxssxjmjslwzs.format(i)# 调用函数进行图片下载download_images(url, headers)