首页 > 其他分享 >解析库

解析库

时间:2024-01-17 18:47:17浏览次数:27  
标签:匹配 self list re html print 解析

解析库

解析库的意思是对我们需要爬取的数据进行操作,从而获得想要的数据。

解析库有很多种,我们可以根据自己的习惯进行选取。

主要分为以下四种:

  • 正则表达式
  • xpath
  • Beautiful Soup
  • pyquery

一、正则表达式

首先讲解正则表达式的使用方法.

1) 元字符

元字符 匹配内容
. 匹配除换行符以外的任意字符
\w 匹配所有普通字符(数字、字母或下划线)
\s 匹配任意的空白符
\d 匹配数字
\n 匹配一个换行符
\t 匹配一个制表符
\b 匹配一个单词的结尾
^ 匹配字符串的开始位置
$ 匹配字符串的结尾位置
\W 匹配非字母或数字或下划线
\D 匹配非数字
\S 匹配非空白符
a|b 匹配字符 a 或字符 b
() 正则表达式分组所用符号,匹配括号内的表达式,表示一个组。
[...] 匹配字符组中的字符
[^...] 匹配除了字符组中字符的所有字符

2) 量词

量词 用法说明
* 重复零次或者更多次
+ 重复一次或者更多次
重复0次或者一次
重复n次
重复n次或者更多次
重复n到m次

3) 字符组

有时也会出现各种字符组成的字符组,这在正则表达式中使用[]

正则 待匹配字符 匹配结果 说明
[0123456789] 8 True 在一个字符组里枚举所有字符,字符组里的任意一个字符 和"待匹配字符"相同都视为可以匹配。
[0123456789] a False 由于字符组中没有 "a" 字符,所以不能匹配。
[0-9] 7 True 也可以用-表示范围,[0-9] 就和 [0123456789] 是一个意思。
[a-z] s True 同样的如果要匹配所有的小写字母,直接用 [a-z] 就可以表示。
[A-Z] B True [A-Z] 就表示所有的大写字母。
[0-9a-fA-F] e True 可以匹配数字,大小写形式的 a~f,用来验证十六进制字符。

1、match方法

该方法用于指定文本模式和待匹配的字符串。第一个参数表示文本模式,第二个参数表示待匹配的字符串。

如果匹配成功,就可以调用group方法获取匹配成功的字符串。

import  re
m = re.match('hello','hello')
if m is not None:
    print(m.group())            #使用group方法
print(m.__class__.__name__)     #输出m的类名
m = re.match('hello','hello world')     #只要模式从字符串起始位置开始,也可以匹配成功
if m is not None:
    print(m.group())
print(m)
hello
Match
hello
<re.Match object; span=(0, 5), match='hello'>

2、search方法

搜索是正则表达式的另一类常用的应用场景。也就是从一段文本找到一个或多个与文本模式相匹配的字符串。

import re
m = re.match('python','I love python')
print(m)
m = re.search('python','I love python')
print(m)
s = '.ind'
m = re.match(s,'bind')
if m is not None:
    print(m.group())
print(m)
m = re.match(s,'bin')
print(m)
None
<re.Match object; span=(7, 13), match='python'>
bind
<re.Match object; span=(0, 4), match='bind'>
None

3、分组

如果一个模式字符串中有一对圆括号括起来的部分,那么这部分就会作为一组,可以通过group方法的参数获取指定的组匹配的字符串。在我们匹配一些需要抓取的信息时,往往会在一次模式匹配时,就获取很多想要的信息,那么此时,我们就需要将想要获取的信息用括号括起来,就可以形成一个列表,这个列表里面的内容就都是我们想要的内容。

import re
m = re.match('(\d{3})-(\d{4})-([a-z]{2})','123-4567-xy')
if m is not None:
    print(m.group())
    print(m.group(1))
    print(m.group(2))
    print(m.group(3))
    print(m.groups())
print("========================")
123-4567-xy
123
4567
xy
('123', '4567', 'xy')
=======================

4、findall和finditer方法

findall函数用于查询字符串中某个正则表达式模式全部的非重复出现情况,finditer方法与findall方法相似,只不过使用finditer方法需要进行迭代,这样更节省内存。

