zoukankan      html  css  js  c++  java
  • 爬虫之三种数据解析

    在获取到响应数据后,需要针对性的提取其中有用的部分,这也是采集数据最常见的方式聚焦网络爬虫。

    数据解析三种方式:

        1.正则表达式解析

      2.xpath解析

      3.bs4解析

    1.正则表达式解析(re模块

      案例:爬取糗事百科---糗图:https://www.qiushibaike.com/pic/

     1 '''
     2 <div class="article block untagged mb15" id="qiushi_tag_122080461">
     3
     4 <div class="author clearfix">
     5 <a href="/users/42609417/" target="_blank" rel="nofollow">
     6 <img src="//pic.qiushibaike.com/system/avtnew/4260/42609417/medium/20190802105831.jpg" alt="灿烂的你">
     7 </a>
     8 <a href="/users/42609417/" target="_blank" title="灿烂的你">
     9 <h2>灿烂的你</h2>
    10 </a>
    11 <div class="articleGender womenIcon">0</div>
    12 </div>
    13
    14
    15
    16 <a href="/article/122080461" target="_blank" class="contentHerf">
    17 <div class="content">
    18
    19
    20
    21 <span>求大神把中间图片p掉看看长啥样</span>
    22
    23
    24 </div>
    25 </a>
    26
    27
    28
    29
    30 <div class="thumb">
    31
    32 <a href="/article/122080461" target="_blank">
    33 <img src="//pic.qiushibaike.com/system/pictures/12208/122080461/medium/3N2UVCLSJEHGAUAZ.jpg" alt="求大神把中间图片p掉看看长啥样">
    34 </a>
    35
    36 </div>
    37
    38
    39
    40 <div class="stats">
    41 <span class="stats-vote"><i class="number">33</i> 好笑</span>
    42 <span class="stats-comments">
    43
    44
    45
    46
    47 </span>
    48 </div>
    49 <div id="qiushi_counts_122080461" class="stats-buttons bar clearfix">
    50 <ul class="clearfix">
    51 <li id="vote-up-122080461" class="up">
    52 <a href="javascript:voting(122080461,1)" class="voting" data-article="122080461" id="up-122080461" rel="nofollow">
    53 <i></i>
    54 <span class="number hidden">33</span>
    55 </a>
    56 </li>
    57 <li id="vote-dn-122080461" class="down">
    58 <a href="javascript:voting(122080461,-1)" class="voting" data-article="122080461" id="dn-122080461" rel="nofollow">
    59 <i></i>
    60 <span class="number hidden">0</span>
    61 </a>
    62 </li>
    63
    64 <li class="comments">
    65 <a href="/article/122080461" id="c-122080461" class="qiushi_comments" target="_blank">
    66 <i></i>
    67 </a>
    68 </li>
    69
    70 </ul>
    71 </div>
    72 <div class="single-share">
    73 <a class="share-wechat" data-type="wechat" title="分享到微信" rel="nofollow">微信</a>
    74 <a class="share-qq" data-type="qq" title="分享到QQ" rel="nofollow">QQ</a>
    75 <a class="share-qzone" data-type="qzone" title="分享到QQ空间" rel="nofollow">QQ空间</a>
    76 <a class="share-weibo" data-type="weibo" title="分享到微博" rel="nofollow">微博</a>
    77 </div>
    78 <div class="single-clear"></div>
    79
    80
    81
    82
    83 </div>
    84 '''
    html页面聚焦

      数据采集之re模块正则解析脚本

     1 # 糗事百科---糗图:https://www.qiushibaike.com/pic/
     2 import os
     3 import re
     4 import requests
     5 from fake_useragent import UserAgent
     6 UA=UserAgent()
     7 headers={
     8 'User-Agent':UA.random
     9 }
    10 start_page=1
    11 end_page=36
    12 reg='<div class="article block untagged mb15".*?<h2>(.*?)</h2>.*?<img src="(.*?)" alt.*?</div>'#正则表达式编写
    13
    14
    15 if not os.path.exists('糗图'):
    16 os.mkdir('糗图')
    17
    18 for page in range(start_page,end_page):
    19 print(f'第{page}页糗图数据获取中............')
    20 url = f'https://www.qiushibaike.com/pic/page/{page}/?s=5215717'
    21 response=requests.get(url,headers=headers)
    22 res=re.findall(reg,response.text,re.S)#正则进行匹配提取解析----注意re.S处理换行和回车
    23 # print(res)
    24 for pic in res:
    25 pic_url='https:'+pic[1]
    26 pic_name=pic[1].rsplit('/')[-1]
    27 pic_path=os.path.join('糗图',pic_name)
    28
    29 if pic_name in os.listdir('糗图'):
    30 continue
    31 response_pic=requests.get(pic_url,headers=headers)
    32
    33 with open(pic_path,'wb')as f:
    34  f.write(response_pic.content)
    35 print(f'{pic_name}下载成功!!!')
    正则解析

    2.xpath解析  

    依赖模块:
        xlml pip install lxml
    模块导入:
        from lxml.html.clean import etree #python 3.5之后
        #from lxml import etree #python 3.5之前
    解析原理:
        实例化一个etree类型的对象,且将即将被解析的页面源码数据加载到该对象中
        调用该对象中的xpath方法结合着不同的xpath表达式进行标签定位和数据提取
    实例化对象:
        tree=etree.parse(fileName)----本地文件
        tree=etree.HTML(page_text)----获取的页面内容
    xpath方法返回值永远是一个列表
    xpath表达式中最左侧的/和//的区别:
        /表示必须从根标签进行定位(从html开始)
        //表示可以从任意位置标签定位
    xpath表达式中非最左侧的/和//的区别:
        /表示直属层级目录
        //表示后代多层级目录
    xpath标签定位:
         属性定位:
            tree.xpath('//div[@id="content"]') tree.xpath('//div[@class="c1"]')     
         tree.xpath('//div/sapn|/p')找到div下所有直属的span和p标签
        层级、索引定位: 
            tree.xpath('//div[@id="content"]/ul/li[2]')找到id为content的div下ul中的第2(索引从1开始)个直系li标签 
        逻辑运算定位: 
           tree.xpath('//a[@id="content" and @href=""]')找到id为content并且href为空的a标签 
           tree.xpath('//a[@id="content" or @href=""]')找到id为content或者href为空的a标签 
        模糊定位: 
           tree.xpath('//div[contains(@class,"c")]')找到class属性中含有c的div标签 
           tree.xpath('//div[start-with(@class,"c")]')找到class属性以c开头的div标签 
        位置属性定位: 
           tree.xpath('//title[@*]") 选取所有带有属性的 div 元素 
    xpath取值: 
        取文本 
           /text():获取的是标签下直系的文本数据 
           //text():获取的是标签下所有的文本数据 
       取属性@ 
          /@attr 
    更多可参考菜鸟教程:https://www.runoob.com/xpath/xpath-syntax.html
        案例一:糗事百科----文字:https://www.qiushibaike.com/text/
     1 # 糗事百科----文字:https://www.qiushibaike.com/text/
     2 import requests
     3 from lxml.html.clean import etree
     4 from fake_useragent import UserAgent
     5 UA=UserAgent()
     6 headers={'User-Agent':UA.random}
     7
     8 url_model='https://www.qiushibaike.com/text/page/%d/'
     9 fp=open('糗事百科---段子.txt','w',encoding='utf-8')
    10 for page in range(1,14):
    11 url=format(url_model%page)
    12 response=requests.get(url,headers=headers)
    13 tree=etree.HTML(response.text)
    14 nick_list=tree.xpath('//div[@class="author clearfix"]/a[2]/h2/text()|//div[@class="author clearfix"]/span[2]/h2/text()')#解析昵称(使用了‘|’多条件选择匹配)
    15 link_list=tree.xpath('//a[@class="contentHerf"]/@href')#解析内容的连接
    16
    17 content_list=[]
    18 url_='https://www.qiushibaike.com'
    19 for nick,link in zip(nick_list,link_list):
    20 content_list.append((nick,url_+link))
    21 # print(content_list)
    22
    23 for i,content in enumerate(content_list):
    24 nick_name=content[0]
    25 url_detail=content[1]
    26 response_detail=requests.get(url_detail,headers=headers)
    27 content_tree=etree.HTML(response_detail.text)
    28
    29 content_detail=content_tree.xpath('//div[@class="content"]/text()')
    30 content_str='
    '.join(content_detail)
    31 str='<'+nick_name.strip('
    ')+'>
    '+content_str+'
    
    '
    32  fp.write(str)
    33 print(f'第{page}页第{i}条段子下载完成!')
    34 fp.close()
    xpath解析之糗图段子采集

         案例二:彼岸图图片采集:http://pic.netbian.com/

     1 '''
     2 彼岸图图片采集:http://pic.netbian.com/
     3 '''
     4 import os
     5 from lxml.html.clean import etree#xpath解析
     6 import requests
     7 from fake_useragent import UserAgent
     8 UA=UserAgent()
     9 headers={'User-Agent':UA.random}
    10
    11 #首页获取图片分类
    12 url_index='http://pic.netbian.com'
    13 response_index=requests.get(url_index,headers=headers)
    14 response_index.encoding='gbk'
    15 # tree = etree.parse(filename)#解析本地html文件
    16 tree_index=etree.HTML(response_index.text)
    17 picture_list=tree_index.xpath('//div[@class="classify clearfix"]/a/@href')
    18 title_list=tree_index.xpath('//div[@class="classify clearfix"]/a/text()')
    19 all_pictures=[]
    20 for title,pic in zip(title_list,picture_list):
    21 all_pictures.append((title,url_index+pic))
    22 print('图片分类如下:')
    23 for i,j in enumerate(all_pictures):
    24 print(i,'	',j[0])
    25
    26 # print(all_pictures)
    27 #输入数字序号进行专辑分类采集:
    28 num=int(input('请输入你要采集的图片的序号>>>>'))
    29
    30
    31 #创建专辑文件夹
    32 dir_pic=all_pictures[num][0]
    33 if not os.path.exists(dir_pic):
    34  os.mkdir(dir_pic)
    35
    36 #请求每个分类的第一页拿到总页码,并保存第一页的内容
    37 print(f'{dir_pic}加载中......')
    38 print('获取第1页图片:')
    39 url=all_pictures[num][1]
    40
    41 #请求首页,获取首页数据及总页码
    42 response = requests.get(url, headers=headers)
    43 tree = etree.HTML(response.text)
    44 pages = int(tree.xpath('//div[@class="page"]/a[7]/text()')[0])
    45 print(pages,type(pages))
    46
    47 li_list = tree.xpath('//div[@class="slist"]/ul[@class="clearfix"]/li')
    48 for i,li in enumerate(li_list):
    49 name = ''
    50 if li.xpath('./a/b/text()'):
    51 name = li.xpath('./a/b/text()')[0].encode('iso-8859-1').decode('gbk')
    52 url_ = url_index + li.xpath('./a/img/@src')[0]
    53
    54 file_name = name + url_.rsplit('/')[-1]
    55 response_ = requests.get(url_, headers=headers)
    56 file_path = os.path.join(dir_pic, file_name)
    57 if file_name in os.listdir(dir_pic):
    58 continue
    59 with open(file_path, 'wb')as f:
    60  f.write(response.content)
    61 print(f"第1页第{i}张{file_name}下载完成!")
    62 print(url)
    63
    64 #第二页开始爬取
    65 for i in range(2,pages):
    66 url_=url+f'index_{i}.html'
    67 response = requests.get(url_, headers=headers)
    68 tree = etree.HTML(response.text)
    69
    70 li_list = tree.xpath('//div[@class="slist"]/ul[@class="clearfix"]/li')
    71 for j,li in enumerate(li_list):
    72 name = ''
    73 if li.xpath('./a/b/text()'):
    74 name =li.xpath('./a/b/text()')[0].encode('iso-8859-1').decode('gbk')
    75 url_ = url_index + li.xpath('./a/img/@src')[0]
    76
    77 file_name = name + url_.rsplit('/')[-1]
    78 response_ = requests.get(url_, headers=headers)
    79 file_path = os.path.join(dir_pic, file_name)
    80 if file_name in os.listdir(dir_pic):
    81 continue
    82 with open(file_path, 'wb')as f:
    83  f.write(response_.content)
    84 print(f"第{i}页第{j}张{file_name}下载完成!")
    xpath解析之彼岸图图片采集

    3.bs4解析

    依赖模块:1)bs4 pip install bs4
       (2)xlml pip install lxml
    模块导入:
       from bs4 import BeautifulSoup
    bs4解析原理1)实例化一个BeautifulSoup的对象,且将即将被解析的页面源码加载到该对象中
       (2)使用该对象中的属性或者方法进行标签定位和数据提取
    使用方式:1)将本地存储的html文档加载到该对象中
          soup=BeautifulSoup(fp,'lxml')
       (2)将互联网上获取的html源码加载到该对象中
          soup=BeautifulSoup(page_text,'lxml')
    内容解析:
    1)定位标签
       a. soup.tagName返回一个标签 soup.div
       b. soup.find(’tagName',attr_=value)返回第一个标签 soup.find('div',class_='home')
    
       c. soup.find_all(’tagName',attr_=value)返回标签列表 soup.find('div',class_='home')
    
       d. soup.select('选择器')返回列表
          类选择器,id选择器,标签选择器,层级选择器(>表示一个层级,空格表示多个层级)soup.select('.tang > ul > li > a')
    
    2)获取标签内容或者属性值
       a. element.string string获取的是标签中直系的文本内容
       b. element.text text获取的是标签中所有的文本内容
       c. element.attrs/element.attrs['属性']/soup.tagName['属性'] 获取标签的所有/指定属性值
     1 环境安装
     2 - 需要将pip源设置为国内源,阿里源、豆瓣源、网易源等
     3 - windows
     4 (1)打开文件资源管理器(文件夹地址栏中)
     5 (2)地址栏上面输入 %appdata%
     6 (3)在这里面新建一个文件夹 pip
     7 (4)在pip文件夹里面新建一个文件叫做 pip.ini ,内容写如下即可
     8 [global]
     9 timeout = 6000
    10 index-url = https://mirrors.aliyun.com/pypi/simple/
    11 trusted-host = mirrors.aliyun.com
    12 - linux
    13 (1)cd ~
    14 (2)mkdir ~/.pip
    15 (3)vi ~/.pip/pip.conf
    16 (4)编辑内容,和windows一模一样
    17 - 需要安装:pip install bs4
    18  bs4在使用时候需要一个第三方库,把这个库也安装一下
    19  pip install lxml
    20 基础使用
    21 使用流程:
    22 - 导包:from bs4 import BeautifulSoup
    23 - 使用方式:可以将一个html文档,转化为BeautifulSoup对象,然后通过对象的方法或者属性去查找指定的节点内容
    24 (1)转化本地文件:
    25 - soup = BeautifulSoup(open('本地文件'), 'lxml')
    26 (2)转化网络文件:
    27 - soup = BeautifulSoup('字符串类型或者字节类型', 'lxml')
    28 (3)打印soup对象显示内容为html文件中的内容
    29
    30 基础巩固:
    31 (1)根据标签名查找
    32 - soup.a 只能找到第一个符合要求的标签
    33 (2)获取属性
    34 - soup.a.attrs 获取a所有的属性和属性值,返回一个字典
    35 - soup.a.attrs['href'] 获取href属性
    36 - soup.a['href'] 也可简写为这种形式
    37 (3)获取内容
    38 - soup.a.string
    39 - soup.a.text
    40 - soup.a.get_text()
    41  【注意】如果标签还有标签,那么string获取到的结果为None,而其它两个,可以获取文本内容
    42 (4)find:找到第一个符合要求的标签
    43 - soup.find('a') 找到第一个符合要求的
    44 - soup.find('a', title="xxx")
    45 - soup.find('a', alt="xxx")
    46 - soup.find('a', class_="xxx")
    47 - soup.find('a', id="xxx")
    48 (5)find_all:找到所有符合要求的标签
    49 - soup.find_all('a')
    50 - soup.find_all(['a','b']) 找到所有的a和b标签
    51 - soup.find_all('a', limit=2) 限制前两个
    52 (6)根据选择器选择指定的内容
    53 select:soup.select('#feng')
    54 - 常见的选择器:标签选择器(a)、类选择器(.)、id选择器(#)、层级选择器
    55 - 层级选择器:
    56 div .dudu #lala .meme .xixi 下面好多级
    57 div > p > a > .lala 只能是下面一级
    58 【注意】select选择器返回永远是列表,需要通过下标提取指定的对象
    bs4安装与基础使用

      案例: 糗事百科----文字首页:https://www.qiushibaike.com/text/

     1 # 糗事百科----文字首页:https://www.qiushibaike.com/text/
     2 import requests
     3 from bs4 import BeautifulSoup
     4 from fake_useragent import UserAgent
     5 UA=UserAgent()
     6 headers={'User-Agent':UA.random}
     7
     8 url='https://www.qiushibaike.com/text/'
     9 response=requests.get(url,headers=headers)
    10 soup=BeautifulSoup(response.text,'lxml')#依赖lxml模块,需提前安装
    11
    12 content_list=soup.select('.content>span')
    13 for i,content in enumerate(content_list):
    14 print(i+1,content.text.strip())
    bs4解析之糗事百科段子采集
  • 相关阅读:
    Netsharp下微信菜单以及OAuth
    权限管理
    java面向对象基础(转)
    闲来无事做了一个批处理的win10账号管理
    bat获取系统时间修改系统密码
    bat常用命令
    bat修改密码
    vbs的一些入门基础。。。
    WCF 之 DataContract
    WCF 之 OperationContract
  • 原文地址:https://www.cnblogs.com/open-yang/p/11304773.html
Copyright © 2011-2022 走看看