Python 网络爬虫-正则表达式、BeautifulSoup、lxml三种提取方法
来源:互联网 发布:报刊制作软件coreldraw 编辑:程序博客网 时间:2024/06/05 11:52
正则表达式
1. Python Re模块
1. 数量词的贪婪模式与非贪婪模式
正则表达式通常用于在文本中查找匹配的字符串。Python里数量词默认是贪婪的(在少数语言里也可能是默认非贪婪),总是尝试匹配尽可能多的字符;非贪婪的则相反,总是尝试匹配尽可能少的字符。例如:正则表达式”ab*”如果用于查找”abbbc”,将找到”abbb”。而如果使用非贪婪的数量词”ab*?”,将找到”a”。
注:我们一般使用非贪婪模式来提取。
2. 反斜杠问题
与大多数编程语言相同,正则表达式里使用”\”作为转义字符,这就可能造成反斜杠困扰。假如你需要匹配文本中的字符”\”,那么使用编程语言表示的正则表达式里将需要4个反斜杠”\\”:前两个和后两个分别用于在编程语言里转义成反斜杠,转换成两个反斜杠后再在正则表达式里转义成一个反斜杠。
Python里的原生字符串很好地解决了这个问题,这个例子中的正则表达式可以使用r”\”表示。同样,匹配一个数字的”\d”可以写成r”\d”。有了原生字符串,妈妈也不用担心是不是漏写了反斜杠,写出来的表达式也更直观。
Python 自带了re模块,它提供了对正则表达式的支持。主要用到的方法列举如下:
Pattern : 可以理解为一个匹配模式;
Pattern = re.compile(r’hello’)
通过compile方法编译生成一个pattern对象
其中flag是匹配模式,取值可以使用按位或运算‘|’表示同时生效,比如re.I|re.M
- re.match(pattern,string[,flags])
作用:从string的开头开始,尝试匹配pattern,一直向后匹配,如果遇到无法匹配的字符,立即返回None,如果匹配未结束已经到达string的末尾,也会返回None。两个结果均表示匹配失败,否则匹配pattern成功,同时匹配终止,不再对string向后匹配。下面我们通过一个例子理解一下 re.search(pattern,string[,flags])
search方法与match方法极其类似,区别在于match()函数只检测re是不是在string的开始位置匹配,search()会扫描整个string查找匹配,match()只有在0位置匹配成功的话才有返回,如果不是开始位置匹配成功的话,match()就返回None。同样,search方法的返回对象同样match()返回对象的方法和属性。我们用一个例子感受一下re.split(pattern,string[,maxsplit])
按照能够匹配的子串将string分割后返回列表。maxsplit用于指定最大分割次数,不指定将全部分割。我们通过下面的例子感受一下。re.findall(pattern,string[,flags])
搜索string,以列表形式返回全部能匹配的字串。我们通过这个例子来感受一下- re.finditer(pattern,string[,flags])
搜索string,返回一个顺序访问每一个匹配结果(Match对象)的迭代器。我们通过下面的例子来感受一下 - re.sub(pattern,repl,string[,count])
使用repl替换string中每一个匹配的子串后返回替换后的字符串。
当repl是一个字符串时,可以使用\id或\g、\g引用分组,但不能使用编号0。
当repl是一个方法时,这个方法应当只接受一个参数(Match对象),并返回一个字符串用于替换(返回的字符串中不能再引用分组)。
count用于指定最多替换次数,不指定时全部替换。 - re.subn(pattern,repl,string[,count])
2. Python 提取网站的正则表达式规则
1).*? 是一个固定的搭配,.和*代表可以匹配任意无限多个字符,加上?表示使用非贪婪模式进行匹配,也就是我们会尽可能短地做匹配,以后我们还会大量用到 .*? 的搭配。
2)(.*?)代表一个分组,在这个正则表达式中我们匹配了五个分组,在后面的遍历item中,item[0]就代表第一个(.*?)所指代的内容,item[1]就代表第二个(.*?)所指代的内容,以此类推。
正则表达式的语法规则
该图片取自网上
实例代码
# _*_ encoding:utf8 _*_import repattern = re.compile(r'<a.*?href=.*?<\/a>',re.I|re.S|re.M)#构建一个patternpattern1 = re.compile(r'<td>.*?</td>',re.I|re.S|re.M)res_url = r"(?<=href=\").*?(?=\")|(?<=href=\').*?(?=\')"pattern2 = re.compile(res_url)content = """<td> <a href="https://www.baidu.com/articles/zj.html" title="浙江省">浙江省主题介绍</a> <a href='https://www.baidu.com//articles/gz.html' title="贵州省">贵州省主题介绍</a> </td> """result = re.findall(pattern2,content) #找出所有满足正则表达式的内容for i in result: print i
BeautifulSoup
安装
pip install beautifulsoup4
内容
2.速度适中 Python 2.7.3 or 3.2.2)前 的版本中文档容错能力差 lxml HTML解析器 BeautifulSoup(marup,’lxml’) 1.速度快
2.容错率高 pip install lxml lxml XML解析器 BeautifulSoup(marup,[‘lxml’,’xml’])
BeautifulSoup(marup,’xml’) 1.速度快
2.唯一支持XML的解析器 pip install lxml html5lib解析器 BeautifulSoup(marup,’html5lib’) 1.容错率最好
2.以浏览器的方式解析文档
3.生成HTML5格式的文档 速度慢
实例代码
# _*_ encoding:utf8 _*_import urllib2import urllibfrom bs4 import BeautifulSoupimport reurl = "http://www.baidu.com"user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'headers = { 'User-Agent' : user_agent }try: request = urllib2.Request(url,headers=headers) #创建一个请求对象 response = urllib2.urlopen(request) #生成一个响应对象 content = response.read() #读取html的内容 html = BeautifulSoup(content,'html.parser') #以html.parser HTML解析器 格式化为BeautifulSoup for t in html.find_all('a',limit=20): print t['href'] #取出每一条中的href属性值 for t in html.find_all('a',limit=20): print t.text #取出标签a的内容 for t in html.find_all('a',class_='bri',limit=20): #遇到class这种与Python calss类冲突的属性在后面加下划线 class_ print t #取出标签a的内容for t in html.find_all('a',wdfield="word",limit=20): print t #取出标签a的内容for t in html.find_all(attrs={"wdfield":"word"}): #满足属性所有标签 print t #取出标签a的内容 except urllib2.URLError as e: pass
lxml
安装
pip install lxml
内容
利用pip安装就可以,如果遇到安装失败就多装几次。
实例代码
# _*_ encoding:utf8 _*_import reimport urllibimport urllib2from lxml import etreecontent = """<html> <head> <meta name="content-type" content="text/html; charset=utf-8" /> <title>友情链接查询 - 站长工具</title> <!-- uRj0Ak8VLEPhjWhg3m9z4EjXJwc --> <meta name="Keywords" content="友情链接查询" /> <meta name="Description" content="友情链接查询" /> </head> <body> <h1 class="heading">Top News</h1> <p style="font-size: 200%">World News only on this page</p> Ah, and here's some more text, by the way. <p>... and this is a parsed fragment ...</p> <a href="http://www.cydf.org.cn/" rel="nofollow" target="_blank1">青少年发展基金会</a> <a href="http://www.4399.com/flash/32979.htm" target="_blank">洛克王国</a> <a href="http://www.4399.com/flash/35538.htm" target="_blank">奥拉星</a> <a href="http://game.3533.com/game/" target="_blank">手机游戏</a> <a href="http://game.3533.com/tupian/" target="_blank">手机壁纸</a> <a href="http://www.4399.com/" target="_blank">4399小游戏</a> <a href="http://www.91wan.com/" target="_blank">91wan游戏</a> </body></html>"""############读取网址来获取html内容#url = "http://www.baidu.com/"#url请求路径#user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'#headers = { 'User-Agent' : user_agent }#request = urllib2.Request(url,headers=headers)#request实例化一个请求对象#response = urllib2.urlopen(request)#response实例化一个响应对象#content = response.read().decode('utf-8')#############try: html = etree.HTML(content.decode('utf-8')) # html = etree.parse('hello.html') #利用parse来读取文件 #转化为lxml格式 result1 = html.xpath(u'//a') # //a查询节点为a 不管位置在哪里 for res in result1: print etree.tostring(res) # 打印查询的结果 result2 = html.xpath(u'/html/body/h1') for res in result2: print etree.tostring(res) result3 = html.xpath(u'//*') # //* 所有的内容 for res in result3: print etree.tostring(res) result4 = html.xpath(u"//a[@target='_blank1']")#查询所有的<a>标签中target='_blank1'的内容 for res in result4: print etree.tostring(res) result5 = html.xpath(u"//a[last()]")#查询所有的<a>标签中最后一个的内容 for res in result5: print etree.tostring(res) result6 = html.xpath(u"//a")# for res in result6: print res.text #打印标签包含的内容 result7 = html.xpath(u'//a[@target="_blank1"]/@href') #找出标签a中属性为href的内容 for res in result7: print res result7 = html.xpath(u'//*[@target="_blank"]/@href') #找出标签属性为target="_blank"中href的内容 for res in result7: print res result8 = html.xpath(u'//a|//h1') #找出所有的标签a或者前边h1 for res in result8: print etree.tostring(res) result9 = html.xpath(u'//*[@*]') #找出所有带有属性的标签 for res in result9: print etree.tostring(res)except urllib2.URLError as e: print e
结语
通过lxml获取信息的关键在于xpath的运用,多练习xpath的路径的写法,自然能熟能生巧!
正则表达式效率是最高的,缺点在于表达式比较繁琐!
lxml的效率比beautifulsoup要高很多,而且比beautifulsoup更加的灵活!
我也是刚学,只是当过笔记记下来,希望能帮到需要的人,有错误的地方还望指正!
- Python 网络爬虫-正则表达式、BeautifulSoup、lxml三种提取方法
- python网络爬虫-正则表达式和BeautifulSoup
- Python网络爬虫与信息提取(三) 正则表达式
- python爬虫里信息提取的核心方法: Beautifulsoup、Xpath和正则表达式
- Python爬虫系列之----Scrapy(五)网页提取的三种方式(正则,Beautiful Soup,Lxml)
- MOOC-Python网络爬虫与信息提取-第二周 BeautifulSoup库入门与信息提取方法
- Python爬虫---数据的提取---正则/Xpath/beautifulsoup--正则
- Python网络爬虫与信息提取(二) BeautifulSoup库
- python网络爬虫学习(三)正则表达式的使用之re.match方法
- Python网络爬虫-正则表达式
- Python-网络爬虫之BeautifulSoup
- python网络爬虫-使用BeautifulSoup
- Python网络爬虫与信息提取-Day11-正则表达式的概念和语法
- Python网络爬虫与信息提取-Day12-Re(正则表达式)库入门
- Python爬虫---提取数据(2)--beautifulsoup
- Python--正则表达式/单线程网络爬虫
- Python网络爬虫(3)正则表达式
- python之正则表达式以及网络爬虫
- JavaMail在SSM框架中的应用
- 找出数组中的一个元素出现次数大于数组长度的一半的元素,若不存在返回0
- HTTP 请求方式: GET和POST的比较
- Mybatis逆向工程教程
- MFC实现Spin控件和Edit控件合用
- Python 网络爬虫-正则表达式、BeautifulSoup、lxml三种提取方法
- nodejs 环境搭建
- 两个经纬度之间的距离计算
- yum搭建lnmp环境(CentOS6.4)
- hdu1160 LIS
- Oracle 11.2.0.4.0 RAC下DRM导致单节点宕机
- 数论
- Android下的配置管理之道之gerrit代码服务器搭建
- Longest Ordered Subsequence(dp)