python网络爬虫学习笔记

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&amp;tpl=mn&amp;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>&copy;2017&nbsp;Baidu&nbsp;<a href=http://www.baidu.com/duty/>使用百度前必读</a>&nbsp; <a href=http://jianyi.baidu.com/ class=cp-feedback>意见反馈</a>&nbsp;京ICP证030173号&nbsp; <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

简洁表达一组字符串的表达式:
image.png

正则表达式常用操作符

操作符 说明 实例
. 表示任何单个字符
[ ] 字符集,对单个字符给出取值范围 [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()
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容