Python爬虫之正则表达式于xpath的使用教学及案例

正则表达式

常用的匹配模式

python 复制代码
\d # 匹配任意一个数字
\D # 匹配任意一个非数字
\w # 匹配任意一个单词字符(数字、字母、下划线)
\W # 匹配任意一个非单词字符
.  # 匹配任意一个字符(除了换行符)
[a-z] # 匹配任意一个小写字母
[\u4e00-\u9fa5] # 匹配任意一个汉字
^  # 匹配字符串的开始
$ # 匹配字符串的结束
? # 匹配0次或1次
+ # 匹配1次或多次
* # 匹配任意次
{n} # 匹配n次
{n,} # 至少匹配n次
{n, m} # 至少匹配n次, 最多匹配m次
a|b # 匹配a或者b
() # 匹配括号内的表达式

正则表达式的基础演示

Python 复制代码
# 1.匹配符合指定个数的字符串
# 导入正则表达式的库
import re
tel = '123456'
tel1 = '1234567'
result = re.match("^\d{6}$",tel)
result1 = re.match("\d{6}$",tel1)
result3 = re.match("\d{6}", tel)
print(result)  # 返回结果:<re.Match object; span=(0, 6), match='123456'>
print(result1)  # 返回结果:None
print(result3)	# 返回结果:<re.Match object; span=(0, 6), match='123456'>
Python 复制代码
# 1.匹配汉字
name = '啦啦1啦'
name2 = '2哈哈哈'
# match是从开头开始搜索,开头有汉字就有,没汉字就没有
result = re.match("[\u4e00-\u9fa5]{2,4}", name)
result1 = re.match("[\u4e00-\u9fa5]{2,4}", name2)  # 从开头开始搜索
# search是全局搜索
result2 = re.search("[\u4e00-\u9fa5]{2,4}", name2)
result3 = re.search("[\u4e00-\u9fa5]{2,4}", name)
print(result)
print(result1)
print(result2)
print(result3)
# 返回的结果依次是:
# <re.Match object; span=(0, 2), match='啦啦'>
# None
# <re.Match object; span=(1, 4), match='哈哈哈'>
# <re.Match object; span=(0, 2), match='啦啦'>
Python 复制代码
# 3. search 只匹配一次,findall 对整个字符串进行检索
keys = 'good good study 2012 , day day up 2022'
result = re.search('good', keys)
print('匹配1条:', result)
# 返回的结果: 匹配1条: <re.Match object; span=(0, 4), match='good'>
result2 = re.findall('good', keys)
print('匹配多条并以列表的格式返回:', result2)
# 返回的结果: 匹配多条并以列表的格式返回: ['good', 'good']

正则表达式与爬虫结合小案例,爬取豆瓣top250的图片

Python 复制代码
import re
import requests
import os
# 网页URL爬取
headers = {
             'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36'}
response = requests.get(
              'https://movie.douban.com/top250',headers=headers)
print(response.text)
 # <img width="100" alt="寻梦环游记" src="https://img2.doubanio.com/view/photo/s_ratio_poster/public/p2505426431.jpg" class="">
title = 'width="100" alt="(.*?)" '
zp = 'src="(.*?)" class=""'
select = 'width="100" alt="(.*?)" src="(.*?)" class=""'
name = re.findall(title, response.text)
zpUrl = re.findall(zp, response.text)
ok = re.findall(select, response.text)
print(name)
print(zpUrl)
print(ok)

# 创建保存图片的目录
save_dir = 'downloaded_images'
if not os.path.exists(save_dir):
    os.makedirs(save_dir)
for i, ii in enumerate(ok):
    # print(i)
    print(f'电影{ii[0]}的海报下载地址:{ii[1]}')
    # 下载图片内容
    img_data = requests.get(ii[1]).content
    # 构建保存路径
    file_path = os.path.join(save_dir, f'{i+1}.{ii[0]}.jpg')
    # 保存图片
    with open(file_path, 'wb') as file:
        file.write(img_data)
        print(f'Image {i+1} saved to {file_path}')
else:
    print('Failed to retrieve the webpage')

正则表达式中的 .*?.* 的区别

