数据解析

数据解析

概念:

将一整张页面中的局部数据进行提取/解析

作用:

用来实现聚焦爬虫

实现方式:

  正则
  bs4
  xpath
  pyquery

数据解析的通用原理

  标签的定位
  数据的提取

页面中的相关的字符串的数据的存储位置

  标签中间
  标签的属性中

基于聚焦爬虫的编码流程

  指定url
  发起请求
  获取响应数据
  数据解析
  持久化存储

 

爬取图片数据

  • 基于requests|
  • 基于urllib
  • 区别:urllib中的urlretrieve不可以进行UA伪装(headers)

 

import requests
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36'
}

requests

#基于requests的图片爬取
url ='http://pic.netbian.com/uploads/allimg/180128/113416-1517110456633d.jpg'
img_data = requests.get(url,headers=headers).content

with open('./123.jpg','wb') as fp:
    fp.write(img_data)

urllib

#基于urllib的图片爬取
from urllib import request
url ='http://pic.netbian.com/uploads/allimg/180128/113416-1517110456633d.jpg'
request.urlretrieve(url,'./456.jpg')

 

正则解析

  将煎蛋网中的图片数据进行爬取且存储在本地

import requests
from urllib import request
#正则匹配
import re
import os
dirName = './imgLibs'
if not os.path.exists(dirName):
    os.mkdir(dirName)
    
url = 'http://jandan.net/pic/MjAxOTEwMDktNjY=#comments'
page_text = requests.get(url,headers=headers).text
#解析数据:img标签的src的属性值
ex = '<div class="text">.*?<img src="(.*?)" referrerPolicy.*?</div>'
img_src_list = re.findall(ex,page_text,re.S)
for src in img_src_list:
    if 'org_src' in src:
        src = re.findall('org_src="(.*?)" onload',src)[0]
    src = 'http:'+src
    imgName = src.split('/')[-1]
    imgPath = dirName+'/'+imgName
    request.urlretrieve(src,imgPath)
    print(imgName,'下载成功!!!')

 

bs4

环境的安装:

  pip install bs4
  pip install lxml    # lxml解释器

bs4的解析原理:

  实例化一个BeautifulSoup的一个对象,把即将被解析的页面源码数据加载到该对象中
  需要调用BeautifulSoup对象中的相关的方法和属性进行标签定位和数据的提取

BeautifulSoup的实例化

  BeautifulSoup(fp,'lxml'):将本地存储的html文档中的页面源码数据加载到该对象中 (fp文件句柄,lxml解释器)
  BeautifulSoup(page_text,'lxml'):将从互联网中请求道的页面源码数据加载到改对象中 (page_text网络源码)

标签的定位

  soup.tagName:只可以定位到第一个tagName标签
  属性定位:soup.find('tagName',attrName='value'),只可以定位到符合要求的第一个标签
    - findAll:返回值是一个列表。可以定位到符合要求的所有标签 class在这里要class_
  选择器定位:soup.select('选择器')
    - 选择器:id,class,tag,层级选择器(大于号表示一个层级,空格表示多个层级)

取文本

  text:将标签中所有的文本取出

  string:将标签中直系的文本取出

取属性

  tag['attrName']

例子

<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>
html
# bs4
from bs4 import BeautifulSoup
fp = open('./text.html',encoding='utf-8')
soup = BeautifulSoup(fp,'lxml')
# soup.find('div',class_='song')
# soup.select('#feng')[0]
# soup.select('.tang > ul > li > a')
# soup.select('.tang li > a')
# soup.select('.tang a')

# tag = soup.b
# tag.string

# div_tag = soup.find('div',class_='tang')
# div_tag.text

# a_tag = soup.select('#feng')[0]
# a_tag['href']
jupyter

 

 三国演义例子

需求:使用bs4解析三国演义小说的标题和内容,存储到本地

main_url = 'http://www.shicimingju.com/book/sanguoyanyi.html'
page_text = requests.get(url=main_url,headers=headers).text
#数据解析:章节的标题和详情页的url
soup = BeautifulSoup(page_text,'lxml')
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
    detail_url = 'http://www.shicimingju.com'+a['href']
    detail_page_text = requests.get(url=detail_url,headers=headers).text
    #数据解析:章节内容
    detail_soup = BeautifulSoup(detail_page_text,'lxml')
    div_tag = detail_soup.find('div',class_='chapter_content')
    content = div_tag.text
    
    fp.write(title+':'+content+'\n')
    print(title,'写入成功!!!')
fp.close()
View Code

 

xpath解析

环境的安装

  pip  install  lxml

解析原理

  实例化一个etree的对象,且把即将被解析的页面源码数据加载到该对象中
  调用etree对象中的xpath方法结合这不同形式的xpath表达式进行标签定位和数据提取

