关键词搜索

源码搜索 ×
×

四种Python爬虫常用的定位元素方法对比,你偏爱哪一款?

发布2021-02-20浏览352次

详情内容

在使用Python本爬虫采集数据时,一个很重要的操作就是如何从请求到的网页中提取数据,而正确定位想要的数据又是第一步操作。

本文将对比几种 Python 爬虫中比较常用的定位网页元素的方式供大家学习
1.传统 BeautifulSoup 操作
2.基于 BeautifulSoup 的 CSS 选择python基础教程器(与 PyQuery 类似)
3.XPath
4.正则表达式

参考网页是当当网图书畅销总榜:

http://bang.dangdang.com/books/bestsellers/01.00.00.00.00.00-24hours-0-0-1-1
在这里插入图片描述

我们以获取第一页 20 本书的书名为例。先确定网站没有设置反爬措施,是否能直接返回待解析的内容:

import requests

url = 'http://bang.dangdang.com/books/bestsellers/01.00.00.00.00.00-24hours-0-0-1-1'
response = requests.get(url).text
print(response)

    在这里插入图片描述

    仔细检查后发现需要的数据都在返回内容中,说明不需要特别考虑反爬举措

    审查网页元素后可以发现,书目信息都包含在 li 中,从属于 class 为 bang_list clearfix bang_list_mode 的 ul 中

    在这里插入图片描述

    进一步审查也可以发现书名在的相应位置,这是多种解析方法的重要基础
    在这里插入图片描述

    1. 传统 BeautifulSoup 操作
      经典的 BeautifulSoup 方法借助 from bs4 import BeautifulSoup,然后通过 soup = BeautifulSoup(html, “lxml”) 将文本转换为特定规范的结构,利用 find 系列方法进行解析,代码如下:
    import requests
    from bs4 import BeautifulSoup
    
    url = 'http://bang.dangdang.com/books/bestsellers/01.00.00.00.00.00-24hours-0-0-1-1'
    response = requests.get(url).text
    
    def bs_for_parse(response):
        soup = BeautifulSoup(response, "lxml")
        li_list = soup.find('ul', class_='bang_list clearfix bang_list_mode').find_all('li') # 锁定ul后获取20个li
        for li in li_list:
            title = li.find('div', class_='name').find('a')['title'] # 逐个解析获取书名
    
            print(title)
    
    if __name__ == '__main__':
        bs_for_parse(response)
    
      6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    在这里插入图片描述

    成功获取了 20 个书名,有些书面显得冗长可以通过正则或者其他字符串方法处理,本文不作详细介绍

    1. 基于 BeautifulSoup 的 CSS 选择器
      这种方法实际上就是 PyQuery 中 CSS 选择器在其他模块的迁移使用,用法是类似的。关于 CSS 选择器详细语法可以参考:http://www.w3school.com.cn/cssref/css_selectors.asp由于是基于 BeautifulSoup 所以导入的模块以及文本结构转换都是一致的:
    import requests
    from bs4 import BeautifulSoup
    
    url = 'http://bang.dangdang.com/books/bestsellers/01.00.00.00.00.00-24hours-0-0-1-1'
    response = requests.get(url).text
            
    def css_for_parse(response):
        soup = BeautifulSoup(response, "lxml") 
        print(soup)
    
    if __name__ == '__main__':
        css_for_parse(response)
    然后就是通过 soup.select 辅以特定的 CSS 语法获取特定内容,基础依旧是对元素的认真审查分析:
    
    import requests
    from bs4 import BeautifulSoup
    from lxml import html
    
    url = 'http://bang.dangdang.com/books/bestsellers/01.00.00.00.00.00-24hours-0-0-1-1'
    response = requests.get(url).text
            
    def css_for_parse(response):
        soup = BeautifulSoup(response, "lxml")
        li_list = soup.select('ul.bang_list.clearfix.bang_list_mode > li')
        for li in li_list:
            title = li.select('div.name > a')[0]['title']
            print(title)
    
    if __name__ == '__main__':
        css_for_parse(response)
    
      6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    1. XPath
      XPath 即为 XML 路径语言,它是一种用来确定 XML 文档中某部分位置的计算机语言,如果使用 Chrome 浏览器建议安装 XPath Helper 插件,会大大提高写 XPath 的效率。

    之前的爬虫文章基本都是基于 XPath,大家相对比较熟悉因此代码直接给出:

    import requests
    from lxml import html
    
    url = 'http://bang.dangdang.com/books/bestsellers/01.00.00.00.00.00-24hours-0-0-1-1'
    response = requests.get(url).text
    
    def xpath_for_parse(response):
        selector = html.fromstring(response)
        books = selector.xpath("//ul[@class='bang_list clearfix bang_list_mode']/li")
        for book in books:
            title = book.xpath('div[@class="name"]/a/@title')[0]
            print(title)
    
    if __name__ == '__main__':
        xpath_for_parse(response)
    
      6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    1. 正则表达式
      如果对 HTML 语言不熟悉,那么之前的几种解析方法都会比较吃力。这里也提供一种万能解析大法:正则表达式,只需要关注文本本身有什么特殊构造文法,即可用特定规则获取相应内容。依赖的模块是 re

    首先重新观察直接返回的内容中,需要的文字前后有什么特殊:

    import requests
    import re
    
    url = 'http://bang.dangdang.com/books/bestsellers/01.00.00.00.00.00-24hours-0-0-1-1'
    response = requests.get(url).text
    print(response)
    
      6

    在这里插入图片描述

    在这里插入图片描述

    观察几个数目相信就有答案了:

    分析到这里正则表达式就可以写出来了:

    import requests
    import re
    
    url = 'http://bang.dangdang.com/books/bestsellers/01.00.00.00.00.00-24hours-0-0-1-1'
    response = requests.get(url).text
    
    def re_for_parse(response):
        reg = '<div class="name"><a href="http://product.dangdang.com/\d+.html" target="_blank" title="(.*?)">'
        for title in re.findall(reg, response):
            print(title)
    
    if __name__ == '__main__':
        re_for_parse(response)
    
      6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    可以发现正则写法是最简单的,但是需要对于正则规则非常熟练。所谓正则大法好!

    当然,不论哪种方法都有它所适用的场景,在真实操作中我们也需要在分析网页结构来判断如何高效的定位元素,最后附上本文介绍的四种方法的完整代码,大家可以自行操作一下来加深体会

    import requests
    from bs4 import BeautifulSoup
    from lxml import html
    import re
    
    url = 'http://bang.dangdang.com/books/bestsellers/01.00.00.00.00.00-24hours-0-0-1-1'
    response = requests.get(url).text
    
    def bs_for_parse(response):
        soup = BeautifulSoup(response, "lxml")
        li_list = soup.find('ul', class_='bang_list clearfix bang_list_mode').find_all('li')
        for li in li_list:
            title = li.find('div', class_='name').find('a')['title']
            print(title)
    
    def css_for_parse(response):
        soup = BeautifulSoup(response, "lxml")
        li_list = soup.select('ul.bang_list.clearfix.bang_list_mode > li')
        for li in li_list:
            title = li.select('div.name > a')[0]['title']
            print(title)
    
    def xpath_for_parse(response):
        selector = html.fromstring(response)
        books = selector.xpath("//ul[@class='bang_list clearfix bang_list_mode']/li")
        for book in books:
            title = book.xpath('div[@class="name"]/a/@title')[0]
            print(title)
    
    def re_for_parse(response):
        reg = '<div class="name"><a href="http://product.dangdang.com/\d+.html" target="_blank" title="(.*?)">'
        for title in re.findall(reg, response):
            print(title)
    
    if __name__ == '__main__':
        # bs_for_parse(response)
        # css_for_parse(response)
        # xpath_for_parse(response)
        re_for_parse(response)
    
      6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    相关技术文章

    最新源码

    下载排行榜

    点击QQ咨询
    开通会员
    返回顶部
    ×
    微信扫码支付
    微信扫码支付
    确定支付下载
    请使用微信描二维码支付
    ×

    提示信息

    ×

    选择支付方式

    • 微信支付
    • 支付宝付款
    确定支付下载