Python爬虫演绎正则提取数据

python爬虫演绎正则提取数据

1.什么是正则表达式?
2.爬取《男人装》网页内容
  • 这次我们来抓取《男人装》杂志的网页中一些我们需要的内容

    • 浏览器搜索男人装,进入官网,随便进入一个页面:
    • 获取页面的url
      在这里插入图片描述
  • 第一步请求服务器响应的数据

这次我们要用到urllib库里面的request模块

from urllib import request

url = 'http://enrz.com/fhm/2016/12/17/74914.html'
""" 请求服务器,获得服务器响应的数据"""
req = request.Request(url)
html = request.urlopen(req)
content = html.read().decode('utf-8')

print(content)

此时我们获取到了这些数据:
在这里插入图片描述

  • 第二步解析数据提取数据内容
    我们来实现这样一个功能:爬取网页数据,存储到文件夹里面,网页每个标题对应一个文件夹。
    • 这里我们要用到正则表达式的通配符
    • 1.什么是正则表达式?

正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。——《百度百科》

给定一个正则表达式和另一个字符串,我们可以达到如下的目的:
①. 给定的字符串是否符合正则表达式的过滤逻辑(称作“匹配”):
②. 可以通过正则表达式,从字符串中获取我们想要的特定部分。

  • 简单来说,打个比方:
    假设这里有一篇xxx的自我介绍,我们想从中了解xxx的兴趣爱好,那么我们可以在文章中找结构为 “我喜欢{xxx}” 或者 “我爱好{xxx}” 的句子,然后提取出{ }里面的内容,这就是对字符串的过滤。

正则表达式使用方法:

  • 正则表达式由一些普通字符和一些元字符(metacharacters)组成。普通字符包括大小写的字母和数字,而元字符则具有特殊的含义。

举几个例子:

  • 最简单的元字符是点,能够匹配任意的单个字符 下面语句:①he is in a rat ②I like root beer ③the food is Rotten
  • 正则表达式 r.t 匹配① ,它是区分大小写的,如果要同时匹配大写和小写可以这么写: [Rr].t

这里我们用的是通配符

通配符是一类键盘字符。
当查找文件夹时;当不知道真正字符或者不想键入完整名字时,常常使用通配符代替一个或多个真正字符。
星号( * )
可以使用星号代替零个、单个或多个字符。如果正在查找以AEW开头的一个文件,但不记得文件名其余部分,可以输入AEW*,查找以AEW开头的所有文件类型的文件,如AEWT.txt、AEWU.EXE、AEWI.dll等。要缩小范围可以输入AEW*.txt,查找以AEW开头的所有文件类型并.txt为扩展名的文件如AEWIP.txt、AEWDF.txt。
问号( ?)
可以使用问号代替一个字符。如果输入love?,查找以love开头的一个字符结尾文件类型的文件,如lovey、lovei等。要缩小范围可以输入love?.doc,查找以love开头的一个字符结尾文件类型并.doc为扩展名的文件如lovey.doc、loveh.doc。
通配符包括星号“ * ”和问号 “ ?”
星号表示匹配的数量不受限制,而后者的匹配字符数则受到限制。 这个技巧主要用于英文搜索中,如输入““computer*”,就可以找到“computer、computers、computerised、computerized”等单词,而输入“comp?ter”,则只能找到“computer、compater、competer”等单词。
——《百度百科》

这里我们用组合字符(.*?)

  • 当(.*?)带有小括号时表示是我们需要获取的内容, . * ?不带小括号时表示不需要的内容。

使用正则表达式,我们需要导入re模块

import re

下面我们来提取数据
第一步构造用于过滤的字符串
1.标题
在网页查看源代码,找到标题的格式:
在这里插入图片描述

'<div id="content"> 
		<h2>如何系围巾不显得娘炮?</h2>'
  • 用(.*?) 取代我们需要的内容, 特别提出一点的是不要忘了源代码中< h2>前还有一个换行符
title_pattern = '<div id="content">.*?<h2>(.*?)</h2>'

2.网页中的图片:

<p><img class=" size-full wp-image-74915 aligncenter" src="http://images.enrz.com/wp-content/uploads/2016/12/FAKE-KNOT-1.jpg" alt="fake-knot-1" width="218" height="354" /></p>

我们需要src里面的内容,忽略掉其他的标签属性(这里保留class特征取得网页中的大图)

url_pattern = '<p><img class=.*?src="(.*?)".*?/></p>'

第二步将两个字符串转换为正则表达式对象

"""加载成为正则表达式对象"""
title = re.compile(title_pattern,re.S)
"""在获得的字符串中匹配我们所需要的内容"""
title_result = re.search(title,content)
print(title_result.group(1))

*(re.S使得表达式能够匹配包括’\n’的所有字符)
下面是我们的运行结果:
在这里插入图片描述
第三步动态地建立文件夹

  • 导入os模块
import os
  • 拼接当前文件夹地绝对路径新建文件名,以之新建文件
dir_path = os.path.join ( os.getcwd(), namestr)
if not os.path.exists (dir_path):"""如果该文件夹不存在则新建"""
	os.makedirs (dir_path)

运行结果:该目录下新生成文件夹
在这里插入图片描述
第四步爬取内容(图片)

  • 当前页面有多张图片,通过死循环抓取
pic_url = re.compile(url_pattern,re.S)
while True:
	pic_items = re.findall( pic_url, content )
	print(pic_items)
	break

运行结果:爬取到了该页面地图片链接
在这里插入图片描述
再加上存储的操作:

  • 图片的名称的获取需要再次用到通配符:
    ^ 匹配输入字行首。
    $ 匹配输入行尾。
http://images.enrz.com/wp-content/uploads/2016/12/FAKE-KNOT-1.jpg
  • 我们需要的内容:
FAKE-KNOT-1.jpg
  • 从匹配到的图片链接中逐个匹配图片名称
pic_url = re.compile(url_pattern,re.S)
name_pattern = '^.*/(.*?)$'
last_pic_name= re.compile(name_pattern,re.S)

while True:
	pic_items = re.findall( pic_url, content )"""查找content里面所有满足条件的图片url"""
	for item in pic_items:
		name_result = re.search(last_pic_name, item)"""获取每一个url的图片名称"""	
		name = name_result.group(1)
		print(name)
	break

运行结果:获得了所有图片的名称
在这里插入图片描述

  • 将图片存入文件夹
	pic_path = os.path.join(dir_path,name)"""获得每一张图片的路径"""
	req = request.Request(item)"""向服务器请求获取图片数据"""
 	html = request.urlopen(req)
 	data = html.read()
    with open(pic_path, 'wb') as file:"""将图片存入文件夹"""
    file.write(data)

运行结果: 爬取到了改也没所有的图片
在这里插入图片描述
源代码:


from urllib import request
import re
import os
from urllib.parse import quote
import string
url = 'http://enrz.com/fhm/2016/12/17/74914.html'
""" 请求服务器,获得服务器响应的数据"""
req = request.Request(url)
html = request.urlopen(req)
content = html.read().decode('utf-8')


title_pattern = '<div id="content">.*?<h2>(.*?)</h2>'
url_pattern = '<p><img.*?src="(.*?)".*?/></p>'
name_pattern = '^.*/(.*?)$'
"""加载成为正则表达式对象"""
title = re.compile(title_pattern,re.S)
"""在得到的字符串中匹配我们所需要的内容"""
title_result = re.search(title, content)
namestr = title_result.group(1)

dir_path = os.path.join(os.getcwd(), namestr)
if not os.path.exists(dir_path):
    os.makedirs(dir_path)

pic_url = re.compile(url_pattern, re.S)
last_pic_name = re.compile(name_pattern, re.S)

while True:
    pic_items = re.findall(pic_url, content)
    for item in pic_items:
        name_result = re.search(last_pic_name, item)
        name = name_result.group(1)
        pic_path = os.path.join(dir_path,name)
        url = quote(item, safe=string.printable)
        req = request.Request(url)
        html = request.urlopen(req)
        data = html.read()
        with open(pic_path, 'wb') as file:
            file.write(data)
    break
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hnu哈哈

请接受直女的么么哒????

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值