etree对象的实例化

  etree.parse('fileName')   本地文件
  etree.HTML(page_text)  网页源码

标签定位

  最左侧的/:一定要从根标签开始进行标签定位
  非最左侧的/:表示一个层级
  最左侧的//:可以从任意位置进行指定标签的定位
  非最左侧的//:表示多个层级
  属性定位://tagName[@attrName="value"]
  索引定位://tagName[@attrName="value"]/li[2],索引是从1开始
  逻辑运算:
    找到href属性值为空且class属性值为du的a标签
    //a[@href="" and @class="du"]
  模糊匹配:
    //div[contains(@class, "ng")]
    //div[starts-with(@class, "ta")]

取文本

  /text():直系的文本内容
  //text():所有的文本内容

取属性

  /@attrName

 例子

<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>
HTML
from lxml import etree
tree = etree.parse('./text.html')
# tree.xpath('/html//title')
# tree.xpath('//div')
# tree.xpath('//div[@class="tang"]')
# tree.xpath('//div[@class="tang"]/ul/li[2]')
# tree.xpath('//p[1]/text()')
# tree.xpath('//div[@class="song"]//text()')
tree.xpath('//img/@src')[0]
xpath

 

虎牙案例查看

url = 'https://www.huya.com/g/xingxiu'
page_text = requests.get(url=url,headers=headers).text

# 数据解析
tree = etree.HTML(page_text)
li_list = tree.xpath('//div[@class="box-bd"]/ul/li')
for li in li_list:
    #实现的是页面局部数据的指定数据的解析
    title = li.xpath('./a[2]/text()')[0]
    author = li.xpath('./span/span[1]/i/text()')[0]
    hot = li.xpath('./span/span[2]/i[2]/text()')[0]
    
    print(title,author,hot)
View Code

 

爬取http://pic.netbian.com/4kmeinv/中前五页的图片数据 

中文乱码的处理 多页码数据的爬取

将乱码的内容(img_name)转码
img_name.encode('iso-8859-1').decode('gbk')+'.jpg'

# url = 'http://pic.netbian.com/4kmeinv/' #第一页
#指定一个通用的url模板:不可变的
url = 'http://pic.netbian.com/4kmeinv/index_%d.html'
dirName = './MZLib'
if not os.path.exists(dirName):
    os.mkdir(dirName)
    
for page in range(1,6):
    if page == 1:
        new_url = 'http://pic.netbian.com/4kmeinv/'
    else:
        new_url = format(url%page)
    page_text = requests.get(url=new_url,headers=headers).text
    #数据解析:图片地址&图片名称
    tree = etree.HTML(page_text)
    li_list = tree.xpath('//div[@class="slist"]/ul/li')
    for li in li_list:
        img_name = li.xpath('./a/img/@alt')[0]
        img_name = img_name.encode('iso-8859-1').decode('gbk')+'.jpg'
        img_src = 'http://pic.netbian.com'+li.xpath('./a/img/@src')[0]
        img_data = requests.get(img_src,headers=headers).content #图片的二进制类型数据
        img_path = dirName+'/'+img_name
        with open(img_path,'wb') as fp:
            fp.write(img_data)
    print('第{}页爬取完毕!!!'.format(page))
        
View Code

 

爬取全国城市的名称 https://www.aqistudy.cn/historydata/

tree.xpath( I ) 可以加管道符来增加条件

url = 'https://www.aqistudy.cn/historydata/'
page_text = requests.get(url,headers=headers).text
tree = etree.HTML(page_text)
# hot_cities = tree.xpath('//div[@class="bottom"]/ul/li/a/text()')
# all_cities = tree.xpath('//div[@class="bottom"]/ul/div[2]/li/a/text()')
tree.xpath('//div[@class="bottom"]/ul/div[2]/li/a/text() | //div[@class="bottom"]/ul/li/a/text()')
View Code

 

小结:

 

 

1.你是如何理解数据解析的?
  就是将一张页面源码中的局部的数据进行提取
2.在爬虫中有哪些实现数据解析的方式?
  正则
  bs4
  xpath
  pyquery
3.数据解析的作用是什么?
  用来实现聚焦爬虫
4.数据解析的通用原理是什么?
  标签的定位
  数据的提取
5.bs4实现的数据解析中常用的方法和属性有哪些?各自的作用是什么?   soup.tagName   find/findAll()   select()   text/string   tag['attrName] 6.写出常用的xpath表达式?   属性定位   索引定位   取文本   取属性

 

posted @ 2019-10-09 14:48  驰念  阅读(279)  评论(0编辑  收藏  举报