Requests库
以管理员身份运行cmd,输入pip install requests
,等待安装。安装成功后,可进入IDLE使用requests库:
>>>import requests
>>>r=requests.get("http://www.baidu.com")
>>> r.status_code #检测这个请求的状态码
200
>>>r.encoding = 'utf-8'
>>>r.text
'<!DOCTYPE html>\r\n<!--STATUS OK--><html> <head><meta http-equiv=content-type content=text/html;charset=utf-8><meta http-equiv=X-UA-Compatible content=IE=Edge><meta content=always name=referrer><link rel=stylesheet type=text/css href=http://s1.bdstatic.com/r/www/cache/bdorz/baidu.min.css><title>百度一下,你就知道</title></head> <body link=#0000cc> <div id=wrapper> <div id=head> <div class=head_wrapper> <div class=s_form> <div class=s_form_wrapper> <div id=lg> <img hidefocus=true src=//www.baidu.com/img/bd_logo1.png width=270 height=129> </div> <form id=form name=f action=//www.baidu.com/s class=fm> <input type=hidden name=bdorz_come value=1> <input type=hidden name=ie value=utf-8> <input type=hidden name=f value=8> <input type=hidden name=rsv_bp value=1> <input type=hidden name=rsv_idx value=1> <input type=hidden name=tn value=baidu><span class="bg s_ipt_wr"><input id=kw name=wd class=s_ipt value maxlength=255 autocomplete=off autofocus></span><span class="bg s_btn_wr"><input type=submit id=su value=百度一下 class="bg s_btn"></span> </form> </div> </div> <div id=u1> <a href=http://news.baidu.com name=tj_trnews class=mnav>新闻</a> <a href=http://www.hao123.com name=tj_trhao123 class=mnav>hao123</a> <a href=http://map.baidu.com name=tj_trmap class=mnav>地图</a> <a href=http://v.baidu.com name=tj_trvideo class=mnav>视频</a> <a href=http://tieba.baidu.com name=tj_trtieba class=mnav>贴吧</a> <noscript> <a href=http://www.baidu.com/bdorz/login.gif?login&tpl=mn&u=http%3A%2F%2Fwww.baidu.com%2f%3fbdorz_come%3d1 name=tj_login class=lb>登录</a> </noscript> <script>document.write(\'<a href="http://www.baidu.com/bdorz/login.gif?login&tpl=mn&u=\'+ encodeURIComponent(window.location.href+ (window.location.search === "" ? "?" : "&")+ "bdorz_come=1")+ \'" name="tj_login" class="lb">登录</a>\');</script> <a href=//www.baidu.com/more/ name=tj_briicon class=bri style="display: block;">更多产品</a> </div> </div> </div> <div id=ftCon> <div id=ftConw> <p id=lh> <a href=http://home.baidu.com>关于百度</a> <a href=http://ir.baidu.com>About Baidu</a> </p> <p id=cp>©2017 Baidu <a href=http://www.baidu.com/duty/>使用百度前必读</a> <a href=http://jianyi.baidu.com/ class=cp-feedback>意见反馈</a> 京ICP证030173号 <img src=//www.baidu.com/img/gs.gif> </p> </div> </div> </div> </body> </html>\r\n'
Requests库的7个主要使用方法
方法 | 说明 |
---|---|
requests.requests() | 构造一个请求,支撑以下各方法的基础方法 |
requests.get() | 获取HTML网页的主要方法,对应于HTTP的GET |
requests.head() | 获取HTTP网页头信息的主要方法,对应于HTTP的HEAD |
requests.post() | 向HTML网页提交POST请求的方法,对应于HTTP的POST |
requests.put() | 向HTML网页提交PUT请求的方法,对应于HTTP的PUT |
requests.patch() | 向HTML网页提交局部请求,对应于HTTP的PATCH |
requests.delete() | 向HTML页面提交删除请求,对应于HTTP的DELETE |
实际上requests库只有一个方法,那就是requests()方法,其他6个方法都是通过requests()方法进行封装的
get()方法
requests.get(url,params=None,**kwargs)
`r = requests.get(url)
构造一个向服务器请求资源的Requests对象
返回一个包含服务器资源的Response对象
url:拟获取页面的url链接
params:url中的额外参数,字典或字节流格式,可选
**kwargs:12个控制访问的参数
>>> import requests
>>> r = requests.get("http://www.baidu.com")
>>> print(r.status_code)
200
>>> type(r) #返回r的类型:一个类
<class 'requests.models.Response'>
>>> r.headers #返回get请求页面的头部信息
{'Cache-Control': 'private, no-cache, no-store, proxy-revalidate, no-transform', 'Connection': 'Keep-Alive', 'Content-Encoding': 'gzip', 'Content-Type': 'text/html', 'Date': 'Mon, 05 Aug 2019 12:13:55 GMT', 'Last-Modified': 'Mon, 23 Jan 2017 13:27:32 GMT', 'Pragma': 'no-cache', 'Server': 'bfe/1.0.8.18', 'Set-Cookie': 'BDORZ=27315; max-age=86400; domain=.baidu.com; path=/', 'Transfer-Encoding': 'chunked'}
>>>
Response对象的属性
属性 | 说明 |
---|---|
r.status_code | HTTP请求的返回状态,200-成功,404-失败 |
r.text | HTTP响应内容的字符串形式,即url对应的页面内容 |
r.encoding | 从HTTP header中猜测的响应内容编码方式 |
r.apparent_encoding | 从内容中分析出的响应内容编码方式 |
r.content | HTTP响应的二进制形式 |
r.encoding:如果header中不存在charset,则认为编码ISO-8859-1
r.text根据r.encoding显示网页内容
r.apparent_encoding:根据网页内容分析出编码方式,可以看作是r.encoding的备选
爬去网页的通用代码框架
异常 | 说明 |
---|---|
requests.ConnectionError | 网络连接错误异常 |
requests.HTTPError | HTTP错误异常 |
requests.URLrequired | URL缺失异常 |
requests.TooManyRedirects | 超过最大重定向次数,产生重定向异常 |
requests.ConnectTimeout | 连接远程服务器超时异常 |
requests.Timeout | 请求URL超时 |
r.raise_for_statis() | 如果不是200,产生异常requests.HTTPError |
通用代码框架:
import requests
def getHTMLText(url):
try:
r = requests.get(url, timeout=30)
r.raise_for_status()
r.encoding = r.apparent_encoding
return r.text
except:
return "产生异常"
if __name__ == "__main__":
url = "http://www.baidu.com"
print(getHTMLText(url))
HTTP协议
HTTP,Hypertext Transfer Protocol,超文本传输协议
HTTP是一个基于“请求与响应”模式的、无状态的应用层协议
HTTP协议采用URL作为定位网络资源的标识,URL格式:
http://host[:port][path]
host:合法的Internet主机域名或IP地址
port:端口号,缺省端口为80
path:请求资源路径
HTTP协议对资源的操作
方法 | 说明 |
---|---|
get | 请求获取url位置的资源 |
head | 请求获取url位置资源的响应信息报告,即获得该资源的头部信息 |
post | 请求向url位置的资源后附加新的数据 |
put | 请求向url位置存储一个资源,覆盖原url位置的资源 |
patch | 请求局部更新url位置的资源,即改变部分内容 |
delete | 请求删除url位置的资源 |
requests.requetst(methon, url, **kwargs)
· method:请求方式
· url:拟获取页面的url链接
· **kwargs:控制访问参数,共13个
· method:
r = requests.requetst('GET', url, **kwargs)
r = requests.requetst('HEAD', url, **kwargs)
......
· **kwargs:控制访问的参数,均为可选项
params:字典或字节序列,作为参数增加到url中
data:字典、字节序列或文件对象,作为Request的内容
json:json格式的数据,作为Request的内容
headers:字典,HTTP定制头
cookies:字典或CookieJar,Request中的cookie
auth:元组,支持HTTP认证功能
files:字典类型,传输文件
timeout:设定超时时间,秒为单位
proxies:字典类型,设定访问代理服务器,可以增加登录认证
allow_redirects:
stream:
verify:
cert:本地SSL证书路径
网络爬虫
网络爬虫的尺寸
小规模,数据量小,爬取速度不敏感:Requests库
中规模,数据规模较大,爬取速度敏感:Scrapy库
大规模,搜索引擎,爬取速度关键:定制开发
网络爬虫的限制
· 来源审查:判断User-Agent进行限制
检查来访HTTP协议头的User-Agent域,只响应浏览器友好爬虫的访问
· 发布公告:Robots协议
Robots协议
Robos Exclusion Standard,网络爬虫排除标准
作用:网站告知网络爬虫哪些可以抓取,哪些不行
形式:在网站根目录下的robots.text文件
案例:京东的Robots协议
User-agent: * #对于任意来源网络爬虫,定义为User-agent
Disallow: /?* #任何爬虫不允许访问以?开头的路径
Disallow: /pop/*.html #
Disallow: /pinpai/*.html?*
#一下四个网络爬虫不允许爬取jd的任何资源
User-agent: EtaoSpider
Disallow: /
User-agent: HuihuiSpider
Disallow: /
User-agent: GwdangSpider
Disallow: /
User-agent: WochachaSpider
Disallow: /
注意:#注释,*代表所有,/代表根目录
Requests库网络爬虫5个案例
1.jd商品页面的爬取
import requests
url = "https://item.jd.com/2967929.html"
try:
r = requests.get(url)
r.raise_for_status()
r.encoding = r.apparent_encoding
print(r.text[:1000])
except:
print("爬取失败")
※:一个普通基本的爬取
2.亚马逊商品页面的爬取
import requests
url = "https://www.amazon.cn/gp/product/B01M8L5Z3Y"
try:
kv = {'user-agent':'Mozilla/5.0'}
r = requests.get(url,headers=kv)
r.raise_for_status()
r.encoding = r.apparent_encoding
print(r.text[1000:2000])
except:
print("爬取失败")
※:如果不进行headers的修改,这次爬取会以python-requests进行请求,而amazon会拒绝这种请求;改变headers字段,模拟成浏览器对amazon服务器发出请求。
3.网络搜索关键词提交
import requests
keyword = "Python"
try:
kv = {'wd':keyword}
r = requests.get("http://www.baidu.com/s",params=kv)
print(r.request.url)
r.raise_for_status()
print(len(r.text))
except:
print("爬取失败")
※:params:关键词
4.网络图片的爬取和存储
import requests
import os
url = "http://img0.dili360.com/ga/M02/33/7C/wKgBzFSbqQyAJVAuAARB8cSWH_w695.tub.jpg"
root = "D://pics//"
path = root + url.split('/')[-1] #根目录,加上以/分割的url的最后一个
try:
if not os.path.exists(root): #如果路径不存在,则创建路径
os.mkdir(root)
if not os.path.exists(path): #如果已存在,则爬取图片地址
r = requests.get(url)
with open(path, 'wb') as f:
f.write(r.content)
f.close()
print("文件保存成功")
else:
print("文件已存在")
except:
print("爬取失败")
BeautifulSoup库
Beautiful Soup的理解
<html> 标签树
<body>
<p class="title"> ... </p>
</body>
</html>
Beautiful Soup库是解析、遍历、维护“标签书”的功能库
基本元素 | 说明 |
---|---|
Tag | 标签,用<>和</>标明开头和结尾 |
Name | 标签的名字,<p>...</p>的名字是'p',格式:<tag>.name |
Attributes | 标签的属性,字典形式组织,格式:<tag>.attrs |
NavigableString | 标签内非属性字符串,<>...</>中字符串,格式:<tag>.string |
Comment | 标签内字符串的注释部分,一种特殊的Comment类型 |
引用方式:
from bs4 import BeautifulSoup
import bs4
基于bs4库的HTML内容遍历方法
标签树的下行遍历
属性 | 说明 |
---|---|
.contents | 子节点列表,将<tag>所有儿子节点存入列表 |
.children | 子节点的迭代类型,与.contents类似,用于循环遍历儿子节点 |
.descendants | 子孙节点的迭代类型,包含所有子孙节点,用于循环遍历 |
标签树的上行遍历
属性 | 说明 |
---|---|
.parent | 节点的父亲标签 |
.parents | 节点先辈标签的迭代类型,用于循环遍历先辈类型 |
标签树的平行遍历
属性 | 说明 |
---|---|
.next_sibling | 返回按照HTML文本顺序的下一个平行节点标签 |
.previous_sibling | 返回按照HTML文本顺序的上一个平行节点标签 |
.next_siblings | 迭代类型,返回后续所有 |
.previous_siblings | 迭代类型,返回之前所有 |
所有平行遍历需要发生在同一个父节点下
基于bs4库的HTML格式输出
如何让<html>内容更加友好的显示?
prettify()方法:为html文本的内容和标签增加换行符
>>>print(soup.a.prettify())
<a class="py1" href="http://www.icourse163.org/course/BIT-268001" id="link1">
Basic Python
</a>
信息组织与提取方法
信息标记的三种形式
XML:xXtensible Markup Language
<name> ... </name>
<name />
<! - - - - >
XML实例:
<person>
<firstname>An</firstname>
<lastname>Ran</lastname>
<address>
<streetAddr>沙河口区</streetAddr>
<city>大连市</city>
<zipcode>116021</zipcode>
</address>
<prof>Computer System</prof>Security</city>
</persom>
JSON:JavaScript Object Notation
"key" : "value"
"key" : ["value1" , "value2"]
"key" : {"subkey" : "subvalue"}
JSON实例:
{
"firstname" : "An" ,
"lastname" : "Ran" ,
"address" : {
"streetAddr" : "沙河口区" ,
"city" : "大连市" ,
"zipcode" : "116021" ,
} ,
"prof" : ["Computer System" , "Security"]
}
YAML:YAML Ain't Markup Language
key : value
key : #Comment
-value1
-value2
key :
subkey : subvalue
firstname : An
lastname : Ran
address :
streetAddr : 沙河口区
city : 大连市
zipcode : 116021
prof :
-Computer System
-Security
比较
类型 | 说明 |
---|---|
XML | 扩展性好,但繁琐。Internet上的信息交互与传递。 |
JSON | 信息有类型,适合程序处理(js),较XML简洁。移动应用云端和节点的信息通信,无注释。 |
YAML | 信息无类型,文本信息比例高,可读性好。各类系统的配置文件,有注释易读。 |
信息提取的一般方法
方法一:完整解析信息的标记形式,再提取关键信息。
XML JSON YAML
需要解析标记器 例如:bs4库的标签遍历树
优点:信息解析准确
缺点:提取过程繁琐,速度慢
方法二:无视标记形式,直接搜索关键信息。
搜索
对信息的文本查找函数即可。
优点:提取过程简洁,速度较快。
缺点:提取结果准确性与信息内容相关。
融合方法:结合形式解析与搜索方法,提取关键信息。
XML JSON YAML 搜索
需要标记解析器及文本查找函数。
实例:提取HTML中所有URL链接
思路:1)搜索到所有<a>标签
2)解析<a>标签格式,提取href后的链接内容
>>> soup = BeautifulSoup(demo,"html.parser")
>>> for link in soup.find_all('a'):
print(link.get('href'))
http://www.icourse163.org/course/BIT-268001
http://www.icourse163.org/course/BIT-1001870001
基于bs4库的HTML内容查找方法
返回一个列表类型, 存储查找的结果
<>.find_all(name,attrs,recursive,string,**kwargs)
· name:对标签名称的检索字符串
>>> soup.find_all('a')
[<a class="py1" href="http://www.icourse163.org/course/BIT-268001" id="link1">Basic Python</a>, <a class="py2" href="http://www.icourse163.org/course/BIT-1001870001" id="link2">Advanced Python</a>]
>>> soup.find_all(['a','b'])
[<b>The demo python introduces several python courses.</b>, <a class="py1" href="http://www.icourse163.org/course/BIT-268001" id="link1">Basic Python</a>, <a class="py2" href="http://www.icourse163.org/course/BIT-1001870001" id="link2">Advanced Python</a>]
>>>
>>> for tag in soup.find_all(True):
print(tag.name)
html
head
title
body
p
b
p
a
a
>>> for tag in soup.find_all(re.compile('b')):
print(tag.name)
body
b
attrs:对标签属性值的检索字符串,可标注属性检索
>>> soup.find_all('p','course') #查找p标签中,含有course属性值的标签
[<p class="course">Python is a wonderful general-purpose programming language. You can learn Python from novice to professional by tracking the following courses:
<a class="py1" href="http://www.icourse163.org/course/BIT-268001" id="link1">Basic Python</a> and <a class="py2" href="http://www.icourse163.org/course/BIT-1001870001" id="link2">Advanced Python</a>.</p>]
>>> soup.find_all(id='link1') #查找id等于'link1'的标签
[<a class="py1" href="http://www.icourse163.org/course/BIT-268001" id="link1">Basic Python</a>]
recursive:是否对子孙全部检索,默认True
True:搜索根节点的儿子节点之后的节点
False:只搜索到根节点的儿子节点,停止
>>> soup.find_all('a',recursive=False)
[]
#说明从soup的根节点开始,即根节点的儿子节点无a标签,a标签在根节点的孙子节点之后
string:<>...</>中字符串区域的检索字符串
>>> soup.find_all(string = re.compile("python"))
['This is a python demo page', 'The demo python introduces several python courses.']
<tag>(..) 等价于 <tag>.find_all(..)
soup(..) 等价于 soup.find_all(..)
扩展方法
方法 | 说明 |
---|---|
<>.find() | 搜索且只返回一个结果,同.find_all()参数 |
<>.find_parents() | 在先辈节点中搜索,返回列表类型,同.find_all()参数 |
<>.find_parent() | 在先辈节点中返回一个结果,同.find()参数 |
<>.find_next_siblings() | 在后续平行节点中搜索,返回列表类型,同.find_all()参数 |
<>.find_next_sibling() | 在后续平行节点中返回一个结果,同.find()参数 |
<>.find_previous)siblings() | 在前序平行节点中搜索,返回列表类型,同.find_all()参数 |
<>.find_previous_sibling() | 在前序平行节点中返回一个结果,同.find()参数 |
Re库:正则表达式
regular expression
正则表达式常用操作符
操作符 | 说明 | 实例 |
---|---|---|
. | 表示任何单个字符 | |
[ ] | 字符集,对单个字符给出取值范围 | [abc]表示a、b、c,[a-z]表示a到z单个字符 |
[^ ] | 非字符集,对单个字符给出排除范围 | [^abc]表示非a或b或的单个字符 |
* | 前一个字符0次或无限次扩展 | abc*表示ab、abc、abcc、abccc等 |
+ | 前一个字符1次或无限次扩展 | abc+表示abc、abcc、abccc等 |
? | 前一个字符0次或1次扩展 | abc?表示ab、abc |
丨 | 左右表达式任意一个 | abc丨def表示abc、def |
{m} | 扩展前一个字符m次 | ab{2}c表示abbc |
{m,n} | 扩展前一个字符m至n次(含n) | ab{1,2}c表示abc、abbc |
^ | 匹配字符串开头 | ^abc表示abc在一个字符串的开头 |
$ | 匹配字符串结尾 | abc$表示abc且在一个字符串的结尾 |
( ) | 分组标记,内部只能使用丨操作符 | (abc)表示abc,(abc丨def)表示abc、def |
\d | 数字,等价于[0-9] | |
\w | 单词字符,等价于[A-Za-z0-9_] |
元字符 | 描述 |
---|---|
. | 句号匹配任意单个字符,除了换行符 |
[ ] | 字符种类,匹配括号内的任意字符 |
[^ ] | 否对的字符种类,匹配除了方括号内的任意字符 |
* | 匹配>=0个重复在*号之前的字符 |
+ | 匹配>=1个重复的+号之前的字符 |
? | 标记?之前的字符为可选 |
{n,m} | 匹配num个大括号之前的字符(n<=num<=m) |
(xyz) | 字符集,匹配与xyz完全相等的字符串 |
丨 | 或运算符,匹配符号前或后的字符 |
\ | 专一字符用于匹配保留字符(表内) |
\d | 数字,等价于[0-9] |
\w | 单词字符,等价于[A-Za-z0-9_ ] |
^ | 从开始行开始匹配 |
$ | 从末端开始匹配 |
Re库的基本使用
Re库是python的标准库,主要用于字符串匹配
调用:import re
raw string类型(原生字符串类型)
表示:r'text'
例:r'[1-9]\d{5}'
Re库主要功能函数
函数 | 说明 |
---|---|
re.search() | 在一个字符串中搜索匹配正则表达式的第一个位置,返回match对象 |
re.match() | 从一个字符串的开始位置起匹配正则表达式,返回match对象 |
re.findall() | 搜索字符串,以列表类型返回全部能匹配的子串 |
re.spilt() | 将一个字符串按照正则表达式匹配结果进行分割,返回列表类型 |
re.finditer() | 搜索字符串,返回一个匹配结果的迭代类型,每个迭代元素是match对象 |
re.sub() | 在一个字符串中替换所有匹配正则表达式的子串,返回替换后的字符串 |
1、re.search(pattern, string, flags=0)
在一个字符串中搜索匹配正则表达式的第一个位置,返回match对象
· pattern:正则表达式的字符串或原生字符串表示
· string:待匹配字符串
· flags:正则表达式使用时的控制标记
常用标记 | 说明 |
---|---|
re.I re.IGNORECASE | 忽略正则表达式的大小写,[A-Z]能够匹配小写字符 |
re.M re.MULTILINE | 正则表达式中的^操作符能够将给定字符串的每行当作匹配开始 |
re.S re.DOTALL | 正则表达式中的.操作符能够匹配所有字符串,默认匹配换行外的所有字符 |
>>> import re
>>> match = re.search(r'[1-9]\d{5}', 'BIT 100081')
>>> if match:
print(match.group(0))
#.search()是在整体中搜索的
100081
2、re.match(pattern, string, flags=0)
>>> import re
>>> match = re.match(r'[1-9]\d{5}', 'BIT 100081')
>>> if match:
match.group(0)
#match从字符串位置搜索,字母不能匹配数字,为空
>>> match = re.match(r'[1-9]\d{5}', '100081 BIT')
>>> if match:
print(match.group(0))
#调换一下目标字符串中字母与数字的位置,就可了
100081
3、re.findall(pattern, string, flags=0)
搜索字符串,以列表类型返回全部能匹配的子串
>>> import re
>>> ls = re.findall(r'[1-9]\d{5}', 'BIT100081 TSU100084')
>>> ls
['100081', '100084']
4、re.spilt(pattern, string, maxspilt=0, flags=0)
maxspilt:最大分割数
将一个字符串按照正则表达式匹配结果进行分割,返回列表类型
>>> import re
>>> re.split(r'[1-9]\d{5}', 'BIT100081 TSU100084')
['BIT', ' TSU', '']
将一个正则表达式匹配字符串,匹配的部分去掉,去掉之后的部分作为元素放在列表里。
5、re.finditer(pattern, string, flags=0)
搜索字符串,返回一个匹配结果的迭代类型,每个迭代元素是match对象。
>>> import re
>>> for m in re.finditer(r'[1-9]\d{5}', 'BIT100081 TSU100084'):
if m:
print(m.group(0))
100081
100084
6、re.sub(pattern, repl, string, count=0, flags=0)
· repl:替换匹配字符串的字符串
· count:匹配的最大替换次数
>>> re.sub(r'[1-9]\d{5}', ':zipcode', 'BIT100081 TSU100084')
'BIT:zipcode TSU:zipcode'
Re库的另一种等价用法
regex = re.compile(pattern, flags=0)
将正则表达式的字符串形式编译成正则表达式对象
`>>>regex = re.compile(r'[1-9]\d{5}')
函数 | 说明 |
---|---|
regex.search() | 在一个字符串中搜索匹配正则表达式的第一个位置,返回match对象 |
regex.match() | 从字符串开始位置匹配 |
regex.findall() | 以列表类型返回全部匹配的子串 |
regex.spilt() | 以匹配部分为分隔,并去掉 |
regex.finditer() | 搜索字符串,返回匹配结果的迭代类型 |
regex.sub() | 替换 |
Re库的Match对象
match对象是一次匹配的结果,包含匹配的很多信息
>>> match = re.search(r'[1-9]\d{5}', 'BIT 100081')
>>> if match:
print(match.group(0))
100081
>>> type(match)
<class 're.Match'>
Match对象的属性
属性 | 说明 |
---|---|
.string | 待匹配的文本 |
.re | 匹配时使用的patter对象(正则表达式) |
.pos | 正则表达式搜索文本的开始位置 |
.endpos | 正则表达式搜索文本的结束位置 |
.group(0) | 获得匹配后的字符串 |
.start() | 匹配字符串在原始字符串的开始位置 |
.end() | 匹配字符串在原始字符串的结束位置 |
.span() | 返回(.start(), .end()) |
>>> import re
>>> m = re.search(r'[1-9]\d{5}', "BIT100081 TSU100084")
>>> m.string
'BIT100081 TSU100084'
>>> m.re
re.compile('[1-9]\\d{5}')
>>> m.pos
0
>>> m.endpos
19
>>> m.group(0)
'100081'
>>> m.start()
3
>>> m.end()
9
>>> m.span()
(3, 9)
Re库的贪婪匹配和最小匹配
Re库默认采用贪婪匹配,即输出匹配最长的子串
>>> match = re.search(r'PY.*N', 'PYANBNCNDN')
>>> match.group(0)
'PYANBNCNDN'
#PY.*N:以PY为口头,N为结尾,*前任意字母无限扩展
最小匹配操作符
操作符 | 说明 |
---|---|
*? | 前一个字符0次或无限次扩展,最小匹配 |
+? | 前一个字符1次或无限次扩展,最小匹配 |
?? | 前一个字符0次或1次扩展,最小匹配 |
{m,n} | 扩展前一个字符m至n次(含n),最小匹配 |
>>> match = re.search(r'PY.*?N', 'PYANBNCNDN')
>>> match.group(0)
'PYAN'
爬取淘宝商品价格信息
import requests
import re
def getHTMLText(url): #获得页面
try:
r = requests.get(url, timeout = 30)
r.raise_for_status()
r.encoding = r.apparent_encoding
return r.text
except:
return ""
def parsePage(ilt, html): #对获得的页面进行解析
try:
plt = re.findall(r'\"view_price\"\:\"[\d\.]*\"',html)
tlt = re.findall(r'\"raw_titile\"\:\".*?\"',html)
for i in range(len(plt)):
price = eval(plt[i].spilt(':')[l])
title = eval(tlt[i].split(':')[l])
ilt.append([price, title])
except:
print("")
def printGoodsList(ilt):
tplt = "{:4}\t{:8}\t{:16}"
print(tplt.format("序号", "价格", "商品名称"))
count = 0
for g in ilt:
count = count + 1
print(tplt.format(count,g[0],g[1]))
def main():
goods = '书包' #爬取关键词
depth = 2 #爬取深度
start_url = 'https://s.taobao.com/search?q=' + goods
infoList = [] #输出结果
for i in range(depth):
try:
url = start_url + '&s=' + str(44*i)
html = getHTMLText(url)
parsePage(infoList, html)
except:
continue
printGoodsList(infoList)
main()