数据解析-xpath
引入
xpath解析是我们在爬虫中最常用也是最通用的一种数据解析方式,由于其高效且简介的解析方式受到了广大程序员的喜爱。在后期学习scrapy框架期间,也会再次使用到xpath解析。
环境安装
- pip install lxml
解析原理
- 使用通用爬虫爬取网页数据
- 实例化etree对象,且将页面数据加载到该对象中
- 使用xpath函数结合xpath表达式进行标签定位和指定数据提取
测试页面数据
-
百里守约
-
-
李清照
-
王安石
-
苏轼
-
柳宗元
-
-
![]()
-
-
- 清明时节雨纷纷,路上行人欲断魂,借问酒家何处有,牧童遥指杏花村
- 秦时明月汉时关,万里长征人未还,但使龙城飞将在,不教胡马度阴山
- 岐王宅里寻常见,崔九堂前几度闻,正是江南好风景,落花时节又逢君
- 杜甫
- 杜牧
- 杜小月
- 度蜜月
- 凤凰台上凤凰游,凤去台空江自流,吴宫花草埋幽径,晋代衣冠成古丘
-
-
常用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(文件名)tree.xpath("xpath表达式")- 网络数据:tree = etree.HTML(网页内容字符串)tree.xpath("xpath表达式")
实战案例
- 项目需求:解析58二手房的相关数据
#解析出一级页面的标题和二级页面的价格和描述import requestsfrom lxml import etreeheaders = {'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'}url = 'https://bj.58.com/changping/ershoufang/?utm_source=sem-baidu-pc&spm=105916147073.26420796294&PGTID=0d30000c-0000-17fc-4658-9bdfb947934d&ClickID=3'page_text = requests.get(url=url,headers=headers).texttree = etree.HTML(page_text)li_list = tree.xpath('//ul[@class="house-list-wrap"]/li')data = []for li in li_list:#解析标题title = li.xpath('.//div[@class="list-info"]/h2/a/text()')[0]detail_page_url = li.xpath('.//div[@class="list-info"]/h2/a/@href')[0]if detail_page_url.split('//')[0] != 'https:':detail_page_url = 'https:'+detail_page_urldetail_text = requests.get(url=detail_page_url,headers=headers).texttree = etree.HTML(detail_text)#解析二级页面的描述和价格desc = ''.join(tree.xpath('//div[@id="generalDesc"]//div[@class="general-item-wrap"]//text()')).strip(' \n \t')price = ''.join(tree.xpath('//div[@id="generalExpense"]//div[@class="general-item-wrap"]//text()')).strip(' \n \t')dic = {'title':title,'desc':desc,'price':price}data.append(dic)#进行持久化存储print(data)
- 项目需求:解析图片数据:http://pic.netbian.com/4kmeinv/
import requestsfrom lxml import etreeurl = 'http://pic.netbian.com/4kmeinv/'headers = {'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'}response = requests.get(url=url,headers=headers)#获取页面原始编码格式print(response.encoding)page_text = response.texttree = etree.HTML(page_text)li_list = tree.xpath('//div[@class="slist"]/ul/li')for li in li_list:img_url = 'http://pic.netbian.com'+li.xpath('./a/img/@src')[0]img_name = li.xpath('./a/img/@alt')[0]img_name = img_name.encode('iso-8859-1').decode('gbk')print(img_url,img_name)
- 项目需求:下载煎蛋网中的图片数据:http://jandan.net/ooxx
import requestsfrom lxml import etreefrom fake_useragent import UserAgentimport base64import urllib.requesturl = 'http://jandan.net/ooxx'ua = UserAgent(verify_ssl=False,use_cache_server=False).randomheaders = {'User-Agent':ua}page_text = requests.get(url=url,headers=headers).text#查看页面源码:发现所有图片的src值都是一样的。#简单观察会发现每张图片加载都是通过jandan_load_img(this)这个js函数实现的。#在该函数后面还有一个class值为img-hash的标签,里面存储的是一组hash值,该值就是加密后的img地址#加密就是通过js函数实现的,所以分析js函数,获知加密方式,然后进行解密。#通过抓包工具抓取起始url的数据包,在数据包中全局搜索js函数名(jandan_load_img),然后分析该函数实现加密的方式。#在该js函数中发现有一个方法调用,该方法就是加密方式,对该方法进行搜索#搜索到的方法中会发现base64和md5等字样,md5是不可逆的所以优先考虑使用base64解密#print(page_text)tree = etree.HTML(page_text)#在抓包工具的数据包响应对象对应的页面中进行xpath的编写,而不是在浏览器页面中。#获取了加密的图片url数据imgCode_list = tree.xpath('//span[@class="img-hash"]/text()')imgUrl_list = []for url in imgCode_list:#base64.b64decode(url)为byte类型,需要转成strimg_url = 'http:'+base64.b64decode(url).decode()imgUrl_list.append(img_url)for url in imgUrl_list:filePath = url.split('/')[-1]urllib.request.urlretrieve(url=url,filename=filePath)print(filePath+'下载成功')
- - 项目需求:解析出所有城市名称https://www.aqistudy.cn/historydata/
import requestsfrom lxml import etreeurl = 'https://www.aqistudy.cn/historydata/'headers = {'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'}response = requests.get(url=url,headers=headers)#获取页面原始编码格式print(response.encoding)page_text = response.texttree = etree.HTML(page_text)li_list = tree.xpath('//div[@class="bottom"]/ul/li | //div[@class="bottom"]/ul//li')for li in li_list:city_name = li.xpath('./a/text()')[0]city_url = 'https://www.aqistudy.cn/historydata/'+li.xpath('./a/@href')[0]print(city_name,city_url)


浙公网安备 33010602011771号