码迷,mamicode.com
首页 > 编程语言 > 详细

Python--爬虫数据解析

时间:2020-07-21 13:36:53      阅读:73      评论:0      收藏:0      [点我收藏+]

标签:value   作者   agent   att   源码   乱码   属性   sele   rap   

页面解析和数据提取

一般来讲对我们而言,需要抓取的是某个网站或者某个应用的内容,提取有用的价值。内容一般分为两部分,非结构化的数据 和 结构化的数据。

常用的数据解析有正则(re)、bs4、xpath等。

正则使用参考

?

bs4

bs4解析原理

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

?

bs4解析流程

?? 环境安装

pip install bs4

?? 导入模块

from bs4 import BeautifulSoup

?? 实例化一个BeautifulSoup对象

# 转化本地文件(将本地存储的一个html文档中的数据加载到实例化好的BeautifulSoup对象中)
soup = BeautifulSoup(open(‘本地文件‘), ‘lxml‘)

# 转化网络文件(将从互联网上获取的页面源码数据加载到实例化好的BeautifulSoup对象中)
soup = BeautifulSoup(‘字符串类型或者字节类型‘, ‘lxml‘)

?? 调用BeautifulSoup对象中的相关属性和方法进行标签的定位

?

bs4基本语法

1.根据标签名查找

soup.tagName
- soup.a	只能找到第一个符合要求的标签

2.获取属性

soup.tagName[‘attrName‘]
- soup.a.attrs  获取a所有的属性和属性值,返回一个字典
- soup.a.attrs[‘href‘]   获取href属性
- soup.a[‘href‘]   也可简写为这种形式

3.获取内容

.string:获取直系的文本内容
.text:获取所有的文本内容
- soup.a.string      获取a标签的直系文本
- soup.a.text     这是属性,获取a子类的所有文本
- soup.a.get_text()  这是方法,获取a标签子类的所有文本
【注意】如果标签还有标签,那么string获取到的结果为None,而其它两个,可以获取文本内容

4.属性定位find方法

soup.find(‘tagName‘, attrName=‘value‘)
- soup.find(‘a‘)  找到第一个符合要求的a标签
- soup.find(‘a‘, title="xxx") 找具有title=xxx属性的第一个a标签
- soup.find(‘li‘, alt="xxx")	找到具有alt=xxx属性的第一个li标签
- soup.find(‘ul‘, class_="xxx")	找到具有class=xxx属性的第一个ui标签
- soup.find(‘div‘, id="xxx")	找到具有id=xxx属性的第一个div标签

5.属性定位find_all方法

soup.find_all(‘tagName‘, attrName=‘value‘),返回值为列表
- soup.find_all(‘a‘)	#找到所有a标签
- soup.find_all(‘a‘, title=‘xxx‘)	找到具有title=xxx属性的所有a标签
- soup.find_all(‘div‘, class_=‘xxx‘, limit=3)	找到具有class=xxx属性的前三个标签

6.选择器定位select方法

