网络爬虫(Python:Requests、Beautiful Soup笔记)

网络爬虫(Python:Requests)

  • 网络协议简要介绍
    • 一。OSI参考模型
    • 二、TCP/IP参考模型
      • 对应关系
      • TCP/IP各层实现的协议
        • 应用层
        • 传输层
        • 网络层
      • HTTP协议
        • HTTP请求
        • HTTP响应
        • HTTP状态码
  • Requests(Python)
    • Requests模块支持的http方法
      • GET
      • HEAD
      • POST
      • PUT
      • DELETE
      • TRACE
      • OPTIONS
      • CONNECT
    • 异常
    • Requests库请求时需要注意的事项
  • Python正则表达式(re模块)
  • Beautiful Soup(bs4)
    • Beautiful Soup支持的解析器
    • 选择子节点、父节点和兄弟节点
    • 方法选择器
      • find_all方法
      • find方法
    • CSS选择器
  • lxml(Python)

网络协议简要介绍

一。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真正意义上实现了多路径并行传输,在连接建立阶段,建立多条路径,然后使用多条路径同时传输数据。
网络层
  • lP:Internet 协议。通过路由选择将下一条IP封装后交给接口层。IP数据报是无连接服务。
  • ICMP:Internet 控制报文协议。是网络层的补充。用于在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 OK
  • 202 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协议是使用明文数据传输的网络协议。端口80
  • HTTPS协议。HTTP协议的安全升级版,在HTTP的基础上增加了数据加密。端口443

列举请求头中常见的字段?

  • User-Agent:客户端请求标识
  • Accept:传输文件类型
  • Referer:请求来源
  • cookie:登录凭据

Requests(Python)

Requests模块支持的http方法

GET

当客户端向Web服务器请求一个资源的时候使用;它被用来访问静态资源,比如HTML文档和图片等

本机ip地址查询:http://httpbin.org/ip

通过requests.get(url, headers=None, params=None)方法可以发送GET请求,其中url为请求地址,headers为请求头部,params为请求参数。

import requests

headers = {
    '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', headers=headers)
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',params=data)
#查看了是哪个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(url=url,headers=header)
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, data=None, json=None, headers=None, timeout=None)
  • 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_python@sina.com",
    "password": "abcd1234"
}

# 实例化session方法,用于自动化的记录session信息
session = requests.session()

