数据解析方式之一:xpath
使用流程:
- 下载:pip install lxml
- 导包:from lxml import etree
- 创建etree对象进行指定数据的解析
本地:etree=etree.parse('本地文件路径')
etree.xpath('xpath表达式')
网络:etree=etree.HTML('网络请求到的页面数据')
etree.xpath('xpath表达式')
xpath插件:火狐浏览器右上角——>附加组件——>搜索Try XPath——>添加即可!
案例:
test.html
测试 百里守约
xpath语法练习:
from lxml import etree#xpath函数返回的总是一个列表#创建etree对象进行指定数据解析tree = etree.parse('./test.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()') #/text()获取当前标签中直系存储的文本数据#tree.xpath('//div[@class="tang"]//text()') #//text()获取某一个标签下所有子标签中存储的文本数据#取属性# tree.xpath('//div[@class="tang"]//li[2]/a/@href')#/表示绝对路径,从根节点选取#.表示选取当前节点#..表示选取当前节点的父节点#@表示 选取属性
需求:利用xpath爬取经典段子网内容
1 import requests 2 from lxml import etree 3 #指定url 4 url='https://ishuo.cn/yulu' 5 #自定义头信息 6 headers = { 7 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.221 Safari/537.36 SE 2.X MetaSr 1.0' 8 } 9 #发起get请求,返回响应对象10 response=requests.get(url=url,headers=headers)11 #获取页面数据12 page_data=response.text13 #数据解析14 tree=etree.HTML(page_data)15 #注:Element类型的对象可以继续调用xpath函数,对该对象表示的局部内容进行指定内容的解析16 li_list=tree.xpath('//div[@id="content"]/div[2]/ul/li')17 #不要把文件放在循环体内,浪费资源18 f=open('./duan.txt','w',encoding='utf-8')19 for li in li_list:20 content=li.xpath('./div[@class="content"]//text()')[0]21 f.write(content+'\n\n')
数据解析之二:正则表达式
常用正则练习:
#提取出pythonkey="javapythonc++php"re.findall('python',key)[0]#提取出hello worldkey="hello world
"re.findall('
hello world
',key)[0]#提取170string = '我喜欢身高为170的女孩're.findall('\d+',string)#提取出http://和https://key='http://www.baidu.com and https://boob.com're.findall('https{0,1}',key)#提取出hit. key='bobo@hit.edu.com're.findall('h.*?\.',key) #贪婪模式:根据正则表达式尽可能多的提取出数据#匹配sas和saaskey='saas and sas and saaas're.findall('sa{1,2}s',key)#匹配出i开头的行 re.S(基于单行) re.M(基于多行)string = '''fall in love with youi love you very muchi love shei love her'''re.findall('^i.*',string,re.M)#匹配全部行string = """
静夜思窗前明月光疑是地上霜举头望明月低头思故乡"""re.findall('.*',string,re.S)
练习:需求是使用正则对糗事百科的图片数据下载
1 import requests 2 import re 3 import os 4 #指定url 5 url = 'https://www.qiushibaike.com/pic/' 6 headers={ 7 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36', 8 } 9 #发起请求10 response = requests.get(url=url,headers=headers)11 #获取页面数据12 page_text = response.text13 #数据解析(该列表中存储的就是当前页面源码中所有的图片链接)14 img_list = re.findall('.*? .*?',page_text,re.S)15 #创建一个存储图片数据的文件夹16 if not os.path.exists('./imgs'):17 os.mkdir('imgs')18 for url in img_list:19 #将图片的url进行拼接,拼接成一个完成的url20 img_url = 'https:' + url21 #持久化存储:存储的是图片的数据,并不是url。22 #获取图片二进制的数据值23 img_data = requests.get(url=img_url,headers=headers).content24 imgName = url.split('/')[-1]25 imgPath = 'imgs/'+imgName26 with open(imgPath,'wb') as fp:27 fp.write(img_data)28 print(imgName+'写入成功')
数据解析之三:BS4
python独有。简单便捷和高效。
环境安装:
需要将pip源设置为国内源,阿里源、豆瓣源、网易源等
Windows:
(1)打开文件资源管理器(文件夹地址栏中)
(2)地址栏上面输入 %appdata%
(3)在这里面新建一个文件夹 pip
(4)在pip文件夹里面新建一个文件叫做 pip.ini ,内容写如下即可
[global] timeout = 6000 index-url = trusted-host = mirrors.aliyun.com
需要安装: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 /text()
- soup.a.text //text()
- soup.a.get_text() //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//img
div > p > a > .lala 只能是下面一级 div/img
【注意】select选择器返回永远是列表,需要通过下标提取指定的对象
BS4语法练习:
from bs4 import BeautifulSoupfp = open('text.html')soup = BeautifulSoup(fp,'lxml')#根据标签名进行查找#soup.div#获取标签属性值#soup.a['href']#获取内容#soup.p.string#获取符合要求的标签#soup.find('div',class_="tang")#soup.findAll('a',limit=2)#select函数的层级选择器:#soup.select('div li')
练习:需求是利用BS4爬取古诗文网中三国小说的标题和内容
1 import requests 2 from bs4 import BeautifulSoup 3 url = 'http://www.shicimingju.com/book/sanguoyanyi.html' 4 headers={ 5 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36', 6 } 7 #根据url获取页面内容中指定的标题所对应的文章内容 8 def get_content(url): 9 content_page = requests.get(url=url,headers=headers).text10 soup = BeautifulSoup(content_page,'lxml')11 div = soup.find('div',class_='chapter_content')12 return div.text13 page_text = requests.get(url=url,headers=headers).text14 #数据解析15 soup = BeautifulSoup(page_text,'lxml')16 #a_list列表中存储的是一系列的a标签对象17 a_list = soup.select('.book-mulu > ul > li > a')18 #type(a_list[0])19 #注意:Tag类型的对象可以继续调用响应的解析属性和方法进行局部数据的解析20 fp = open('./sanguo.txt','w',encoding='utf-8')21 for a in a_list:22 #获取了章节的标题23 title = a.string24 content_url = 'http://www.shicimingju.com'+a['href']25 print(content_url)26 #获取章节的内容27 content = get_content(content_url)28 fp.write(title+':'+content+"\n\n\n")29 print('写入一个章节内容')