soup.select(‘选择器‘)
- soup.select(‘.song‘)	找到类属性为song的标签
- soup.select(‘#song‘)	找到id属性为song的标签

	- 常见的选择器:标签选择器(a)、类选择器(.)、id选择器(#)、层级选择器
- 层级选择器:
        div .haha #wan    	空格表示多个层级
        div > p > a > img 	>表示一个层级

?

bs4爬虫示例

?? 爬取三国整篇内容

#爬取三国整篇内容(章节名称和章节内容) http://www.shicimingju.com/book/sanguoyanyi.html
import requests
from bs4 import BeautifulSoup

fp = open(‘sanguo.txt‘,‘w‘,encoding=‘utf-8‘)

headers = {
    ‘User-Agent‘: ‘Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 Safari/537.36‘
}
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‘) #返回的列表中存储的是一个个a标签
for a in a_list:
    title = a.string
    detail_url = ‘http://www.shicimingju.com‘+a[‘href‘]
    detail_page_text = requests.get(detail_url, headers=headers).text
    #解析详情页中的章节内容
    soup = BeautifulSoup(detail_page_text, ‘lxml‘)
    content = soup.find(‘div‘, class_=‘chapter_content‘).text
    fp.write(title+‘:‘+content+‘\n‘)
    print(title,‘下载成功!‘)
fp.close

?

xpath

xpath解析原理

  • 实例化一个etree的对象,然后将即将被解析的页面源码加载到该对象中
  • 使用etree对象中xpath方法结合着不同形式的xpath表达式实现标签定位和数据提取

?

xpath解析流程

?? 环境安装

pip install lxml

?? 导入模块

from lxml import etree

?? 实例化一个etree对象

# 转化本地文件(将本地存储的一个html文档中的数据加载到实例化好的tree对象中)
tree = etree.parse(‘test.html‘)
# 转化网络文件(将从互联网上获取的页面源码数据加载到实例化好的tree对象中)
tree = etree.HTML(page_text)

?

xpath基本语法

xpath表达式:xpath方法的返回值一定是一个列表
最左侧的/表示:xpath表达式一定要从根标签逐层进行标签查询和定位
最左侧的//表示:xpath表达式可以从任意位置定位标签
非最左侧的/:表示一个层级
非最左侧的//:表示夸多个层级
属性定位://tagName[@attrName=‘value‘]
索引定位://tagName[index] 索引从1开始

1.取文本:

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

2.取属性:

/@attrName

示例

准备html内容

<html><body>
<div>
    <ul>
         <li class="item-0"><a href="link1.html">first item</a></li>
         <li class="item-1"><a href="link2.html">second item</a></li>
         <li class="item-inactive"><a href="link3.html">third item</a></li>
         <li class="item-1"><a href="link4.html">fourth item</a></li>
         <li class="item-0"><a href="link5.html">fifth item</a></li>
</ul>
 </div>
</body></html>

1.获取所有的

  • 标签

    from lxml import etree
    html = etree.parse(‘hello.html‘)
    
    result = html.xpath(‘//li‘)
    
    print(result)   # 打印<li>标签的元素集合
    
    result_text = html.xpath(‘//li/text()‘)
    

    2.获取

  • 标签的所有class属性

    from lxml import etree
    
    html = etree.parse(‘hello.html‘)
    result = html.xpath(‘//li/@class‘)
    
    print result
    
    结果是
    [‘item-0‘, ‘item-1‘, ‘item-inactive‘, ‘item-1‘, ‘item-0‘]
    

    3.继续获取<li>标签下hreflink1.html<a> 标签

    from lxml import etree
    
    html = etree.parse(‘hello.html‘)
    result = html.xpath(‘//li/a[@href="link1.html"]‘)
    
    print result
    
    运行结果
    
    [<Element a at 0x10ffaae18>]
    

    4.获取最后一个 <li><a> 的 href

    from lxml import etree
    
    html = etree.parse(‘hello.html‘)
    
    result = html.xpath(‘//li[last()]/a/@href‘)
    # 谓语 [last()] 可以找到最后一个元素
    
    print result
    
    运行结果
    
    [‘link5.html‘]
    

    ?

    xpath 爬虫示例

    ?? 示例1

    #爬取糗事百科中段子内容和作者名称
    import requests
    from lxml import etree
    
    headers = {
        ‘User-Agent‘: ‘Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 Safari/537.36‘
    }
    url = ‘https://www.qiushibaike.com/text/‘
    page_text = requests.get(url=url, headers=headers).text
    
    #解析内容
    tree = etree.HTML(page_text)
    div_list = tree.xpath(‘//div[@class="col1 old-style-col1"]/div‘)
    
    for div in div_list:
        author = div.xpath(‘./div[1]/a[2]/h2/text()‘)[0] #实现局部解析
        content = div.xpath(‘./a[1]/div/span//text()‘)
        content = ‘‘.join(content)
        
        print(author, content)
    

    ?? 示例2

    # http://pic.netbian.com/4kmeinv/  联系xpath和解决中文乱码问题
    
    dirName = ‘./meinvLibs‘
    if not os.path.exists(dirName):
        os.mkdir(dirName)
    url = ‘http://pic.netbian.com/4kmeinv/index_%d.html‘
    for page in range(1,11):
        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)
        a_list = tree.xpath(‘//div[@class="slist"]/ul/li/a‘)
        for a in a_list:
            img_src = ‘http://pic.netbian.com‘ + a.xpath(‘./img/@src‘)[0]
            img_name = a.xpath(‘./b/text()‘)[0]
            img_name = img_name.encode(‘iso-8859-1‘).decode(‘gbk‘)
            img_data = requests.get(url=img_src, headers=headers).content
            imgPath = dirName+‘/‘+img_name+‘.jpg‘
            with open(imgPath, ‘wb‘) as fp:
                fp.write(img_data)
                print(img_name, "下载成功!!!")
    

    ?? 示例3

    # http://sc.chinaz.com/jianli/free.html 爬取简历模板前五页  通过xpath解析
    import requests, os
    from lxml import etree
    
    save_resume_dir = ‘./jianli‘
    if not os.path.exists(save_resume_dir):
        os.mkdir(save_resume_dir)
    
    headers = {
        ‘User-Agent‘: ‘Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 Safari/537.36‘
    }
    
    url = ‘http://sc.chinaz.com/jianli/free_%d.html‘
    
    for page in range(1,6):
        if page == 1:
            new_url = ‘http://sc.chinaz.com/jianli/free.html‘
        else:
            new_url = format(url%page)
        page_text = requests.get(url=new_url, headers=headers).text  #向每一页发起请求
        tree = etree.HTML(page_text)
        a_list = tree.xpath(‘//div[@id="container"]/div/a‘)   #获取每一页中所有的简历
        for a in a_list:
            resume_url = a.xpath(‘./@href‘)[0]  #得到每一份简历的url地址
            resume_anme = a.xpath(‘./img/@alt‘)[0]  #得到每一份简历的名字
            resume_anme = resume_anme.encode(‘iso-8859-1‘).decode(‘utf-8‘)  #解决简历名字乱码
            resume_text = requests.get(url=resume_url, headers=headers).text  #向每一份简历的页面发起请求
            tree = etree.HTML(resume_text)
            resume_down_url = tree.xpath(‘//div[@class="down_wrap"]/div[2]/ul/li[1]/a/@href‘)[0]  #对每一份简历页面请求数据进行解析,得到下载的url
            resume_down_text = requests.get(url=resume_down_url, headers=headers).content  #下载每一份简历
            resume_path = save_resume_dir + ‘/‘ + resume_anme + ‘.rar‘
            with open(resume_path, ‘wb‘) as fp:
                fp.write(resume_down_text)
                print(resume_anme+‘简历模板下载成功!!!‘)
    

    ?? 示例4

    # 爬取梨视频任意板块最热视频  https://www.pearvideo.com/category_8
    import requests
    from lxml import etree
    import re
    
    headers = {
        ‘User-Agent‘: ‘Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 Safari/537.36‘
    }
    
    main_url = ‘https://www.pearvideo.com/category_8‘
    
    main_text = requests.get(url=main_url, headers=headers).text
    tree = etree.HTML(main_text)
    
    div_list = tree.xpath(‘//*[@id="listvideoListUl"]/li‘)
    
    for li in div_list:
        detile_url = ‘https://www.pearvideo.com/‘ + li.xpath(‘./div/a/@href‘)[0]  #获取视频详情页
        title = li.xpath(‘./div/a/div[2]/text()‘)[0] + ‘.mp4‘  #获取视频名字
    
        detile_page_text = requests.get(url=detile_url, headers=headers).text  #向视频详情页发起请求
    
        ex = ‘srcUrl="(.*?)",vdoUrl‘   #通过正则获取js动态加载的数据
        video_url = re.findall(ex, detile_page_text, re.S)[0]  #解析出视频url的地址
        video_data = requests.get(video_url, headers=headers).content   #对视频url发起请求进行下载
    
        with open(f‘./video/{title}‘, ‘wb‘) as fp:
            fp.write(video_data)
    

    Python--爬虫数据解析

    标签:value   作者   agent   att   源码   乱码   属性   sele   rap   

    原文地址:https://www.cnblogs.com/yanjieli/p/13353926.html

  • (0)
    (0)
       
    举报
    评论 一句话评论(0
    登录后才能评论!
    © 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
    迷上了代码!