数据解析
爬虫步骤:
- 指定URL
- 发起请求
- 获取页面数据
- 数据解析
- 进行数据持久化存储
数据解析的三种方式:
- 正则
- xpath
- bs4
项目一、正则解析
#需求:使用正则对糗事百科中的图片进行解析和下载操作 import requests import re import os #指定url url="https://www.qiushibaike.com/pic/" #自定义headers headers={ "User-Agent":"Mozilla/5.0 (Windows NT 10.0;) Gecko/20100101 Firefox/65.0" } #发起请求 response=requests.get(url=url,headers=headers) #获取页面数据 page_text=response.text #单行模式处理,获取图片链接 imgs_url_list=re.findall('<div class="thumb">.*?<img src="(.*?)".*?>.*?</div>',page_text,re.S) #本地没有imgs文件夹则创建 if not os.path.exists("./imgs"): os.mkdir("imgs") for url in imgs_url_list: #将图片url地址进行拼接成完整的url img_url="https:"+url #持久化存储图片,获取图片二进制数据值 response=requests.get(url=img_url,headers=headers).content img_name=img_url.split("/")[-1] imgPath="./imgs/"+img_name with open(imgPath,'wb') as fp: fp.write(response) print("图片%s写入成功" % img_name ) #扩展:爬去指定页码图片
xpath数据解析
- 下载安装:
- 导包
- 创建etree对象对数据进行解析
- 本地:etree.parse("本地某文件").xpath("xpath表达式")
- 网络:etree.HTML("网络请求到的页面数据").xpath("xpath表达式")
xpath回顾及基础使用:
#创建etree对象进行指定数据解析 tree=etree.parse("./test.html") #属性定位:根据指定的属性定位到指定节点标签 tree.xpath("//div[@class='song']") #层级索引定位:[2]标示第二个li tree.xpath("//div[@class='tang']/ul/li[2]/a") #逻辑定位:找到href为空且class为du的a标签 tree.xpath('//a[@href="" and @class="du"]') #模糊匹配:class属性包含ng的div tree.xpath('//div[contains(@class,"ng")]') #以xxx开头 tree.xpath('//div[starts-with(@class,"ta")]') #获取文本:text() tree.xpath("//div[@class='song']/p[1]/text()") #获取某一个标签下所有子标签中存储的数据://text() tree.xpath("//div[@class='song']/p[1]//text()") #取属性值@href tree.xpath("//div[@class='tang']//li[2]/a/@href")
xpath插件:可以直接将xpath表达式作用于浏览器的网页当中
项目二、xpath解析
#需求:使用xpath对段子王中的的段子的内容和标题进行爬去 import requests from lxml import etree #1、指定url url="https://ishuo.cn/joke" #自定义headers headers={ "User-Agent":"Mozilla/5.0 (Windows NT 10.0;) Gecko/20100101 Firefox/65.0" } #2、发起请求 response=requests.get(url=url,headers=headers) #3、获取页面类容 page_text=response.text #4、解析数据 tree=etree.HTML(page_text) li_list=tree.xpath('//div[@id="list"]/ul/li') #5、持久化存储 fp=open("./duanzi.text",'w',encoding="utf-8") #Element类型的对象可以继续调用xpath函数,对该对象表上的局部内容进行指定内容的解析 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") print("数据写入成功.") fp.close()
bs4数据解析
Beautiful解析:python独有的解析方式,使用更便捷高效
环境安装:pip install bs4
核心思想:将html文档转换成Beautiful对象,然后调用该对象中的属性和方法进行html文档指定内容的定位查找
创建Beautiful对象:
如果html文档的来源于本地:Beautiful("open('本地html文件')","lxml")
如果html文档的来源于网络:Beautiful('网络请求的页面数据','lxml')
bs4基础使用:
from bs4 import BeautifulSoup #打开html文件 fp=open("text.html") #创建Beautiful对象 soup=BeautifulSoup(fp,'lxml') #根据标签名进行查找,只能找到第一个符合要求的标签 soup.div #获取属性 soup.a.attrs #根据属性名称获取属性值 soup.a.attrs['href'] #获取内容 soup.a.string#标签下的内容,类似xpath的/text() soup.a.text#某个标签下的所有文本内容,类似xpath的//text() soup.a.get_text()#类似text #查找第一个符合要求的标签 soup.find("a") #查找指定class属性的标签,class后面有个下划线,其他没有 soup.find("a",class_="song") #查找所有符合指定条件的标签 soup.findAll("a") #limit限制查找的个数 soup.findAll("a",limit=2) #查找所有的a标签和b标签 soup.findAll(['a','b']) #根据选择器选择指定类容,select永远返回的是列表 #选择器类型有:标签选择器、类选择器、id选择器、层级选择器 #层级选择器,单级用>分割 soup.select('div>img') #层级选择器,夸多级用空格分割 soup.select("div li")
项目三、bs4项目
#需求:爬去古诗文网中三国小说里的标题和内容 from bs4 import BeautifulSoup import requests #指定url url="http://www.shicimingju.com/book/sanguoyanyi.html" url_header="http://www.shicimingju.com" #指定headers headers={ "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36" } #发起请求 response=requests.get(url=url,headers=headers) #获取页面数据 page_text=response.text ##创建BeautifulSoup对象 soup=BeautifulSoup(page_text,'lxml') #a_list存储的是a标签对象 a_list=soup.select(".book-mulu > ul > li > a") #Tag类型的的对象可以继续调用相应的解析属性和方法进行局部数据的解析 #定义一个函数,根据指定url获取页面的内容 def get_content(url): #发起请求 response=requests.get(url=url,headers=headers) #获取页面类容 content_page=response.text #创建BeautifSoup对象 soup=BeautifulSoup(content_page,'lxml') #查找chapter_content的div对象 content_div=soup.find('div',class_='chapter_content') #获取content_div对象的类容 content=content_div.text return content #持久化存储 fp=open("./sanguo.text",'w',encoding='utf-8') for a in a_list: #获取了章节的标题 title=a.string #获取章节所对应的url content_url=url_header+a['href'] content=get_content(content_url) fp.write(title+"\n\n"+content+"\n\n\n\n") fp.close()