# 发送了一个POST请求,并且提供了login_data数据
# login_response = requests.post(url="http://yushu.talelin.com/login", data=login_data)
# 1.需要把原来的requests替换为实例化好的session
login_response = session.post(url="http://yushu.talelin.com/login", data=login_data)
# print(login_response.text)
# 登录之后,请求个人信息页的时候是失败的
# 可以在请求头中提供cookies就可以访问个人信息页面了
# personal_response = requests.get(url="http://yushu.talelin.com/personal")
# 自动化的带上session,个人的登录凭据信息
personal_response = session.get(url="http://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(r'<span>(.*?)</span>')
    # 图书的描述
    desc_search = re.compile(r'summary">(.*?)</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?q=python&page={}".format(i)
        response = requests.get(url=url, headers=header)
        handle_detail_re(response.text)

if __name__ == '__main__':
    main()

Beautiful Soup(bs4)

Beautiful Soup 是 Python 用于解析 HTML 和 XML 文件的第三方库,可以从 HTML 和 XML 文件中提取数据。

Beautiful Soup支持的解析器

在这里插入图片描述

基本元素说明
Tag标签,基本信息组织单元,分别用<>和</>标明开头和结尾
Name标签的名字,p></p>的名字是‘p’,格式:<tag>.name
Attributes标签的属性,字典形式组织,格式:<tag>.attrs
NavigableString标签内非属性字符串,<>…<>中字符串,格式:<tag>.string
Commeent标签内字符串的注释部分,一种特殊的 Comment类型
# 安装的是beautifulsoup4,但是导包的时候,是通过bs4来导入的,并且导入的是大写的BeautifulSoup
from bs4 import BeautifulSoup

html = """
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title" name="dromouse"><b>The Dormouse's story</b></p>
<p class="story">Once upon a time there were three little sisters; and their names were
<a href="http://example.com/elsie" class="sister" id="link1"><!-- Elsie --></a>,
<a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
<a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
and they lived at the bottom of a well.</p>
<p class="story">...</p>
"""
# lxml提前安装好,pip install lxml,第一个参数是html代码段,第二个参数是解析器
soup = BeautifulSoup(html, 'lxml')
# 查看经过bs4实例化,初始化的代码段
print(soup.prettify())
# 获取到的是数据结构,tag,tag有很多方法,如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'])
### 输出
<html>
 <head>
  <title>
   The Dormouse's story
  </title>
 </head>
 <body>
  <p class="title" name="dromouse">
   <b>
    The Dormouse's story
   </b>
  </p>
  <p class="story">
   Once upon a time there were three little sisters; and their names were
   <a class="sister" href="http://example.com/elsie" id="link1">
    <!-- Elsie -->
   </a>
   ,
   <a class="sister" href="http://example.com/lacie" id="link2">
    Lacie
   </a>
   and
   <a class="sister" href="http://example.com/tillie" id="link3">
    Tillie
   </a>
   ;
and they lived at the bottom of a well.
  </p>
  <p class="story">
   ...
  </p>
 </body>
</html>
<class 'bs4.element.Tag'>
The Dormouse's story
<head><title>The Dormouse's story</title></head>
<p class="title" name="dromouse"><b>The Dormouse's 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, name=None, 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 BeautifulSoup

html='''
<div class="panel">
    <div class="panel-heading">
        <h4>Hello</h4>
    </div>
    <div class="panel-body">
        <ul class="list" id="list-1" name="elements">
            <li class="element">Foo</li>
            <li class="element">Bar</li>
            <li class="element">Jay</li>
        </ul>
        <ul class="list" id="list-1">
            <li class="element">Foo2</li>
            <li class="element">Bar2</li>
            <li class="element">Jay2</li>
        </ul>
        <ul class="list list-small" id="list-2">
            <li class="element">Foo</li>
            <li class="element">Bar</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(id="list-1"))
#class在Python中是一个关键字,find_all方法里面要用class的时候,后面加上一个下划线
# print(soup.find_all(class_="list"))

#可以通过text参数来获取文本的值,可以传递正则表达式,返回是一个列表
# print(soup.find_all(text=re.compile("Foo\d")))

#find方法,返回的是一个单个的元素,第一个匹配的元素,而find_all返回的是所有值的列表
# print(soup.find(name="ul"))


"""
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 BeautifulSoup

html='''
<div class="panel">
    <div class="panel-heading">
        <h4>Hello</h4>
    </div>
    <div class="panel-body">
        <ul class="list" id="list-1">
            <li class="element">Foo</li>
            <li class="element">Bar</li>
            <li class="element">Jay</li>
        </ul>
        <ul class="list list-small" id="list-2">
            <li class="element">Foo</li>
            <li class="element">Bar</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-2,class为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/

lxml(Python)

Python读写xml(xml,lxml)

#导入lxml库,etree
from lxml import etree


#准备的html数据,不完整,html,body,li不完整
html_data = '''
<div>
  <ul>
       <li class="item-0"><a href="link1.html">first item</a></li>
       <li class="item-1"><a href="link2.html">second item</a></li>
       <li class="item-inactive"><a href="link3.html"><span class="bold">third item</span></a></li>
       <li class="item-1"><a href="link4.html">fourth item</a></li>
       <li class="item-0"><a href="link5.html">fifth item</a>
   </ul>
</div>
'''
#使用etree.HTML
html = etree.HTML(html_data)
#etree.tostring,decode()
# <html><body><div>
#   <ul>
#        <li class="item-0"><a href="link1.html">first item</a></li>
#        <li class="item-1"><a href="link2.html">second item</a></li>
#        <li class="item-inactive"><a href="link3.html"><span class="bold">third item</span></a></li>
#        <li class="item-1"><a href="link4.html">fourth item</a></li>
#        <li class="item-0"><a href="link5.html">fifth 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[@href='link1.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 BeautifulSoup


def download_images(url, headers):
    """

    :param url:
    :param headers:
    :return:
    """
    # 发送HTTP请求并获取网页内容
    response = requests.get(url, headers=headers)
    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)
            continue


headers = {
    '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):
    # 替换为目标网站的URL
    url = 'https://dxs.moe.gov.cn/zx/a/hd_sxjm_sxjmlw_2022qgdxssxjmjslwzs_2022ctlw/230613/{}.shtml?source=hd_sxjm_sxjmlw_2022qgdxssxjmjslwzs'.format(
        i)
    # 调用函数进行图片下载
    download_images(url, headers)


for i in range(1820271, 1820297, 2):
    # 替换为目标网站的URL
    url = 'https://dxs.moe.gov.cn/zx/a/hd_sxjm_sxjmlw_2022qgdxssxjmjslwzs/221106/{}.shtml?source=hd_sxjm_sxjmlw_2022qgdxssxjmjslwzs'.format(
        i)
    # 调用函数进行图片下载
    download_images(url, headers)

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

探索深度学习:从理论到实践的全面指南

探索深度学习&#xff1a;从理论到实践的全面指南 摘要&#xff1a; 本文旨在提供一个关于深度学习的全面指南&#xff0c;带领读者从理论基础到实践应用全方位了解这一技术。我们将介绍深度学习的历史、基本原理、常用算法和应用场景&#xff0c;并通过Python代码示例和Tens…

Python | CAP - 累积精度曲线分析案例

CAP通常被称为“累积精度曲线”&#xff0c;用于分类模型的性能评估。它有助于我们理解和总结分类模型的鲁棒性。为了直观地显示这一点&#xff0c;我们在图中绘制了三条不同的曲线&#xff1a; 一个随机的曲线&#xff08;random&#xff09;通过使用随机森林分类器获得的曲线…

docker基础学习笔记

文章目录 Docker简介Linux下安装DockerDocker常用命令Docker网络Docker存储docker-composedockerfile制作镜像私有仓库镜像导入导出参考 Docker简介 定义&#xff1a;Docker是一个开源的应用容器引擎优势&#xff1a; 一键部署&#xff0c;开箱即用&#xff1a;容器使用基于im…

openlayers+jsts 实现对行政区以外的区域进行遮罩(兼容多面的情况,兼容不同的ol版本)

先抛效果图,该区域有很多个小面 之前在网上搜到的方式实现 Openlayers 为目标范围以外的区域添加遮罩 - 知乎 核心代码如下&#xff0c;如果您不需要兼容全国的所有省市&#xff0c;而刚好要加地区又是连贯的区域的话&#xff0c;该方法可行&#xff0c;但是如果需要兼容全国…

微服务实战系列之Nginx(技巧篇)

前言 今天北京早晨竟然飘了一些“雪花”&#xff0c;定睛一看&#xff0c;似雪非雪&#xff0c;像泡沫球一样&#xff0c;原来那叫“霰”。 自然中&#xff0c;雨雪霜露雾&#xff0c;因为出场太频繁&#xff0c;认识门槛较低&#xff0c;自然不费吹灰之力&#xff0c;即可享受…

HarmonyOS开发(七):构建丰富页面

1、组件状态管理 1.1、概述 在应用中&#xff0c;界面一般都是动态的。界面会根据不同状态展示不一样的效果。 ArkUI作为一种声明式UI&#xff0c;具有状态驱动UI更新的特点&#xff0c;当用户进行界面交互或有外部事件引起状态改变时&#xff0c;状态的变会会触发组件的自动…

大量索引场景下 Easysearch 和 Elasticsearch 的吞吐量差异

最近有客户在使用 Elasticsearch 搜索服务时发现集群有掉节点&#xff0c;并且有 master 收集节点信息超时的日志&#xff0c;节点的负载也很高&#xff0c;不只是 data 节点&#xff0c;master 和协调节点的 cpu 使用率都很高&#xff0c;看现象集群似乎遇到了性能瓶颈。 查看…

autojs-练手-简单的视频号点赞(初阶版)

注释很详细&#xff0c;直接上代码&#xff08;简单的练手实践&#xff0c;仅供参考&#xff09; //设置点赞次数 var num50; //等待权限授予 auto.waitFor(); //进入点赞流程 while(num!0) {//先向下滑一个视频scrollDown();//使用auto.js找到点赞控件的id&#xff08;每个人不…

Redis 面试题——持久化

目录 1.概述1.1.Redis 的持久化功能是指什么&#xff1f;1.2.Redis 有哪些持久化机制&#xff1f; 2.RDB2.1.什么是 RDB 持久化&#xff1f;2.2.Redis 中使用什么命令来生成 RDB 快照文件&#xff1f;2.3.如何在 Redis 的配置文件中对 RDB 进行配置&#xff1f;2.4.✨RDB 持久化…

Scrapy爬虫异步框架之持久化存储(一篇文章齐全)

1、Scrapy框架初识&#xff08;点击前往查阅&#xff09; 2、Scrapy框架持久化存储&#xff08;点击前往查阅&#xff09; 3、Scrapy框架内置管道&#xff08;点击前往查阅&#xff09; 4、Scrapy框架中间件&#xff08;点击前往查阅&#xff09; Scrapy 是一个开源的、基于…

jQuery_06 过滤器的使用

什么是过滤器&#xff1f; 过滤器就是用来筛选dom对象的&#xff0c;过滤器是和选择器一起使用的。在选择了dom对象后在进行过滤筛选。 jQuery对象中存储的dom对象顺序与页面标签声明有关系。 声明顺序就是dom中存放的顺序 1.基本过滤器 使用dom对象在数组中的位置来作为过滤条…

.NET6 开发一个检查某些状态持续多长时间的类

📢欢迎点赞 :👍 收藏 ⭐留言 📝 如有错误敬请指正,赐人玫瑰,手留余香!📢本文作者:由webmote 原创📢作者格言:新的征程,我们面对的不仅仅是技术还有人心,人心不可测,海水不可量,唯有技术,才是深沉黑夜中的一座闪烁的灯塔 !序言 在代码的世界里,时常碰撞…

【Linux学习】基础IO

目录 八.系统文件IO 8.1 前言 8.2 C语言文件IO C语言常用的基本函数 C语言默认打开的的三个流 8.3 系统文件IO open接口 close接口 write接口 read接口 8.4 C语言文件IO与系统文件IO的关系 八.系统文件IO 8.1 前言 系统文件 I/O&#xff08;输入/输出&#xff09;是指在…

【电路笔记】-快速了电阻

电阻类型 文章目录 电阻类型1、概述2、电阻器的组成类型2.1 碳电阻器2.2 薄膜电阻器2.3 绕线电阻器 3、总结 电阻器是所有电子元件中最基本、最常用的元件&#xff0c;人们几乎认为电阻器是理所当然的&#xff0c;但它们在电路中起着至关重要的作用。 1、概述 有许多不同类型的…

17.找出1000之内的所有完数。

文章目录 前言一、题目描述 二、题目分析 三、解题 程序运行代码 前言 本系列为循环结构编程题&#xff0c;点滴成长&#xff0c;一起逆袭。 一、题目描述 一个数如果恰好等于它的因子之和&#xff0c;这个数就称为“完数”。例如&#xff0c;⑥的因子为1、2、3&#xff0c;而…

2024年最新最全的Jmeter接口测试必会技能:jmeter_HTTP Cookie管理器

HTTP Cookie管理器 HTTP Cookie管理器可以像浏览器一样自动存储和发送cookie&#xff0c;以这种自 动收集的方式收集到的cookie不会在cookie manager中进行展示&#xff0c;但是运行后&#xff0c; 可以通过 查看结果树&#xff08;监听器&#xff09;可以查看到cookie信息 除…

【开源】基于JAVA的天然气工程业务管理系统

项目编号&#xff1a; S 021 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S021&#xff0c;文末获取源码。} 项目编号&#xff1a;S021&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块三、使用角色3.1 施工人员3.2 管理员 四…

hive杂谈

数据仓库是一个面向主题的、集成的、非易失的、随时间变化的&#xff0c;用来支持管理人员决策的数据集合&#xff0c;数据仓库中包含了粒度化的企业数据。 数据仓库的主要特征是&#xff1a;主题性、集成性、非易失性、时变性。 数据仓库的体系结构通常包含4个层次&#xff…

(数据结构)顺序表的定义

#include<stdio.h> //顺序表的实现——静态分配 #define MAX 10 //定义最大长度 typedef struct List {int data[MAX]; //用静态的数组存放数据int lenth; //顺序表现在的长度 }List; //顺序表的初始化 void ChuShiHua(List L) {L.lenth 0; //将顺序表的长度初始化…

NAS非接入层协议学习(二)

在无线通信网络中 NAS (Non-Access Stratum)做为非接入层是演进分组系统(或5G核心网)中的一组协议。NAS用于在用户设备(UE)和移动管理实体(MME/AMF)之间传送非无线电信令&#xff0c;以实现NR/LTE/E-UTRAN接入。 NAS在协议栈中是控制面的最高层。 NAS协议分组中可以将其分为两…