在正则表达式中,.*?.* 都用于匹配任意数量的字符,但它们的匹配方式有所不同。

1. .*的理解

  • 定义.* 匹配任意数量的字符(包括零个字符),并且是 贪婪(greedy)的。
  • 贪婪模式 :贪婪模式会尽可能多地匹配字符。例如,在字符串 abc123def 中,正则表达式 a.*d 将匹配整个字符串,因为 .* 会尽可能地匹配到最后的 d
  • 示例
    • 输入abc123def
    • 正则a.*d
    • 匹配结果abc123def

2. .*?的理解

  • 定义.*? 同样匹配任意数量的字符(包括零个字符),但它是 非贪婪(lazy)的。
  • 非贪婪模式 :非贪婪模式会尽可能少地匹配字符,优先匹配最短的字符串。例如,在同样的字符串 abc123def 中,正则表达式 a.*?d 只会匹配 abd 之间的字符,结果是 abc123def 中的 a 和第一个 d 之间的最短部分。
  • 示例
    • 输入abc123def
    • 正则a.*?d
    • 匹配结果abc123d

总结

  • .* 是贪婪的,会尽量多地匹配字符,直到最后一个符合条件的字符。
  • .*? 是非贪婪的,会尽量少地匹配字符,优先返回最短的符合条件的字符串。

将爬取的图片以wb保存二进制文件

正则表达式获取豆瓣电影评分和参评人数

解析网页另一好用方法xpath

通过提问逐步理解

1.提问1:xm1和htm1分别代表什么意思?有什么区别

  • xml:可扩展的标记语言,html:超文本标记语句
  • 相同点:成双成对,又开始有结束。
  • 区别:xml的标签可以自定义,语法更自由

2.提问2:xpath的作用

  • xpath使用路径表达式在xml或html文档中查找目标信息

3.提问3:如果想使用xpath,必须安装哪个库(其中使用了清华镜像)

Python 复制代码
pip install lxml -i https://pypi.tuna.tsinqhua.edu.cn/simple 

4.问题四: 如何构建etree树(使用的网页网址为https://movie.douban.com/top250)

任务4的案例源发如下:

Python 复制代码
import requests
from lxml import etree

# 通过读取本地下载好的网页文件再对网页内容进行解析提取
file = open('demo1.html', 'r', encoding='utf-8')
# 读取目前网页内容
content = file.read()

# 构建etree树后,才可以使用xpath表达式
html = etree.HTML(content)

# 使用XPath提取图片的src属性
image_urls = html.xpath('//a/img/@src')

# 获取电影名称
title = html.xpath('//span[@class="title"][1]/text()')
print(title)
# 下载图片
for i, url in enumerate(image_urls):
    # 设置图片保存路径
    file_path = f"图片/{i}{title[i]}.webp"
    # 下载图片
    response = requests.get(url)
    if response.status_code == 200:
        with open(file_path, 'wb') as f:
            f.write(response.content)
        print(f"图片已下载到: {file_path}")
    else:
        print(f"图片下载失败: {url}")

效果如下:

相关推荐
进击的六角龙20 分钟前
Python中处理Excel的基本概念(如工作簿、工作表等)
开发语言·python·excel
一只爱好编程的程序猿40 分钟前
Java后台生成指定路径下创建指定名称的文件
java·python·数据下载
Aniay_ivy1 小时前
深入探索 Java 8 Stream 流:高效操作与应用场景
java·开发语言·python
gonghw4031 小时前
DearPyGui学习
python·gui
向阳12181 小时前
Bert快速入门
人工智能·python·自然语言处理·bert
engchina1 小时前
Neo4j 和 Python 初学者指南:如何使用可选关系匹配优化 Cypher 查询
数据库·python·neo4j
兆。1 小时前
掌握 PyQt5:从零开始的桌面应用开发
开发语言·爬虫·python·qt
南宫理的日知录2 小时前
99、Python并发编程:多线程的问题、临界资源以及同步机制
开发语言·python·学习·编程学习
coberup2 小时前
django Forbidden (403)错误解决方法
python·django·403错误
龙哥说跨境2 小时前
如何利用指纹浏览器爬虫绕过Cloudflare的防护?
服务器·网络·python·网络爬虫