通用类型集成环境 | 特点 |
---|---|
IDLE | 适用于,Python入门,功能简单直接,300+代码以内 |
Sublime Text | 专为程序员开发的第三方专用编程工具,专业编程体验,多种编程风格,工具非注册免费使用 |
Wing | 公司维护,工具收费,调试功能丰富,版本控制,版本同步,适合多人共同开发 |
Visual Studio&PTVS | 微软公司维护,Win环境为主,调试功能丰富, |
Eclipse | 开源IDE开发工具,需要有一定开发经验 |
Pycharm | 社区版免费,简单,集成度高,适合较复杂工程 |
科学计算,数据分析集成环境 | 特点 |
---|---|
Canopy | 公司维护,工具收费,支持近500个第三方库,适合科学计算领域应用开发 |
Anaconda | 开源免费,支持近800个第三方库 |
the website is the API
import requests
r=requests.get("http://www.baidu.com")
r.status_code
r.encoding='utf-8'
r.text
r.encoding:如果 header中不存在 charset,则认为编码为ISO-8859-1
r. apparent_encoding:根据网页内容分析出的编码方式 可以得到中文
print(r.encoding)→ISO-8859-1
print(r.apparent_encoding)→utf-8
print(r.text)
Requests库的异常
通用代码框架,最大的作用是使得用户访问和爬取网页,变得更有效,变得更稳定,变得更可靠。
import requests
def gethtmltext(url):
try:
r=requests.get(url, timeout=30)
r.raise_for_status()#最重要:如果状态不是200,引发HTTPERROR!异常
r.encoding =r.apparent_encoding
return r.text
except:
return "产生异常"
if _name_="_main_":
url="http://www.baidu.com"
print(gethtmltext(url))
HTTP协议
HTP, Hypertext Transfer Protocol,超文本传输协议。
HTTP是一个基于“请求与响应”模式的、无状态的应用层协议。
HTTP协议采用URL作为定位网络资源的标识。
URL格式:http://host[:port ] [ path ]
host:合法的 Internet主机域名或P地址
port:端号,缺省端囗为80
path:请求资源的路径
假设URL位置有一组数据 Userinfo,包括 Userid、 Username等20个字段。
需求:用户修改了 Username,其他不变。
采用 PATCH,仅向URL提交 Usernamel的局部更新请求
采用PUT,必须将所有20个字段一并提交到URL,未提交字段被删除。
PATCH:节省网络带宽
POST一个字典/键值对,会默认存储到一个表单的字段下。POST一个字符串,会自动编码为data
PUT方法类似于POST方法,一个表单,只是会覆盖掉原有数据。
request
params
POST方法提交data,并不作为url链接,而是url链接所对应的位置的地方作为数据来存储。
data
JSON
headers,模拟浏览器
proxies:这样访问网页时,所使用的地址就是代理服务器的地址。有效防止爬虫的逆追踪。
alow_redirects:
stream:
verify:
cert
掌握params,data,json,headers
get方法。
来源审查:判断Uer- Agenti进行限制
检查来访HTTP协议头的User-Agent域,只响应浏览器或友好爬虫的访问。
发布公告: Robots协议
告知所有爬虫网站的肥取策略,要求爬虫遵守。
Robots Exclusion Standard网络爬虫排除标准
作用:网站告知网络吧虫哪些页面可以抓取,哪些不行。
形式:在网站根目录下的 robots,txt文件。
网络爬虫:自动或人工识别 robots.txt,再进行内容爬取。
约束性: Robots协议是建议但非约束性,网络爬虫可以不遵守,但存在法律风险。
类似人类的获取信息行为,访问量小,频率也小,可以不遵守。
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("爬取失败")
r=requests.get("https://www.amazon.cn/gp/product/B01M8L5Z3Y")
r.status_code#503爬取失败
r.request.headers#现实python爬虫告诉服务器,自己user-agent是python-requests
kv={'user-agent':'Mozilla/5.0'}
r.requests.get(url,headers=kv)
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("爬取失败")
搜索引擎关键词提交接口
百度的关键词接口
http://www.baidu.com/s?wd=keyword
360的关键词接口
http://www.s0.com/s?q=keyword
import requests
kv ={'wd': 'Python'}
r=requests.get("http://www.baidu.com/s,params=kv)
r.status_code
r.request.url#通过response对象中包含的request对象信息,看请求的url到底
#是什么,http://www.baidu.com/s?wd=Python
len(r.text)#660000+字节长度
全代码:
import requests
keyword="python"
try:
kv={'wd':keyword}#360搜索引擎的键值对的键由wd改为q
r=requests.get('http://www.baidu.com/s',params=kv)
print(r.request.url)
r.raise_for_status()
print(len(r.text))
except:
print("爬取失败")
r请求,已经包含了图片,如何保存为二进制格式。
r.content表示返回内容的二进制形式
import requests
import os
url="http://image.nationalgeographic.com.cn/2017/0211/20170211061910157.jpg"
root="D://pics//"
path=root+url.split('/')[-1]# 斜线分隔,并[-1]读取斜线分隔后倒数第一个元素
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("爬取失败")
ip138查询
http://m.ip138.com/iplookup.asp?ip=ipaddress
import requests
url="http://m.ip138.com/iplookup.asp?ip="
try:
r= requests.get(url+'202.204.80.112')
r.raise_for_status()
r.encoding =r.apparent_encoding
print(r.text[-500:])
except:
print("爬取失败")
安装:pip install beautifulsoup4
from bs4 import BeautifulSoup
soup=BeautifulSoup ("<p>data</p>',html.parser')
import requests
r=requests.get('http://www.baidu.com')
demo=r.text
from bs4 import BeautifulSoup
soup=BeautifulSoup(demo,'html.parser')#给出demo,并给出解析demo的解释器
print(soup.prettify())
Beautiful Soup库是解析、遍历、维护“标签树”的功能库。
属性是由键和值组成的结构。
BeautifulSoup类,可以对应一个HTML/XML的文档的全部内容。
五种解析器:
demo:http://python123.io/ws/demo.html
from bs4 import BeautifulSoup
demo="http://python123.io/ws/demo.html"
soup=BeautifulSoup(demo,"html.parser")#soup变量就是解析后的demo页面
soup.title#得到了title标签
tag=soup.a
tag
#任何一个标签都可以通过soup.的方式获得
soup.a.name
soup.a.parent.parent.name
tag=soup.a
type(tag)#标签是标签类型,返回
soup.p.string#是navigablestring类型,返回标签内容
#!--xxxx--!的注释内容也可以通过.string获得。只是type为comment
type(tag.attrs)#标签属性是字典类型,返回
tag.attrs#获得a标签的全部属性字典,标签名字,属性名字,和属性的值
tag.attrs['class']#获得class属性的值
tag.attrs['href']#链接属性
HTML是树形结构的基本信息
三种遍历方法
.contents返回的是列表
子节点不仅包括标签结点,也包括字符串结点(如’\n’)。
也即尽管树形结构采用标签的形式来组织,但标签之间的NavigableString也构成了标签树的结点。(平行标签)
len(soup.body.contents)#body标签的全部子节点个数。返回5
soup.body.contents[1]
最高级标签的.parent是他自己
如何让HTML页面更加友好的显示
print(soup.prettify())
print(soup.a.prettify())
注意bs4库将读入的任何HTML文件和字符串都变成了utf-8编码。python3可以友好展示。
信息的标记:
标记后的信息可形成信息组织结构,增加了信息维度
标记后的信息可用于通信、存储或展示
标记的结构与信息一样具有重要价值
标记后的信息更利于程序理解和运用
扩展标记语言
img是标签。src是属性。china.jpg是值。
javascript语言中对面向对象信息的表达形式
有类型的键值对key: value
键值对中都需要增加双引号。表达他是字符串的形式。如果是一个数字,直接写数字即可。
如果多个值,采用方括号组织。
键值对多值用[,]组织。
键值对嵌套用{,}
XML实例:大多数信息被标签占用
JSON都需要双引号
很简洁
语言类型 | 特点 | 用处 |
---|---|---|
XML | 最早的通用信息标记语言,可扩展性好,但因为需要起始繁琐。 | Internet上的信息交互与传递。 |
JSON | 信息有类型,适合程序处理(Js),较XML简洁。 | 移动应用云端和节点的信息通信,无注释。 |
YAML | 信息无类型,文本信息比例最高,可读性好。 | 各类系统的配置文件,有注释易读。 |
XML JSON YAML
需要标记解析器例如:bs4库的标签树遍历
优点:信息解析准确
缺点提取过程繁琐,速度慢。
搜索
对信息的文本查找函数即可。
优点:提取过程简洁,速度较快。
缺点:提取结果准确性与信息内容相关。
融合方法:结合形式解析与搜索方法,提取关键信息。
XML JSON YAML + 搜索
需要标记解析器及文本查拢函数。
find_all .get(‘href’)
from bs4 import BeautifulSoup
soup=BeautifulSoup(demo,'html.parser')
for link in soup.find_all('a'):
print(link.get('href'))
import re
for tag in soup.fing_all(re.compile('b')):#re.compile('b')表示正则匹配所有以b开头的标签
print(tag.name)#返回b和body
soup.find_all('p','course')#找含有属性为course的p标签
soup.find_all(id='link1')#找属性及其值分别对应为id=link1的标签
soup.find_all(string="Basic Python")#检索内容为Basic Python
< tag >()等价于. find_all()
soup()等价于soup.find_all()
输入:大学排名URL链接
输出:大学排名信息的屏幕输出(排名,大学名称,总分)
技水路线: requests-bs4
定向爬虫:仅对输入URL进行吧取,不扩展爬取。
步骤1:从网络上获取大学排名网页内容
步骤2:提取网页内容中信息到合适的数据结构
步骤3:利用数据结构展示并输出结果
步骤1:从网络上获取大学排名网页内容
getHTMLText()
步骤2:提取网页内容中信息到合适的数据结构
fillUnivList()
步骤3:利用数据结构展示井输出结果
printUnivList()
try:
r=requests.get(url)
r.raise_for_status
r.encoding=r.apparent_encoding
return r.text
except:
return ""
def fillUnivList(ulist,html):
soup=BeautifulSoup(html)
for tr in soup.find('tbody').children:
if isinstance(tr,bs4.element.tag):
tds=tr('td')
ulist.append([tds[0].string,tds[1].string,tds[2].string])
def printUnivList(ulist,num):
print("{:^10}\t{:^6}\t{:^10}".format("排名","学校名称","总分"))
for i in range(num):
u=ulist[i]
print("{:^10}\t{:^6}\t{:^10}".format(u[0],u[1],u[2]))
def main():
uinfo=[]
url="https://www.shanghairanking.cn/rankings/bcur/2020"
html=getHTMLText(url)
fillUnivList(uinfo,html)
printUnivList(uinfo,20)
main()
首先找到tbody标签,再在其中解析tr标签,再在tr中找到td标签
当空格不够,默认的是西文空格填充,而不是中文空格。
中文对齐的填充:
采用中文字符的空格填充 chr(12288)#utf-8编码的中文空格。
tplt="{0:^10}\t{1:{3}^10}\t{2:^10}"
使用tplt的{3}第三个变量进行填充。
print(tplt.format("排名","学校名称","总分",chr(12288))
print(tplr.format(t[0),t[1],t[2],chr(12288))
regular expression regex RE
通用的字符串表达框架
简洁表达一组字符串的表达式
针对字符串表达“简洁”和“特征”思想的工具
判断某字符串的特征归属
表达文本类型的特征(病毒、人侵等)
同时查找或替换一组字符串
匹配字符串的全部或部分
正则表达式的使用:
编译:将符合正则表达式语法的字符串转换成正则表达式特征。
编译后的特征与一组字符串是对应的。
^表示以次开头,[]限定范围,+表示1-无限次拓展,$表示以次结尾,?表示0或1次拓展,*表示前一个字符0或无限次拓展,\d表示数字[0-9]
正则式 | 含义 |
---|---|
^ [A-Za-z]+$ | 由26个字母组成的字符串 |
^ [A-Za-z0-9]+$ | 由26个字母和数字组成的字符串 |
^-?\d$ | 整数形式的字符串 |
^ [0-9 ]*[ 1-9 ] [0-9] *$ | 正整数形式的字符串 |
[1-9]\d{5} | 中国境内邮政编码 |
[\u4e00-\u9fa5] | 匹配中文字符 |
\d{3}-\d{8}竖线\d{4}-\d{7} | 国内电话号码,010-68913536 |
IP地址字符串形式的正则表达式
(IP地址分4段,每段0-255)
#不太精确
\d+.\d+.\d+.\d+
\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}
#精确写法,将255拆分
0-99:[1-9]?\d 100-199:1\d{2}
200-249:2[0-4]\d 250-255:25[0-5]
([[1-9]?\d|1\d{2}|2[0-4]\d|25[0-5].]){3}([[1-9]?\d|1\d{2}|2[0-4]\d|25[0-5]])
\
不被解释为转义字符r‘text’
r‘[1-9]\d{5}’
\
re.search(),re.match(),re.findall(),re.split(),re.finditer(),re.sub()
re.search(pattern,string,flag=0)
.match()是从起始位置开始匹配。
要搭配if使用
re.findall()
re.split()是按正则匹配,匹配的部分去掉,去掉后的东西放到一个列表里。
re.finditer()
将一个正则表达式的字符串编译为一个正则表达式的类型。patter对象。直接调用方法,获得结果。
Re库默认贪婪匹配,如果有多个,则是最长匹配。
PY.*N
最短匹配
PY.*?N
当有操作符可以匹配不同长度时,都可以在这个操作符后面添加一个?,来获得最小匹配的结果。
功能描述:
目标:获取淘宝搜索页面的信息,提取其中的商品名称和价格。
理解:淘宝的搜索接口-翻页的处理
技术处理:requests-re
观察分析:
步骤1:提交商品搜索请求,循环获取页面。
步骤2:对于每个页面,提取商品名称和价格信息。
步骤3:将信息输出到屏幕上。
#CrowTaobaoPrice.py
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:
#\ 这是引用符,用来将这里列出的这些元字符当作普通的字符来进行匹配。
#例如正则表达式\$被用来匹配美元符号
#商品价格由view_price这个键值对组成
plt = re.findall(r'\"view_price\"\:\"[\d\.]*\"',html)
tlt = re.findall(r'\"raw_title\"\:\".*?\"',html)
for i in range(len(plt)):
price = eval(plt[i].split(':')[1])
title = eval(tlt[i].split(':')[1])
ilt.append([price , title])
except:
print("")
def printGoodsList(ilt):
tplt = "{:4}\t{:8}\t{:16}"
#打印输出标题
print(tplt.format("序号", "价格", "商品名称"))
#count作为序号计数
count = 0
for g in ilt:
count = count + 1
print(tplt.format(count, g[0], g[1]))
def main():
goods = '书包'
depth = 3
start_url = 'https://s.taobao.com/search?q=' + goods
infoList = []
for i in range(depth):
try:
#观察到不同url中,s相差44
url = start_url + '&s=' + str(44*i)
html = getHTMLText(url)
parsePage(infoList, html)
except:
continue
printGoodsList(infoList)
main()
功能描述
目标:获取上交所和深交所所有股票的名称和交易信息
输出:保存到文件中
技水路线: requests-bs4-re
要找那些信息写在HTML代码中
步骤1:从东方财富网获取股票列表
步骤2:根据股票列表逐个到百度股票获取个股信息
步骤3:将结果存储到文件
获得r.apparent_encoding较耗费时间。手动访问网页并赋值,
增加动态进度显示。
\r特殊的转义符,将光标提到头部。下一次打印就会覆盖展示。
#CrawBaiduStocksA.py
import requests
from bs4 import BeautifulSoup
import traceback
import re
def getHTMLText(url):
try:
r = requests.get(url)
r.raise_for_status()
r.encoding = r.apparent_encoding
return r.text
except:
return ""
def getStockList(lst, stockURL):
html = getHTMLText(stockURL)
soup = BeautifulSoup(html, 'html.parser')
a = soup.find_all('a')
for i in a:
try:
href = i.attrs['href']
lst.append(re.findall(r"[s][hz]\d{6}", href)[0])
except:
continue
def getStockInfo(lst, stockURL, fpath):
for stock in lst:
url = stockURL + stock + ".html"
html = getHTMLText(url)
try:
if html=="":
continue
infoDict = {}
soup = BeautifulSoup(html, 'html.parser')
stockInfo = soup.find('div',attrs={'class':'stock-bets'})
name = stockInfo.find_all(attrs={'class':'bets-name'})[0]
infoDict.update({'股票名称': name.text.split()[0]})
keyList = stockInfo.find_all('dt')
valueList = stockInfo.find_all('dd')
for i in range(len(keyList)):
key = keyList[i].text
val = valueList[i].text
infoDict[key] = val
with open(fpath, 'a', encoding='utf-8') as f:
f.write( str(infoDict) + '\n' )
except:
traceback.print_exc()
continue
def main():
stock_list_url = 'https://quote.eastmoney.com/stocklist.html'
stock_info_url = 'https://gupiao.baidu.com/stock/'
output_file = 'D:/BaiduStockInfo.txt'
slist=[]
getStockList(slist, stock_list_url)
getStockInfo(slist, stock_info_url, output_file)
main()