import re
s = '12-a-abc54-a-xyz---78-A-ytr'
#r是规避转义的字符
result = re.findall(r'\d\d-a-[a-z]{3}',s)
#匹配出了两个与该模式字符串相匹配的字符串
print(result)
['12-a-abc', '54-a-xyz']

5、sub和subn方法

sub函数与subn函数用于实现搜索和替换功能。这两个函数功能几乎完全一样,只不过sub函数返回替换后的结果,subn函数返回一个元组,元组的第一个元素是替换后的结果,第二个元素是替换的总数。

import re
#使用sub函数,第一个参数是模式字符串,第二个参数是要替换的字符串,第三个参数是被替换的字符串
result = re.sub('Mike','Bill','Mike is my son,I like Mike')
print(result)
result = re.subn('Mike','Bill','Mike is my son,I like Mike')
print(result)
#运行结果
Bill is my son,I like Bill
#元组
('Bill is my son,I like Bill', 2)

6、split方法

split函数用于根据正则表达式分隔字符串,split函数的第一个参数是模式字符串,第二个参数是带分隔的字符串。

import re
result = re.split(';','Bill;Mike;John')
print(result)
#运行结果
['Bill', 'Mike', 'John']
实战案例:抓取猫眼电影TOP100榜单(http://www.maoyan.com/)
import requests
#导入正则表达式
import re
#导入会话,维持状态
from requests import Session
session = Session()
class CatEyeMovie:
    def __init__(self):
        """
        个人爬取网站的一些经验:
        一开始我只使用了UA最为代理,后来发现爬取一段时间后,就不能在进行爬取了。
        然后我就导入了Host和Referer两个请求头作为参数,然后又爬取一段时间后又不能
        爬取了,然后我有采用了cookie值,并导入了session维持会话,后来保持稳定了,但
        我也不能完全保证后面不会出现问题,还有一个需要大家注意的点,就是我们最好将UA
        经常换一下,否则网站很容易判断你就是一个爬虫。
        """
        self.headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1',
            'Host':'www.maoyan.com',
            'Referer':'https: // www.maoyan.com / board / 6?timeStamp = 1705477546939 & channelId = 40011 & index = 1 & signKey = 53785d6920acbc1fad61a808070e6544 & sVersion = 1 & webdriver = false',
            'Cookie':'__mta = 208959021.1705475089718.1705477531026.1705477547761.23;uuid_n_v = v1;uuid = AEE07180B50611EE8FD01FDE53D00FC1F4728774816242469EDC18C661A68E3E;_csrf = bd11e59bd2541a5db1defecd0b98453acc792bc7b43e8c627d9f291922d330a5;Hm_lvt_703e94591e87be68cc8da0da7cbd0be2 = 1705475088;_lx_utm = utm_source % 3DBaidu % 26utm_medium % 3Dorganic;_lxsdk_cuid = 18d163ca06e88 - 09e6b05cd12e1e - 26001951 - 1bcab9 - 18d163ca06fc8;WEBDFPID = z7vx1480u69z54z2y8wxxw25u87w9wy681w834vxv2w9795839872754 - 2020837336064 - 1705477335287GSOGGSIfd79fef3d01d5e9aadc18ccd4d0c95079584;token = AgFrJIp1VufADHtEUTi0mp6KitQUBV_Ejob2I8Ux0OAvh6hc4y2_WhnCuFWgooIo_KncuV_jDf4ttQAAAABjHQAAZVmX7tI2iKUXgdLslHWY_dwRCQzD5i7IK_Ayog8 - 7acQiKH6CO0VVeeAwm4LSd1d;uid = 4274654873;uid.sig = vNE7mg6CHWQbb4imGsjuWSza8rs;lxsdk = AEE07180B50611EE8FD01FDE53D00FC1F4728774816242469EDC18C661A68E3E;__mta = 208959021.1705475089718.1705477312976.1705477544324.6;Hm_lpvt_703e94591e87be68cc8da0da7cbd0be2 = 1705477548;_lxsdk_s = 18d163ca06f - 4af - c1e - 68b % 7C % 7C62'
        }
    def get_html(self):
        #通过分析网站的URL,我们可以得出网站地址的规律
        for i in range(0,101,10):
            url = f'https://www.maoyan.com/board/4?timeStamp=1705475173402&channelId=40011&index=10&signKey=31588cad6150fc9509dd3f73c509fdac&sVersion=1&webdriver=false&offset={i}'
            response = session.get(url,headers=self.headers)
            #作判断,如果不是200,表示爬取不了
            if response.status_code == 200:
                html = response.text
                #print(html)
                self.re_html(html)
    def re_html(self,html):
       	#使用正则表达式获取电影名和主演
        re_act = '<p\sclass="name">.*?>(.*?)</a></p>\n.*?<p\s.*?>\n(.*?)\n.*?</p>'
        #通过正则表达式获取图片链接
        re_img_src = '<img\sdata-src="(.*?)".*?/>'
        lists = re.findall(re_act,html,re.S)
        img_lists = re.findall(re_img_src,html,re.S)
        for list,img_list in zip(lists,img_lists):
            title = list[0]
            #使用strip函数去掉字符串两头的空格
            lead_act = list[1].strip()
            print(title)
            print(lead_act)
            print(img_list)
            print("==================")


