一 正则表达式
# 提取出python key = "javapythonc++php" re.findall('python', key) # 提取出hello world key = "<html><h1>hello word</h1></html>" re.findall('<h1>(hello word)</h1>', key) # 提取170 string = '我喜欢身高为170的XX' re.findall('\d+', string) # 提取出http://和https:// key = 'http://www.baidu.com and https://boob.com' re.findall('https?', key) 或 re.findall('https{0,1}', key) # 提取出hit. key = 'bobo@hit.edu.com' re.findall('h.*?\.', key) # 贪婪模式:根据正则表达式尽可能多的提取出数据 # 匹配asa和saas key = 'saas and sas and saaas' re.findall('sa{1,2}s', key) # 匹配出i开头的行 string = ''' fall in love with you i love you very much i love she i love her ''' re.findall('^i.*', string, re.M) # re.S(单行匹配) re.M(多行匹配) # 匹配全部行 string = ''' <div>静夜思 窗前明月光 疑似地上霜 举头望明月 低头思故乡 ''' re.findall('<div>.*</div>', string, re.S)
示例:使用正则对糗事百科中的图片数据进行解析和下载
import requests import re import os headers = { #定制请求头中的User-Agent参数,当然也可以定制请求头中其他的参数 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36', } url = 'https://www.qiushibaike.com/imgrank/' requests.get(url=url, headers=headers) page_text = response.text # 数据解析 ''' 图片html <div class="thumb"> <a href="/article/121733601" target="_blank"> <img src="//pic.qiushibaike.com/system/pictures/12173/121733601/medium/HDWWXFFANYVPKZGN.jpg" alt="糗事#121733601" class="illustration" width="100%" height="auto"> </a> </div> ''' # 该列表中存储的就是当前页面源码中所有图片链接 img_list = re.findall('<div class="thumb">.*?<img src="(.*?)" .*?>.*?</div>', page_text, re.S) # 创建一个存储图片数据的文件夹 if not os.path.exists('./imgs'): os.mkdir('imgs') for url in img_list: # 将图片的url进行拼接,拼接成一个完整的url img_url = 'https:' + url # 持久化存储:存储的是图片的数据并不是图片的url img_data = requests.get(url=img_url, headers=headers).content img_name = url.split('/')[-1] img_path = 'imgs/' + img_name with open(img_path, 'wb') as fp: fp.write(img_data) print(img_name+'写入成功')
二 xpath在爬虫的使用流程
下载:pip instal lxml
导包: from lxml import etree
创建etree对象进行制定数据的解析 - 本地:etree.parse('本地文件路径') etree.xpath('xpath表达式') - 网络:etree.HTML('网络请求到的页面数据') etree.xpath('xpath表达式')
测试页面数据:
<html lang="en"> <head> <meta charset="UTF-8" /> <title>测试bs4</title> </head> <body> <div> <p>百里守约</p> </div> <div class="song"> <p>李清照</p> <p>王安石</p> <p>苏轼</p> <p>柳宗元</p> <a href="http://www.song.com/" title="赵匡胤" target="_self"> <span>this is span</span> 宋朝是最强大的王朝,不是军队的强大,而是经济很强大,国民都很有钱</a> <a href="" class="du">总为浮云能蔽日,长安不见使人愁</a> <img src="http://www.baidu.com/meinv.jpg" alt="" /> </div> <div class="tang"> <ul> <li><a href="http://www.baidu.com" title="qing">清明时节雨纷纷,路上行人欲断魂,借问酒家何处有,牧童遥指杏花村</a></li> <li><a href="http://www.163.com" title="qin">秦时明月汉时关,万里长征人未还,但使龙城飞将在,不教胡马度阴山</a></li> <li><a href="http://www.126.com" alt="qi">岐王宅里寻常见,崔九堂前几度闻,正是江南好风景,落花时节又逢君</a></li> <li><a href="http://www.sina.com" class="du">杜甫</a></li> <li><a href="http://www.dudu.com" class="du">杜牧</a></li> <li><b>杜小月</b></li> <li><i>度蜜月</i></li> <li><a href="http://www.haha.com" id="feng">凤凰台上凤凰游,凤去台空江自流,吴宫花草埋幽径,晋代衣冠成古丘</a></li> </ul> </div> </body> </html>
常用xpath表达式
属性定位:
#找到class属性值为song的div标签
//div[@class="song"]
层级&索引定位:
#找到class属性值为tang的div的直系子标签ul下的第二个子标签li下的直系子标签a
//div[@class="tang"]/ul/li[2]/a
逻辑运算:
#找到href属性值为空且class属性值为du的a标签
//a[@href="" and @class="du"]
模糊匹配:
//div[contains(@class, "ng")]
//div[starts-with(@class, "ta")]
取文本:
# /表示获取某个标签下的文本内容
# //表示获取某个标签下的文本内容和所有子标签下的文本内容
//div[@class="song"]/p[1]/text()
//div[@class="tang"]//text()
取属性:
//div[@class="tang"]//li[2]/a/@href
实例演示:
# 创建etree对象进行制定数据解析
tree = etree.parse('./text.html')
# 属性定位:根据指定的属性定位到指定的节点标签
tree.xpath('//div[@class="song"]')
# 层级索引定位
tree.xpath('//div[@class="tang"]/ul/li[2]/a')
# 逻辑定位
tree.xpath('//a[@href="" and @class="du"]')
# 模糊匹配
tree.xpath('//div[contains(@class, "ng")]')
tree.xpath('//div[starts-with(@class, "ta")]')
# 取文本
tree.xpath('//div[@class="song"]/p[1]/text()')
tree.xpath('//div[@class="tang"]//text()')
# 取属性:
tree.xpath('//div[@class="tang"]//li[2]/a/@href')
xpat插件
浏览器中的一个插件可以直接将xpath表达式作用于浏览器当中
安装:
- 打开浏览器更多工具的扩展程序>>开启右上角开发者模式>>xpath程序拖拽的页面
- 开启和关闭xpath插件:ctrl+shif+x
xpath实战项目:需求使用xpath对段子网中的段子内容和标题进行解析
import requests from lxml import etree url = 'https://ishuo.cn/duanzi' headers = { #定制请求头中的User-Agent参数,当然也可以定制请求头中其他的参数 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36', } response = requests.get(url=url, headers=headers) page_text = response.text tree = etree.HTML(page_text) # 每个li标签列表 注意:Element类型的对象可以继续调用xpath函数对该对象表示的局部内容进行指定内容的解析 li_list = tree.xpath('//div[@id="list"]/ul/li') fp = open('./duanzi.txt', 'w', encoding='utf-8') for li in li_list: content = li.xpath("./div[@class='content']/text()")[0] title = li.xpath("./div[@class='info']/a/text()")[0] fp.write(title+":"+content+"\n\n")
三 Beadutiful解析
Beadutiful是在python中独有的解析方式
环境安装:
windows
(1)打开文件资源管理器(文件夹地址栏中)
(2)地址栏上面输入 %appdata%
(3)在这里面新建一个文件夹 pip
(4)在pip文件夹里面新建一个文件叫做 pip.ini ,内容写如下即可
[global]
timeout = 6000
index-url = https://mirrors.aliyun.com/pypi/simple/
trusted-host = mirrors.aliyun.com
linux
(1)cd ~
(2)mkdir ~/.pip
(3)vi ~/.pip/pip.conf
(4)编辑内容,和windows一模一样
需要安装:pip install bs4
bs4在使用时候需要一个第三方库,把这个库也安装一下
pip install lxml
核心思想:将html文档转换成Beautiful对象, 然后调用该对象中的属性和方法进行html文档指定内容的定位查找。
导包: from bs4 import BeautifulSoup
创建Beautiful对象:
如果html文档的来源是本地: Beautiful('open('本地的html文件')', 'lxml') 如果 html是来源于网络 Beautiful('网络请求的页面数据', 'lxml')
基础方法:
(1)根据标签名查找 - soup.a 只能找到第一个符合要求的标签 (2)获取属性 - soup.a.attrs 获取a所有的属性和属性值,返回一个字典 - soup.a.attrs['href'] 获取href属性 - soup.a['href'] 也可简写为这种形式 (3)获取内容 - soup.a.string - soup.a.text - soup.a.get_text() 【注意】如果标签还有标签,那么string获取到的结果为None,而其它两个,可以获取文本内容 (4)find:找到第一个符合要求的标签 - soup.find('a') 找到第一个符合要求的 - soup.find('a', title="xxx") - soup.find('a', alt="xxx") - soup.find('a', class_="xxx") - soup.find('a', id="xxx") (5)find_all:找到所有符合要求的标签 - soup.find_all('a') - soup.find_all(['a','b']) 找到所有的a和b标签 - soup.find_all('a', limit=2) 限制前两个 (6)根据选择器选择指定的内容 select:soup.select('#feng') - 常见的选择器:标签选择器(a)、类选择器(.)、id选择器(#)、层级选择器 - 层级选择器: div .dudu #lala .meme .xixi 下面好多级 div > p > a > .lala 只能是下面一级 【注意】select选择器返回永远是列表,需要通过下标提取指定的对象
实战演练:
# 需求:使用bs4实现将诗词名句网站中三国演义小说的每一章的内容爬去到本地磁盘进行存储 import requests from bs4 import BeautifulSoup def parse_content(url): #获取标题正文页数据 page_text = requests.get(url,headers=headers).text soup = BeautifulSoup(page_text,'lxml') #解析获得标签 ele = soup.find('div',class_='chapter_content') content = ele.text #获取标签中的数据值 return content headers = { #定制请求头中的User-Agent参数,当然也可以定制请求头中其他的参数 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36', } url = 'http://www.shicimingju.com/book/sanguoyanyi.html' page_text = requests.get(url=url, headers=headers).text soup = BeautifulSoup(page_text, 'lxml') # a_list列表中存储的是一系列a标签对象 a_list = soup.select('.book-mulu > ul > li > a') fp = open('./sanguo.txt','w', encoding='utf-8') for a in a_list: title = a.string # 获取章节的内容 content_url = 'http://www.shicimingju.com' +a['href'] content = parse_content(content_url) fp.write(title+":"+content+'\n\n\n\n\n')