Python爬虫学习笔记-第六课(正则表达式下+csv模块的使用)

1. re模块方法补充

1.1 compile()方法

这个是re模块的工厂方法,用于将字符串形式的正则表达式编译为Pattern模式对象,可以实现更加效率的匹配。第二个参数flag是匹配模式,使用compile()完成一次转换后,再次使用还匹配模式的时候就不能进行转换了。经过compile()转换的正则表达式对象也能使用普通的re方法。

import re
# compile()方法传递匹配模板,返回Pattern对象
pat = re.compile(r'abc')
print(pat, type(pat))
result = pat.match(r'abc123').group()
print(result)

在这里插入图片描述

在这里插入图片描述

1.2 search()和findall()方法

search()方法:在文本内查找,返回第一个匹配到的字符串。它的返回值类型和使用方法与match()一样的,唯一的区别是查找的位置不用固定在文本的开头。
findall()方法:它与search、match的区别在于后两者都是单次匹配,找到一个就结束,直接返回不再查找。而fandall是全文查找,它的返回值是一个匹配到的字符串列表。这个列表没有group()方法,没有start、end和span,也不是匹配对象,仅仅是个列表。如果一项都没有匹配到就返回一个空列表。
在这里插入图片描述

1.3 split()方法

re模块的split()方法和字符串的split()方法很相似,都是利用特定的字符去分割字符串。但是re模块的split()可以使用正则表达式,相比更为灵活。
split()有个参数maxsplit,用于指定分割的次数。
在这里插入图片描述

[]里面的内容加了\对+、*、/进行转义。第三行命令中指定maxsplit=2,截取两段后,剩下的内容自动变成一个字符串。

1.4 sub()方法

sub()方法类似字符串的replace()方法,用指定的内容替换匹配到的字符,可以指定替换次数。
在这里插入图片描述

2. re模块分组

re模块里面有一个分组功能,所谓分组就是已经在匹配到的内容里面去筛选,相当于二次过滤。实现分组靠圆括号(),而获取分组的内容是group()、groups(),在之前已经介绍过。re模块里的几个重要方法在分组上有不同的表现形式,需要区别对待。

示例代码

import re
s = 'apple price is $66, banana price is $22'
# 需求:$66、$22
result = re.search(r'.+\$\d+.+\$\d+', s)
print(result.group())
result = re.search(r'.+(\$\d+).+(\$\d+)', s)
print('result.group() = ', result.group())
print('result.group(1) = ', result.group(1))
print('result.group(2) = ', result.group(2))
print('result.group(0) = ',result.group(0))
print('result.groups() = ', result.groups())

运行结果:
在这里插入图片描述

小总结
group()/group(0) 返回整个分组;
group(1)/(2) 返回第一/二个分组的内容;
groups() 以元祖的形式返回所有的分组。

3. 案例分析

3.1 代码需求:爬取百度图片

百度图片是典型的瀑布流数据,岑参不齐的图片形式,在尾部不断地往下加载,对于用户操作简单。但是不便于python爬取,最好能想办法转化为传统的页面布局,分页式排版。
在这里插入图片描述
在之前有一种常见的方法是将上述url中的index改为flip,但现在百度网站的反爬手段提升,这个方法现在无法使用了。按照更为传统的方法,按快捷键F12,在network里寻找图片的url,如下图:

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

复制图片的url,并在网页源代码中查找该url,能找到对应的图片:
在这里插入图片描述

上图显示有三种url,分别为thumbURL、middleURL和hoverURL,笔者猜想应该是对应同一张图片中不同的尺寸或者分辨率。这里笔者以middleURL为例,简单地介绍爬取图片的思路以及相关代码的编写。

3.2 代码思路及编写

  1. 拿到目标url,这里指百度图片搜索后的首页;
import requests
import re
source_url = 'https://image.baidu.com/search/index?tn=baiduimage&ipn=r&ct=201326592&cl=2&lm=-1&st=-1&fm' \
             '=result&fr=&sf=1&fmq=1608640730142_R&pv=&ic=&nc=1&z=&hd=&latest=&copyright=&se=1&showtab=0' \
             '&fb=0&width=&height=&face=0&istype=2&ie=utf-8&sid=&word=%E5%A4%A9%E5%91%BD%E5%A5%87%E5%BE' \
             '%A1'
request_headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36 ',
    'Referer': 'https://image.baidu.com/',
	'Cookie':'BAIDUID=3DF52D16EFD175773213166BEE350E5A:FG=1;PSTM=1603507809;BIDUPSID=805830771AB53DC6285322A895A5C6F7;BDUSS=NQQ1VlRUUwYTVNSkh6QTNObXo4ZmJnVHMxbTduS0F3ZEhTWGZJU1NsY1VVYnRmSVFBQUFBJCQAAAAAAAAAAAEAAAAdAQ430MezvbH5vMUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABTEk18UxJNfWl;BDUSS_BFESS=NQQ1VlRUUwYTVNSkh6QTNObXo4ZmJnVHMxbTduS0F3ZEhTWGZJU1NsY1VVYnRmSVFBQUFBJCQAAAAAAAAAAAEAAAAdAQ430MezvbH5vMUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABTEk18UxJNfWl;BDORZ=B490B5EBF6F3CD402E515D22BCDA1598;BAIDUID_BFESS=DAC46E01AE25535771A3DA66E4CA85B7:FG=1;H_PS_PSSID=1449_33242_33306_33261_33236_31253_33285_33343_33313_33312_33311_33310_32446_33218_33309_33308_33307_22158;BDRCVFR[feWj1Vr5u3D]=I67x6TjHwwYf0;delPer=0;PSINO=5;BA_HECTOR=2024al208k2hal8gin1fu3q6a0r;BDRCVFR[dG2JNJb_ajR]=mk3SLVN4HKm;ab_sr=1.0.0_YzQ2ZjEwODI4ZTQ1MjE2MThjNzg4OGM3NWQ0ODhjYjhjNzQxMDE2NTUwZjJkOTQxZDBkMWNjMjY5ODM1N2VhOGMyMDU2MGM2MDZlYWU3MWE3MmU5ZDc2NmU0ZmUxNTZmYjJlYTEzZTY3NjYyOTgwMWQ1ZTQ3MDJmMTVhNWQ4Zjc='
}