if __name__ == '__main__':
    cat = CatEyeMovie()
    cat.get_html()
我不是药神
主演:徐峥,周一围,王传君
https://p0.pipi.cn/mmdb/d2dad59253751bd236338fa5bd5a27c710413.jpg?imageView2/1/w/160/h/220
==================
肖申克的救赎
主演:蒂姆·罗宾斯,摩根·弗里曼,鲍勃·冈顿
https://p0.pipi.cn/mmdb/fb7386020fa51b0fafcf3e2e3a0bbe694d17d.jpg?imageView2/1/w/160/h/220
==================
海上钢琴师
主演:蒂姆·罗斯,比尔·努恩 ,克兰伦斯·威廉姆斯三世
https://p0.pipi.cn/mmdb/d2dad592c7e7e1d2365bf1b63cd25951b722b.jpg?imageView2/1/w/160/h/220
==================
绿皮书
主演:维果·莫腾森,马赫沙拉·阿里,琳达·卡德里尼
https://p0.pipi.cn/mmdb/d2dad59253751b230f21f0818a5bfd4d8679c.jpg?imageView2/1/w/160/h/220
==================
霸王别姬
主演:张国荣,张丰毅,巩俐
https://p0.pipi.cn/mmdb/fb7386beddd338537c8ea3bb80d25a9078b13.jpg?imageView2/1/w/160/h/220
==================
美丽人生
主演:罗伯托·贝尼尼,朱斯蒂诺·杜拉诺,赛尔乔·比尼·布斯特里克
https://p0.pipi.cn/mmdb/d2dad592c7e7e1d2367a3507befaed31a5903.jpg?imageView2/1/w/160/h/220
==================
这个杀手不太冷
主演:让·雷诺,加里·奥德曼,娜塔莉·波特曼
https://p0.pipi.cn/mmdb/d2dad592c7e7e13ba3ddd25677b4d70fc45fa.jpg?imageView2/1/w/160/h/220
==================
小偷家族
主演:中川雅也,安藤樱,松冈茉优
https://p0.pipi.cn/mmdb/d2dad5925372ffd7c387a9d01bddad81625c3.jpg?imageView2/1/w/160/h/220
==================
星际穿越
主演:马修·麦康纳,安妮·海瑟薇,杰西卡·查斯坦
https://p0.pipi.cn/mmdb/d2dad592b125bfc9fd300b8a46169f8008efb.jpg?imageView2/1/w/160/h/220
==================
怦然心动
主演:玛德琳·卡罗尔,卡兰·麦克奥利菲,艾丹·奎因
https://p0.pipi.cn/mmdb/d2dad592b122ff8d3387a93ccab6036f616c1.jpg?imageView2/1/w/160/h/220
==================
盗梦空间
主演:莱昂纳多·迪卡普里奥,渡边谦,约瑟夫·高登-莱维特
https://p0.pipi.cn/mmdb/fb7386510fa2ffd7c3e19bcb2e6ea4dc44460.jpg?imageView2/1/w/160/h/220
==================
泰坦尼克号
主演:莱昂纳多·迪卡普里奥,凯特·温丝莱特,比利·赞恩
https://p0.pipi.cn/mmdb/fb73869af2a51b339e537c802afb40db7a7fe.jpg?imageView2/1/w/160/h/220
==================
哪吒之魔童降世
主演:吕艳婷,囧森瑟夫,瀚墨
https://p0.pipi.cn/mmdb/d2dad592537923f0ee07acada3ac59b9f3ffb.jpg?imageView2/1/w/160/h/220
==================

