|
发表于 2023-6-14 15:48:52
|
显示全部楼层
轮子哥
@vczh的回答虽然是个玩笑(urllib、urlib2、urllib3),但是,也确实反映出了Python标准库的混乱。就我个人的使用感受来说,Python和Python标准库在数据结构方面非常强大,但是,在网络和邮件这两块,设计得非常糟糕。正是由于标准库的不完美,才有了更多更好的开源项目。对于Python程序员来说,可谓是"失之东隅,收之桑榆"。重要的是我们要善于发现并使用这些项目。
下面就给大家推荐几个我用过的,并且特别好用的项目,而不是简单的贴一下awesome python。相信很多人看完awesome python以后,只是简单的收藏一下,并没有很多帮助。
1. yagmail
Python官网上发邮件的例子(
Examples - Python 2.7.13 documentation),大家感受一下。反正我看到这一堆的import就已经被吓退场了。
#!/usr/bin/env python
"""Send the contents of a directory as a MIME message."""
import os
import sys
import smtplib
# For guessing MIME type based on file name extension
import mimetypes
from optparse import OptionParser
from email import encoders
from email.message import Message
from email.mime.audio import MIMEAudio
from email.mime.base import MIMEBase
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
如果使用yagmail,发送一个带附件的邮件,只需要2行代码:
import yagmail
yag = yagmail.SMTP(user='joy_lmx@163.com', password='nicai?', host='smtp.163.com', port='25')
yag.send(user, subject = "I now can send an attachment", attachments=['a.txt', 'b.jpg'])
2. requests
requests很多人都推荐过了,不过可能一些同学感受不到requests到底好在哪里。我们就以官网的例子为例简单说明,在没有request之前,如果我们要请求
https://api.github.com/user,需要像下面这样:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import urllib2
gh_url = 'https://api.github.com'
req = urllib2.Request(gh_url)
password_manager = urllib2.HTTPPasswordMgrWithDefaultRealm()
password_manager.add_password(None, gh_url, 'user', 'pass')
auth_manager = urllib2.HTTPBasicAuthHandler(password_manager)
opener = urllib2.build_opener(auth_manager)
urllib2.install_opener(opener)
handler = urllib2.urlopen(req)
print handler.getcode()
print handler.headers.getheader('content-type')
# ------
# 200
# 'application/json'
用requests以后,做同样的事情,我们可以这样(注意,前3行代码等于上面一整段代码):
>>> r = requests.get('https://api.github.com/user', auth=('user', 'pass'))
>>> r.status_code
200
>>> r.headers['content-type']
'application/json; charset=utf8'
>>> r.encoding
'utf-8'
>>> r.text
u'{"type":"User"...'
>>> r.json()
{u'private_gists': 419, u'total_private_repos': 77, ...}
3. psutil
psutil是用来获取操作系统监控以及进程管理的,如果你正在写一个监控系统(或脚本),赶紧去试试。这么说吧,我曾经使用psutil把网易内部的一个监控模块,从1000+行重构到了100+行。
我这里推荐的几个库,可能yagmail对最多人有用。而psutil,对专业的人士最有用。如果你要写一个监控系统,不使用psutil的话,只能直接去/proc目录下读取想用的文件进行计算,或者执行iostat、vmstat、df等linux命令获取命令输出,不管哪一种方法,都要处理很多繁琐的细节。有了psutil以后,就轻松多了。贴段代码大家感受一下:
def get_network_info(self):
"""
psutil.net_io_counters()
snetio(bytes_sent=12541464, bytes_recv=21459989, packets_sent=80164, packets_recv=88134, errin=0, errout=0,
dropin=0, dropout=0)
"""
return psutil.net_io_counters()
def get_memory_used(self):
"""
psutil.virtual_memory()
svmem(total=4159041536, available=3723980800, percent=10.5, used=1599082496,
free=2559959040, active=587403264, inactive=897105920, buffers=95989760, cached=1068032000)
"""
memory_info = psutil.virtual_memory()
memory_used = ( memory_info.total * memory_info.percent / 100 ) / 1024 / 1024
return memory_used
此外,使用越来越广泛的监控工具glances(如果没用过,要不现在就是试试?),就是用psutil收集相关数据的。
4. BeautifulSoup
如果你写爬虫,还在用XPath解析HTML,那赶紧用用BeautifulSoup,比XPath好用一百倍;如果你还在用正则表达式从HTML中获取内容,BeautifulSoup能让你好用到哭。(补充:评论里大家都说XPath更好用,难道是我思维方式和大家不一样?)
BeautifulSoup是用来解析HTML的,特点就是好用,有人吐槽BeautifulSoup慢?我不在乎BeautifulSoup比XPath慢多少,我只知道,我的时间比机器的更宝贵。
例如,要找到页面中所有的links,如下所示:
from bs4 import BeautifulSoup
soup = BeautifulSoup(open("index.html"))
for link in soup.find_all('a'):
print(link.get('href'))
例如,我在编写知乎的爬虫的时候,对于每一个用户的”关注”页面,对于每一个关注对象,有如下的tag:
<div class=&#34;zm-profile-card zm-profile-section-item zg-clear no-hovercard&#34;>
.......
<a title=&#34;天雨白&#34; data-hovercard=&#34;p$t$tian-yu-bai&#34; class=&#34;zm-item-link-avatar&#34; href=&#34;/people/tian-yu-bai&#34;>
</a>
.......
</div>
所以,解析单个关注的用户代码如下所示:
soup = BeautifulSoup(text)
#通过属性找到这个div,对于每个用户,对应于这样一个div
items = soup.find_all(&#39;div&#39;, class_=&#34;zm-profile-card zm-profile-section-item zg-clear no-hovercard&#34;)
for item in items:
# 获取这个div下的<a>标签的title属性
name = item.a.attrs[&#39;title&#39;]
# 获取这个div下的<a>标签下的<img>标签里面的src属性
avatar = item.a.img.attrs[&#39;src&#39;]
有了BeautifulSoup以后,爬虫操作就变得特别简单了。脏活累活别人都帮忙做好了。
5. utils
除了开源的库以外,还有些开源项目的DataStruct.py helper.py utils.py文件,也值得看一看。里面很多好东西,都是可以直接拿过来用的。
我举几个例子。
# -*- coding: utf-8 -*-
&#34;&#34;&#34;
requests.structures
~~~~~~~~~~~~~~~~~~~
Data structures that power Requests.
&#34;&#34;&#34;
class CaseInsensitiveDict(dict):
&#34;&#34;&#34;Case-insensitive Dictionary
For example, ``headers[&#39;content-encoding&#39;]`` will return the
value of a ``&#39;Content-Encoding&#39;`` response header.&#34;&#34;&#34;
&#34;&#34;&#34;
1. low_keys是一个字典,key是dict中key的消息形式,大写是dict中的key
2. 如果对字典进行了修改操作,则清空low_keys
3. 获取字典时,通过get --> __getitem__ --> __contains__ -->
通过low_keys字典获取到真实的key,通过真实的key获取dict中的value
&#34;&#34;&#34;
@property
def lower_keys(self):
if not hasattr(self, &#39;_lower_keys&#39;) or not self._lower_keys:
self._lower_keys = dict((k.lower(), k) for k in self.iterkeys())
return self._lower_keys
def _clear_lower_keys(self):
if hasattr(self, &#39;_lower_keys&#39;):
self._lower_keys.clear()
def __setitem__(self, key, value):
dict.__setitem__(self, key, value)
self._clear_lower_keys()
def __delitem__(self, key):
dict.__delitem__(self, key)
self._lower_keys.clear()
def __contains__(self, key):
return key.lower() in self.lower_keys
def __getitem__(self, key):
# We allow fall-through here, so values default to None
if key in self:
return dict.__getitem__(self, self.lower_keys[key.lower()])
def get(self, key, default=None):
if key in self:
return self[key]
else:
return default
def main():
d = CaseInsensitiveDict()
d[&#39;Laimingxing&#39;] = &#39;Laimingxing&#39;
d[&#39;LAimingxing&#39;] = &#39;LAimingxing&#39;
print d
print d[&#39;LAimingxing&#39;]
if __name__ == &#39;__main__&#39;:
main()
def dictreverse(mapping):
&#34;&#34;&#34;
Returns a new dictionary with keys and values swapped.
>>> dictreverse({1: 2, 3: 4})
{2: 1, 4: 3}
&#34;&#34;&#34;
return dict([(value, key) for (key, value) in iteritems(mapping)])
def dictfind(dictionary, element):
&#34;&#34;&#34;
Returns a key whose value in `dictionary` is `element`
or, if none exists, None.
>>> d = {1:2, 3:4}
>>> dictfind(d, 4)
3
>>> dictfind(d, 5)
&#34;&#34;&#34;
for (key, value) in iteritems(dictionary):
if element is value:
return key
class Storage(dict):
&#34;&#34;&#34;
A Storage object is like a dictionary except `obj.foo` can be used
in addition to `obj[&#39;foo&#39;]`.
>>> o = storage(a=1)
>>> o.a
1
>>> o[&#39;a&#39;]
1
>>> o.a = 2
>>> o[&#39;a&#39;]
2
>>> del o.a
>>> o.a
Traceback (most recent call last):
...
AttributeError: &#39;a&#39;
&#34;&#34;&#34;
def __getattr__(self, key):
try:
return self[key]
except KeyError as k:
raise AttributeError(k)
def __setattr__(self, key, value):
self[key] = value
def __delattr__(self, key):
try:
del self[key]
except KeyError as k:
raise AttributeError(k)
def __repr__(self):
return &#39;<Storage &#39; + dict.__repr__(self) + &#39;>&#39;
ps:web.py的作者是亚伦·斯沃茨(Aaron Swartz),一位年少成名的计算机天才,著名社交网站
Reddit联合创始人。致力于网络信息开放,却因涉嫌非法侵入麻省理工学院(MIT)和JSTOR(全称Journal Storage,存储学术期刊的在线系统)被指控,将受到最高35年监禁和100万美元罚款。该案正在认罪辩诉阶段,而亚伦·斯沃茨却于2013年1月11日在其纽约布鲁克林的寓所内,用一根皮带上吊自杀,尸体随后被女友发现,年仅26岁。
当然,我这还有很多乱七八糟的好东西,如果大家感兴趣的话,我再补充吧。要学Python看这里:
乐岸教育Python公开课-在线播放-优酷网,视频高清在线观看
此外,大家反馈,这个回答也对大家很有帮助:
怎么样才算是精通 Python? |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
×
|