cookie 和 user-agent根据自己机器的实际情况来写。

  1. 获取网页源码,向第一步的url发起请求后,获取网页的原始数据;
req_obj = requests.get(source_url, headers=request_headers)
req_cont = req_obj.content.decode('utf-8')
  1. 获取图片的url地址,用findall匹配需要的url
# "middleURL":"https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=476331077,327453246&fm=26&gp=0.jpg"
result_url = re.findall(r'"middleURL":"(.*?")', req_cont) # 匹配到以后再分组,将结果保存到一个列表
print(result_url)

此处先运行现有的代码,查看是否匹配到需要的图片url地址,下图为运行结果:
在这里插入图片描述

笔者试了几个地址,大多都是有效的。

  1. 保存图片
count = 1 # 以图片顺序命名
for pict_url in result_url:
    pict_path = 'pict/' + str(count) + '.jpg'
    with open(pict_path, 'wb') as fobj:
        # 可能出现网络问题
        try:
            pict_cont = requests.get(pict_url).content
            fobj.write(pict_cont)
        except Exception as e:
            print(e, type(e))
    count += 1

在指定的目录下,保存的图片如下:
在这里插入图片描述

4. csv模块的使用

4.1 基本概念

CSV(Common Separated Values),是一种常见的文本格式,用以存储表格数据,包括数字或者字符。很多程序在处理数据时都会碰到csv这种格式的文件。python自带了csv模块,专门用于处理csv文件的读取。

4.2 写入csv文件

  1. 通过创建writer对象,主要用到2个方法。一个是writerow(),写入一行。另一个是writerows()写入多行;
  2. 使用DictWriter()可以使用字典方式把数据写入进去。

writerow()/writerows()的使用:

import csv
# 定义表头
titles = ['name', 'age', 'kongfu']
conts = [['杨过', '36', '玄铁剑法'],
         ['郭靖', '30', '降龙十八掌'],
         ['张无忌', '24', '乾坤大挪移']]
with open('test.csv', 'w', encoding='utf-8', newline='') as fobj:
    # 创建writer对象
    write_obj = csv.writer(fobj)
    # 写入表头
    write_obj.writerow(titles)
    # 写入具体内容
    for cont in conts:
        write_obj.writerow(cont)

运行结果,test.csv的内容如下:

name,age,kongfu
杨过,36,玄铁剑法
郭靖,30,降龙十八掌
张无忌,24,乾坤大挪移

上述代码通过for循环,一行一行写入内容,也可以通过writerows()一次写入多行:

# 写入具体内容
write_obj.writerows(conts)

运行结果和之前的一样。

DictWriter()的使用:

import csv
# 定义表头
titles = ['name', 'age', 'kongfu']
conts = [{'name': '杨过', 'age': '36', 'kongfu': '玄铁剑法'},
         {'name': '郭靖', 'age': '30', 'kongfu': '降龙十八掌'},
         {'name': '张无忌', 'age': '24', 'kongfu': '乾坤大挪移'}]
with open('test1.csv', 'w', encoding='utf-8', newline='') as fobj:
    # 创建writer对象, 第二个参数传递表头,对应数据的key
    writer_obj = csv.DictWriter(fobj, titles)
    # 写入表头
    writer_obj.writeheader()
    # 写入内容
    writer_obj.writerows(conts)

运行结果,test1.csv的内容如下:

name,age,kongfu
杨过,36,玄铁剑法
郭靖,30,降龙十八掌
张无忌,24,乾坤大挪移

注意:使用DictWriter()创建writer对象传递的表头会对写入数据的key进行检查,如不一致会报错。

4.3 读取csv文件

  1. 通过reader()读取到的每一条数据是一个列表。可以通过下标的方式获取具体某一个值;
  2. 使用DictReader()读取到的数据是一个字典,可以通过key值的方式获取数据。

reader()的使用:

import csv
with open('test1.csv', 'r', encoding='utf-8') as fobj:
    reader_obj = csv.reader(fobj)
    for cont in reader_obj:
        print(cont)

运行结果:
在这里插入图片描述

DictReader()的使用:

import csv
with open('test1.csv', 'r', encoding='utf-8') as fobj:
    reader_obj = csv.DictReader(fobj)
    for cont in reader_obj:
        print(cont)
        print('name = ', cont['name'])

运行结果:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值