二、lxml和xpath

1、lxml基础

lxml是python的一个解析库,用于解析HTML和XML,支持xpath解析方式。由于lxml底层是使用C语言编写的,所以解析效率非常高。但是lxml插件需要安转,在这里,我就不讲如何安装,大家可以用自己的方法去安装。

2、操作xml

lxml可以读取XML文件,也可以使用字符串形式的XML文档。读取XML文件时,需要使用parse函数,该函数需要传入XML文件名。如果要解析字符串形式的XML文档,需要使用fromstring函数,该函数的参数就是XML字符串。

<products>
    <product id = "0001">
        <name>手机</name>
        <price>2000</price>
    </product>
    <product id = "0002">
        <name>电脑</name>
        <price>8350</price>
    </product>
</products>
from lxml import etree
tree = etree.parse('product.xml')
print(type(tree))
#将tree重新转换为字符串形式的XML文档
print(str(etree.tostring(tree,encoding="utf-8"),'utf-8'))
#获得根结点对象
root = tree.getroot()
#输出根结点的名称
print(root.tag)
#获得根结点的所有子节点
children = root.getchildren()
for child in children:
    #获取子节点的ID属性值
    print(child.get('id'))
    #获取子节点的文本内容
    print(child[0].text)
    print(child[1].text)
#重写XML文档
root = etree.fromstring(
    '''
    <product>
            <product1 name="iphone"/>
            <product2 name="iPad"/>
    </product>
    '''
)
#注意:从这里root的值就开始改变了,不在是XML文件里的值,而是自己写的
print(root.tag)
children = root.getchildren()
for child in children:
    print(child.get('name'))
<class 'lxml.etree._ElementTree'>
<products>
    <product id="0001">
        <name>手机</name>
        <price>2000</price>
    </product>
    <product id="0002">
        <name>电脑</name>
        <price>8350</price>
    </product>
</products>
products
0001
手机
2000
0002
电脑
8350
product
iphone
iPad

3、操作HTML

使用lxml库解析HTML与解析XML类似,在这里,我通过代码能够让读者更加容易理解。

from lxml import etree
#创建lxml.etree.HTMLPareser对象
parser = etree.HTMLParser()
print(type(parser))
#读取并解析html文件
tree = etree.parse('product.html',parser)
#获取根结点
root = tree.getroot()
#将html文档转换为可读格式
result = etree.tostring(root,encoding='utf-8',pretty_print=True,method="html")
print(result,'utf-8')
#获取根结点名称
print(root.tag)
print(root.get('lang'))
#在这里相当于列表,head是列表里的第一个值,body是列表的第二个值
print(root[0][0].get('charset'))
print(root[0][1].text)
print(root[1][0].text)
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>这是一个HTML文件</title>
</head>
<body>
    <h1>解析库</h1>
</body>
</html>
<class 'lxml.etree.HTMLParser'>
b'<html lang="en">\r\n<head>\r\n    <meta charset="UTF-8">\r\n    <title>\xe8\xbf\x99\xe6\x98\xaf\xe4\xb8\x80\xe4\xb8\xaaHTML\xe6\x96\x87\xe4\xbb\xb6</title>\r\n</head>\r\n<body>\r\n    <h1>\xe8\xa7\xa3\xe6\x9e\x90\xe5\xba\x93</h1>\r\n</body>\r\n</html>\n' utf-8
html
en
UTF-8
这是一个HTML文件
解析库

4、Xpath

1) 基本语法使用

Xpath 使用路径表达式在文档中选取节点,下表列出了常用的表达式规则:

