网络爬虫与正则表达式
对应教学日历:讲次 14-15
一、网络爬虫概述
网络爬虫:按照一定规则,自动抓取万维网信息的程序或脚本。
爬虫步骤
- 获取网页源码
- 根据目标链接特点写出正则表达式
- 用正则对象匹配获取目标链接
- 用循环结构遍历目标链接并下载信息
二、requests 库
import requests获取网页内容
url = "http://www.people.com.cn/"
r = requests.get(url)
r.encoding = r.apparent_encoding # 修正编码
data = r.text # 字符串形式Response 对象属性
| 属性 | 说明 |
|---|---|
r.text | 网页响应内容的字符串形式 |
r.content | 网页响应内容的二进制形式 |
r.encoding | 猜测的编码方式 |
r.apparent_encoding | 从内容分析出的编码方式 |
爬取图片
import requests
url = "http://example.com/image.jpg"
r = requests.get(url)
data = r.content
with open("result.jpg", "wb") as fobj:
fobj.write(data)三、正则表达式(re模块)
import re常用模式
| 模式 | 描述 |
|---|---|
\d | 匹配一个数字字符 |
\w | 匹配字母、数字、下划线 |
\s | 匹配一个空白字符 |
. | 匹配任意字符(换行符除外) |
{n} | 匹配n个字符 |
{n,m} | 匹配n到m个字符 |
* | 匹配前面的字符0次或多次 |
+ | 匹配前面的字符1次或多次 |
? | 匹配前面的字符0次或1次 |
[] | 字符范围,只能取一个 |
( ) | 构建一个组 |
基本示例
import re
content = 'Hello 123 world 456'
re.findall(r'\d\d\d', content) # ['123', '456']
re.findall(r'\d{3}', content) # ['123', '456']
re.findall(r'\w\w\w', content) # ['Hel', '123', 'wor', '456']
re.findall(r'.o', content) # ['lo', 'wo']
re.findall(r'\d{1,3}', content) # ['12', '345', '6']
re.findall(r'\d*\d', content) # ['12', '456', '3']
re.findall(r'\d+\d', content) # ['12', '456']
re.findall(r'\d?\d', content) # ['12', '45', '6', '3']字符范围
content = 'Mike_123 sum Hi_1234 456'
re.findall(r'[0-9a-zA-Z\_]{6,8}', content)
# ['Mike_123', 'Hi_1234']组匹配
content = 'Hello 12 world 4567'
re.findall(r'\d(.*)\d', content) # ['2 world 456']四、贪婪匹配 vs 非贪婪匹配
import re
res = '文本A百度新闻文本B,文本A新浪财经文本B,文本A搜狐新闻文本B'
# 贪婪匹配(默认):尽可能多地匹配
re.findall(r'文本A(.*)文本B', res)
# ['百度新闻文本B,文本A新浪财经文本B,文本A搜狐新闻']
# 非贪婪匹配:尽可能少地匹配
re.findall(r'文本A(.*?)文本B', res)
# ['百度新闻', '新浪财经', '搜狐新闻']非贪婪匹配在量词后加 ?:.*?, +?, {n,m}?
五、re库内置函数
import re
string = "I love ECUST. ECUST loves me."
re.match("I", string) # 从起始位置匹配
re.search("ECUST", string) # 搜索第一个匹配
re.findall("ECUST", string) # 返回所有匹配列表
re.findall("it", string, re.I) # re.I 忽略大小写compile + re.I 实现不区分大小写
test = re.compile("it", re.I)
result = re.findall(test, string)
# ['It']作业示例
爬取人民网链接和标题
import requests
import re
url = "http://www.people.com.cn"
r = requests.get(url)
r.encoding = r.apparent_encoding
data = r.text
reg = r'<li><a href="(.*?)" target="_blank">(.*?)</a></li>'
urls = re.findall(reg, data)
fobj = open("peoplecn.csv", 'w', encoding="GBK")
for titu in urls:
fobj.write(titu[0] + "," + titu[1] + '\n')
fobj.close()要点:
(.*?)非贪婪匹配提取内容findall返回元组列表[(url, title), ...]
爬取新闻图片
import requests
import re
url = 'http://www.people.com.cn'
r = requests.get(url)
r.encoding = r.apparent_encoding
paper = r.text
regrule = r' target=_blank><img src="(.*?)"'
urls = re.findall(regrule, paper)
x = 0
for imgu in urls:
r = requests.get(url + imgu)
filename = '%d.jpg' % x
with open(filename, 'wb') as f:
f.write(r.content)
x += 1HTML标签提取
import re
s = '''<img src="C:\\XH.jpg" width="300"/>
<img src="C:\\FX.jpg" width="300"/>'''
result = re.findall(r'<img src="(.*?)" ', s)
print(result) # ['C:\\XH.jpg', 'C:\\FX.jpg']
# 提取多个属性
result = re.findall(r'<img src="(.*?)" width="(.*?)"', s)
print(result) # [('C:\\XH.jpg', '300'), ('C:\\FX.jpg', '300')]不区分大小写匹配
import re
result = re.compile("it", re.I)
string = "I love it. It loves me."
re.findall(result, string) # ['it', 'It']作业重点
requests.get(url)获取网页,r.text返回字符串r.encoding = r.apparent_encoding修正编码方式\d数字、\w字母数字下划线、.任意字符{n}精确匹配n次、{n,m}匹配n到m次*0次或多次、+1次或多次、?0次或1次(.*?)非贪婪匹配提取内容,(.*)贪婪匹配re.findall(pattern, string)返回所有匹配的列表re.I忽略大小写修饰符- 爬虫核心:获取源码 → 正则匹配 → 提取目标