• python爬虫解析页面数据的三种方式


    re模块

    • re.S表示匹配单行
    • re.M表示匹配多行
      使用re模块提取图片url,下载所有糗事百科中的图片

    普通版

    import requests
    import re
    import os
    
    if not os.path.exists('image'):
        os.mkdir('image')
    def get_page(number):
        '''
        页数
        :param number:
        :return:
        '''
        if number == 1:
            url = 'https://www.qiushibaike.com/pic/'
        else:
            url='https://www.qiushibaike.com/pic/'+str(number)
        headers = {
            'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'
        }
        page_text = requests.get(url=url,headers=headers).text
    
        img_list = re.findall('<div class="thumb">.*?<img src="(.*?)".*?>.*?</div>',page_text,re.S)
        for _url in img_list:
            img_url = 'https:'+_url
            response = requests.get(url=img_url,headers=headers)
            filename = img_url.split('/')[-1]
            file_path = 'image/%s'%filename
            with open(file_path,'wb') as f:
                f.write(response.content)
                print('爬取第%s页数据中:%s'%(number,filename))
    
    for i in range(1,35):
        get_page(i)
    

    使用多线程下载

    import requests
    import re
    import os
    from concurrent.futures import ThreadPoolExecutor
    if not os.path.exists('image'):
        os.mkdir('image')
    def get_page(number):
        '''
        页数
        :param number:
        :return:
        '''
        if number == 1:
            url = 'https://www.qiushibaike.com/pic/'
        else:
            url='https://www.qiushibaike.com/pic/'+'page/'+str(number)
        print(url)
        headers = {
            'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'
        }
        page_text = requests.get(url=url,headers=headers).text
    
        img_list = re.findall('<div class="thumb">.*?<img src="(.*?)".*?>.*?</div>',page_text,re.S)
        for _url in img_list:
            img_url = 'https:'+_url
            response = requests.get(url=img_url,headers=headers)
            filename = img_url.split('/')[-1]
            file_path = 'image/%s'%filename
            with open(file_path,'wb') as f:
                f.write(response.content)
                print('爬取第%s页数据中:%s'%(number,filename))
    
    if __name__ == '__main__':
        pool = ThreadPoolExecutor(5)
        for i in range(1,36):
            pool.submit(get_page,i)
    
        pool.shutdown()
        print('爬取完毕')
    

    xpath

    xpath在爬虫中的使用流程

    • 下载
    • 导包
    • 创建etree对象进行指定数据的解析
      • 本地:tree = etree.parse('本地文件路径')
        • etree.xpath('xpath表达式')
      • 网络:tree = etree.HTML('网络请求到的页面数据')
        • tree.xpath('xpath表达式')
    #安装
    pip3 install lxml
    #导包
    from lxml import etree
    

    常用的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
    

    xpath简单使用

    from lxml import etree
    import requests
    
    url = 'https://www.qiushibaike.com/pic/'
    page_text = requests.get(url=url).text
    
    tree = etree.HTML(page_text)
    url_list = tree.xpath('//div[@class="article block untagged mb15"]/div[2]/a/img/@src')
    
    print(url_list)
    

    xpath插件

    • xpath插件:就是可以直接将xpath表达式作用域浏览器的网页中
    • 安装:chorm浏览器 -> 更多工具 -> 扩展程序 -> 开启开发者模式 -> 将xpath插件拖动到页面
    • 快捷键
      • 开启关闭:ctrl + shift + x

    Element类型的对象可以继续调用xpath函数,对该对象表示的局部内容进行指定内容解析

    # 使用xpath提取出段子网的段子和标题
    import requests
    from lxml import etree
    
    url = 'https://ishuo.cn/'
    headers = {
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'
    }
    page_text = requests.get(url=url,headers=headers).text
    
    tree = etree.HTML(page_text)
    li_list = tree.xpath('//div[@id="list"]/ul/li')
    f = open('段子.text','w',encoding='utf-8')
    for li in li_list:
        content = li.xpath('./div[@class="content"]/text()')[0]
        title = li.xpath('./div[@class="info"]/a/text()')[0]
        f.write("#####################
    "+title+":
    "+content+"
    
    ")
    print('写入数据成功')
    

    BeautifulSoup解析

    BeautifulSoup库是python独有的库,简单便捷和高效

    • 核心思想:将将html文档转换成Beautiful对象,然后调用该对象中的属性和方法进行html文档指定内容的定位查找。

    • 导包

    from bs4 import BeautifulSoup
    
    • 创建BeautifulSoup对象:
      • 如果html文档的来源是来源于本地:Beautiful('open('本地的html文件')','lxml')
      • 如果html是来源于网络:Beautiful(‘网络请求到的页面数据’,‘lxml’)

    属性和方法

    1. 根据标签名查找:
    soup.a  # 只能找到第一个符合要求的标签
    
    1. 获取属性
    soup.a.attrs  # 获取a所有的属性和属性值,返回一个字典
    soup.a.attrs['href']   # 获取href属性
    soup.a['href']   # 也可简写为这种形式
    
    1. 获取内容
    soup.a.string   //text()
    soup.a.text   //text()
    soup.a.get_text()  //text()
    # 如果标签还有标签,那么string获取到的结果为None,而其它两个,可以获取文本内容
    
    1. find:找到第一个符合要求的标签
    soup.find('a') //找到第一个符合要求的
    soup.find('a', title="xxx")
    soup.find('a', alt="xxx")
    soup.find('a', class_="xxx")
    soup.find('a', id="xxx")
    
    1. find_All:找到所有符合要求的标签
    soup.find_All('a')
    soup.find_All(['a','b']) # 找到所有的a和b标签
    soup.find_All('a', limit=2)  # 限制前两个
    
    1. 根据选择器选择指定的内容
    select:soup.select('#feng')
    

    常见的选择器:标签选择器(a)、类选择器(.)、id选择器(#)、层级选择器

    select选择器返回永远是列表,需要通过下标提取指定的对象

    使用BeautifulSoup解析爬取三国演义小说全集

    import requests
    from bs4 import BeautifulSoup
    
    url = 'http://www.shicimingju.com/book/sanguoyanyi.html'
    headers = {
            'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'
        }
    page_text = requests.get(url=url,headers=headers).text
    
    def get_content(url,fileobj):
        '''
        爬取页面内容
        :param url:
        :param fileobj:
        :return:
        '''
        content_page = requests.get(url=url, headers=headers).text
        content_soup = BeautifulSoup(content_page, 'lxml')
        p_list = content_soup.select('.chapter_content > p')
        for p in p_list:
            fileobj.write('
    ' + p.text + '
    
    ')
    
    soup = BeautifulSoup(page_text,'lxml')
    a_list = soup.select('.book-mulu > ul > li > a')
    f = open('三国演义.txt','w',encoding='utf-8')
    for a in a_list:
        f.write('
    '+a.text)
        content_url = 'http://www.shicimingju.com'+a['href']
        get_content(content_url,f)
        print('爬取成功',a.text)
    
  • 相关阅读:
    [ACM] POJ 3687 Labeling Balls (拓扑排序,反向生成端)
    xml和json选择奖
    android 如何分析java.lang.IllegalArgumentException: Cannot draw recycled bitmaps异常
    代码农民提高生产力
    &#39;Basic&#39; attribute type should not be a persistence entity/a container
    13 适配器
    密码学基础知识(四)分组密码
    PKCS #1 RSA Encryption Version 1.5 填充方式
    rsa加密--选择padding模式需要注意的问题。。。
    RSA PKCS1 填充方式
  • 原文地址:https://www.cnblogs.com/wualin/p/10220113.html
Copyright © 2020-2023  润新知