表达式 描述
node_name 选取此节点的所有子节点。
/ 绝对路径匹配,从根节点选取。
// 相对路径匹配,从所有节点中查找当前选择的节点,包括子节点和后代节点,其第一个 / 表示根节点。
. 选取当前节点。
.. 选取当前节点的父节点。
@ 选取属性值,通过属性值选取数据。常用元素属性有 @id 、@name、@type、@class、@tittle、@href。

2) xpath通配符

Xpath 表达式的通配符可以用来选取未知的节点元素,基本语法如下:

通配符 描述说明
* 匹配任意元素节点
@* 匹配任意属性节点
node() 匹配任意类型的节点

xpath其它知识点

1、可以使用“|”,表示多路径匹配,有时获取相同的位置格式,解析语法并不是完全一样的。

2、xpath还有很多内建函数,在这里我说一个经常用的就是“text属性”,后面进行实战案例时,会给大家详细介绍。

想要了解更多关于 Xpath 的知识可访问官方网站:https://www.w3.org/TR/xpath/

实战案例:抓取起点中文网小说信息()
#导入Excel表格
import xlwt
import requests
#导入随机函数,可以使用随机UA代理池
import random
from lxml import etree
#这里面是一些UA代理,可以随机切换UA,避免浏览器发现爬虫程序
from UA_info import ua_list
class StartSpider:
    #定义表头
    header = ['书名', '作者', '类型', '完成度', '介绍']
    #创建workbook对象
    book = xlwt.Workbook(encoding='utf-8')
    #添加一个名为novels的sheet
    sheet = book.add_sheet('novels')
    #为Excel表单添加表头
    for h in range(len(header)):
        sheet.write(0, h, header[h])
    def __init__(self):
        #计数器
        self.i = 1
        self.headers = {
            'User-Agent': random.choice(ua_list),
        }
    def get_html(self):
        for i in range(1,6):
            url = f'https://www.qidian.com/all/page{i}/'
            response = requests.get(url,headers=self.headers)
            if response.status_code == 200:
                html = response.text
                self.xml_html(html)
    def xml_html(self,html):
        xml = etree.HTML(html)
        #书名的解析语法
        title_list = xml.xpath('//*[@id="book-img-text"]/ul/li/div[2]/h2/a/text()')
        #作者名的解析语法
        author_list = xml.xpath('//*[@id="book-img-text"]/ul/li/div[2]/p[1]/a[1]/text()')
        #小说类型的解析语法
        type_list1 = xml.xpath('//ul[@class="all-img-list cf"]//p/a[2]/text()')
        type_list2 = xml.xpath('//ul[@class="all-img-list cf"]//p/a[3]/text()')
        #小说完成度解析语法
        complete_list = xml.xpath('///ul[@class="all-img-list cf"]//p[@class="author"]/span/text()')
        #小说简介
        introduce_list = xml.xpath('//ul[@class="all-img-list cf"]//p[@class="intro"]/text()')
        for title,author,type1,type2,complete,introduce in zip(title_list,author_list,type_list1,type_list2,complete_list,introduce_list):
            type = type1+'·'+type2
            print(title)
            print(author)
            print("========================")
            self.save_data(title,author,type,complete,introduce)
    #定义保存数据的函数
    def save_data(self,title,author,type,complete,introduce):
        self.sheet.write(self.i,0,title)
        self.sheet.write(self.i,1,author)
        self.sheet.write(self.i,2,type)
        self.sheet.write(self.i,3,complete)
        self.sheet.write(self.i,4,introduce)
        self.i += 1
if __name__ == '__main__':
    start = StartSpider()
    start.get_html()
    #将内存中的Excel数据保存为该文件
    StartSpider.book.save('novels.xls')
灵境行者
卖报小郎君
========================
赤心巡天
情何以甚
========================
宿命之环
爱潜水的乌贼
========================
都重生了谁谈恋爱啊
错哪儿了
========================
深海余烬
远瞳
========================
谁让他修仙的!
最白的乌鸦
========================
这游戏也太真实了
晨星LL
========================
万古神帝
飞天鱼
========================
逼我重生是吧
幼儿园一把手
========================
玄鉴仙族
季越人
========================

1705486991290

以上是写入Excel表格中的数据!

标签:匹配,self,list,re,html,print,解析
From: https://www.cnblogs.com/wjx-2005-07-01/p/17970719

相关文章

  • 收件信息解析
    privateSmartAnalysisResultSmartAnalysisAddress(List<tm_master_city_PO>regions,stringmemo){varresult=newSmartAnalysisResult();if(string.IsNullOrEmpty(memo))returnnull;varareas=regions.Where(t=>t.RegionType==&quo......
  • 白话文解析LiteFlow的理念是什么?什么时候用该怎么用?干货满满
    官网:https://liteflow.cc/Gitee:https://gitee.com/dromara/liteFlowGithub:https://github.com/dromara/liteflowLiteFlow一个现代化的开源规则引擎框架,以下文中简称LF。前言时常在社区里看到有的小伙伴在那提问:LF在一个流程中如何暂停,等待操作员完成后,进行下一步该怎么做?LF......
  • 解析HTTP响应的状态码和头部信息
    HTTP响应是客户端与服务器之间通信的重要部分。它包含了服务器对客户端请求的回应,以及与该响应相关的各种信息。在HTTP响应中,有两个关键部分:状态码和头部信息。状态码状态码是HTTP响应的第一部分,它是一个三位数字的代码,用于表示请求的处理结果。状态码提供了一种标准的方法来告诉客......
  • Spring Boot 自动配置机制全解析
    本篇博文旨在全面剖析SpringBoot的自动配置原理,为开发者提供深入理解其背后机制的视角。SpringBoot自动配置通过智能地推断所需配置,极大地简化了开发过程,优化了开发体验。1.SpringBoot自动配置的核心:@SpringBootApplicationSpringBoot应用的入口通常标注有@SpringBootAp......
  • 构建高效数据生态:数据库、数据仓库、数据湖、大数据平台与数据中台解析_光点科技
    在数字化的浪潮中,一套高效的数据管理系统是企业竞争力的核心。从传统的数据库到现代的数据中台,每一种技术都在数据的旅程中扮演着关键角色。本文将深入探讨数据库、数据仓库、数据湖、大数据平台以及数据中台的功能和价值,帮助您构建一个符合自身业务需求的高效数据生态系统。数据库......
  • 解析 terminating with uncaught exception of type std::bad_cast: std::bad_cast
    解析"terminatingwithuncaughtexceptionoftypestd::bad_cast:std::bad_cast"简介在C++编程中,我们有时会遇到异常(exception),这些异常可能是由于程序运行时出现意外情况而引发的错误。其中,"terminatingwithuncaughtexceptionoftypestd::bad_cast:std::bad_cast"是一种......
  • 【深入挖掘Java技术】「源码原理体系」盲点问题解析之HashMap工作原理全揭秘(上)
    知识盲点概念介绍HashMap是基于Map接口构建的数据结构,它以键值对的形式存储元素,允许键和值都为null。由于键的唯一性,HashMap中只能有一个键为null。HashMap的特点是元素的无序性和不重复性。注意,HashMap并不是线程安全的。在多线程环境下,如果不进行适当的同步处理,可能会导致数据不......
  • Spring事务传播机制解析
    确保数据一致性的关键在Java的Spring框架中,事务管理是保证应用数据一致性和可靠性的关键。Spring提供了灵活的事务传播机制,它定义了事务边界,以及在嵌套方法调用时如何处理事务。本文旨在深入探讨Spring的事务传播行为,帮助开发者更好地理解和运用这一重要特性。事务传播机制简介......
  • VUE框架实现符合Vue3语法格式的页面与各个配置项解析------VUE框架
    <template><HelloWorld></HelloWorld><h1>{{name}}</h1><h1>{{age}}</h1><h1>{{a}}</h1><h1>{{b}}</h1><button@click="sayHello">按一下</butto......
  • Elasticsearch内核解析 - 数据模型篇【转载】
    原文链接Elasticsearch是一个实时的分布式搜索和分析引擎,它可以帮助我们用很快的速度去处理大规模数据,可以用于全文检索、结构化检索、推荐、分析以及统计聚合等多种场景。Elasticsearch是一个建立在全文搜索引擎库ApacheLucene基础上的分布式搜索引擎,Lucene最早的版本是2......