马哥linux致力于linux运维培训,连续多年排名第一,订阅者可免费获得学习机会和相关Linux独家实战资料! |
|
运维 · 再见,CDN 巨头:Akamai 宣布 ... · 2 天前 |
【伯乐在线导读】:有网友在 Quora 上提问,「你用 Python 写过最牛逼的程序/脚本是什么?」。本文摘编了 3 个国外程序员的多个小项目,含代码。
更新:凭借这些脚本,我找到了工作!可看我在这个帖子中的回复,《Has anyone got a job through Quora? Or somehow made lots of money through Quora?》
我们经常会遇到这样的情景,就是打开字幕网站subscene 或者opensubtitles, 搜索电影或电视剧的名字,然后选择正确的抓取器,下载字幕文件,解压,剪切并粘贴到电影所在的文件夹,并且需把字幕文件重命名以匹配电影文件的名字。是不是觉得太无趣呢?对了,我之前写了一个脚本,用来下载正确的电影或电视剧字幕文件,并且存储到与电影文件所在位置。所有的操作步骤仅需一键就可以完成。懵逼了吗?
请看这个 Youtube 视频:https://youtu.be/Q5YWEqgw9X8
源代码 存放在GitHub: subtitle-downloader
更新: 目前,该脚本支持多个字幕文件同时下载。步骤:按住 Ctrl ,选择你想要为其下载字幕的多个文件 , 最后执行脚本即可
我是一个电影迷,喜欢看电影。我总是会为该看哪一部电影而困惑,因为我搜集了大量的电影。所以,我应该如何做才能消除这种困惑,选择一部今晚看的电影?没错,就是IMDb。我打开 http://imdb.com,输入电影的名字,看排名,阅读和评论,找出一部值得看的电影。
但是,我有太多电影了。谁会想要在搜索框输入所有的电影的名字呢? 我肯定不会这样做,尤其是我相信“如果某些东西是重复性的,那么它应该是可以自动化的”。因此,我写了一个 python 脚本, 目的是为了使用 非官方的 IMDb API 来获取数据。我选择一个电影文件(文件夹),点击右键,选择‘发送到’,然后 点击 IMDB.cmd (顺便提一下,IMDB.cmd 这个文件就是我写的 python 脚本),就是这样。
我的浏览器会打开这部电影在
IMDb
网站上的准确页面。
仅仅只需点击一个按键,就可以完成如上操作。如果你不能够了解这个脚本到底有多酷,以及它可以为你节省多少时间,请看这个 Youtube 视频:https://youtu.be/JANNcimQGyk
从现在开始,你再也不需要打开你的浏览器,等待加载IMDb的页面,键入电影的名字。这个脚本会帮你完成所有的操作。跟往常一样,源代码放在了GitHub:imdb ,并且附有操作说明。当然,由于这个脚本必须去掉文件或文件夹中的无意义的字符,比如“DVDRip, YIFY, BRrip”等,所以在运行脚本的时候会有一定比例的错误。但是经过测试,这个脚本在我几乎所有的电影文件上都运行的很好。
2014-04-01更新:
许多人在问我是否可以写一个脚本,可以发现一个文件夹中所有电影的详细信息,因为每一次只能发现一个电影的详细信息是非常麻烦的。我已经更新了这个脚本,支持处理整个文件夹。脚本会分析这个文件夹里的所有子文件夹,从 IMDb上抓取所有电影的详细信息 ,然后打开一个电子表格,根据IMDb 上的排名,从高到低降序排列所有的电影。这个表格中包含了 (所有电影)在 IMDb URL, 年份,情节,分类,获奖信息,演员信息,以及其他的你可能在 IMBb找到的信息。下面是脚本执行后,生成的表格范例:
Your very own personal IMDb database! What more can a movie buff ask for? ;)
Source on GitHub:
imdb
你也可以有一个个人 IMDb 数据库!一个电影爱好者还能够要求更多吗?:)
源代码在 GitHub : imdb
我个人超级喜欢 Matthew Inman 的漫画。它们在疯狂搞笑的同时,却又发人深省。但是,我很厌烦重复点击下一个,然后才能阅读每一个漫画。另外,由于每一个漫画都由多福图片组成,所以手动下载这些漫画是非常困难的。
基于如上原因,我写了一个 python 脚本 ,用来从这个站点下载所有的漫画。这个脚本利用 BeautifulSoup (http://www.crummy.com/software/B… ) 解析 HTML 数据, 所以在运行脚本前,必须安装 BeautifulSoup。 用于下载燕麦片(马修.英曼的一部漫画作品)的下载器已经上传到GitHub:theoatmeal.com-downloader 。(漫画)下载完后的文件夹是这样的 :D
4. someecards.com 下载器
成功地从http://www.theoatmeal.com 下载了整部漫画后,我在想是否我可以做同样的事情 , 从另一个我喜欢的站点— 搞笑的,唯一的 http://www.someecards.com . 下载一些东西呢?
somececards 的问题是,图片命名是完全随机的,所有图片的排放没有特定的顺序,并且一共有52 个大的类别, 每一个类别都有数以千计的图片。
我知道,如果我的脚本是多线程的话,那将是非常完美的,因为有大量的数据需要解析和下载,因此我给每一个类别中的每一页都分配一个线程。这个脚本会从网站的每一个单独的分类下载搞笑的电子贺卡,并且把每一个放到单独的文件夹。现在,我拥有这个星球上最好笑的电子贺卡私人收藏。下载完成后,我的文件夹是这样的:
没错,我的私人收藏总共包括:52个类别,5036个电子贺卡。 源代码在这里: someecards.com-downloader
编辑:很多人问我是否可以共享我下载的所有文件,(在这里,我要说)由于我的网络不太稳定,我没办法把我的收藏上传到网络硬盘,但是我已经上传一个种子文件,你们可以在这里下载: somecards.com Site Rip torrent
种下种子,传播爱:)
有三个故事让我的21岁生日变的难忘,这是最后一个故事。我倾向于在每一条祝福下亲自评论,但是使用 python 来做更好。
…
1. # Thanking everyone who wished me on my birthday
2. import requests
3. import json
4.
5. # Aman's post time
6. AFTER = 1353233754
7. TOKEN = ' '
8.
9. def get_posts () :
10. """Returns dictionary of id, first names of people who posted on my wall
11. between start and end time"""
12. query = ( "SELECT post_id, actor_id, message FROM stream WHERE "
13. "filter_key = 'others' AND source_id = me() AND "
14. "created_time > 1353233754 LIMIT 200" )
15.
16. payload = { 'q' : query , 'access_token' : TOKEN }
17. r = requests . get ( 'https://graph.facebook.com/fql' , params = payload )
18. result = json . loads ( r . text )
19. return result [ 'data' ]
20.
21. def commentall ( wallposts ) :
22. """Comments thank you on all posts"""
23. #TODO convert to batch request later
24. for wallpost in wallposts :
25.
26. r = requests . get ( 'https://graph.facebook.com/%s' %
27. wallpost [ 'actor_id' ])
28. url = 'https://graph.facebook.com/%s/comments' % wallpost [ 'post_id' ]
29. user = json . loads ( r . text )
30. message = 'Thanks %s :)' % user [ 'first_name' ]
31. payload = { 'access_token' : TOKEN , 'message' : message }
32. s = requests . post ( url , data = payload )
33.
34. print "Wall post %s done" % wallpost [ 'post_id' ]
35.
36. if __name__ == '__main__' :
37. commentall ( get_posts ())
…
为了能够顺利运行脚本,你需要从Graph API Explorer(需适当权限)获得 token。 本脚本假设特定时间戳之后的所有帖子都是生日祝福。
尽管对评论功能做了一点改变,我仍然喜欢每一个帖子。
当我的点赞数,评论数以及评论结构在 ticker(Facebook一项功能,朋友可以看到另一个朋友在做什么,比如点赞,听歌,看电影等) 中爆涨后,我的一个朋友很快发现此事必有蹊跷。
尽管这个不是我最满意的脚本,但是它简单,快捷,有趣。
当我和 Sandesh Agrawal 在网络实验室讨论时,有了写这个脚本的想法。 为此,Sandesh Agrawal 耽搁了实验室作业,深表感谢。
好了,在我失去这个项目之前(一个猪一样的朋友格式化了我的硬盘,我的所有代码都在那个硬盘上)或者说,在我忘记这些代码之前,我决定来回答这个问题。
当我对图像处理感兴趣之后,我一直致力于研究机器学习。我写这个有趣的脚本,目的是为了分类图片,很像 Facebook 做的那样(当然这是一个不够精确的算法)。 我使用了 OpenCV 的人脸检测算法,“haarcascade_frontalface_default.xml”,它可以从一张照片中检测到人脸。
你可能已经察觉到这张照片的某些地方被错误地识别为人脸。 我试图通过修改一些参数(来修正这一问题),但还是某些地方被错误地识别为人脸,这是由相机的相对距离导致的。我会在下一阶段解决这一问题(训练步骤)。
这个训练算法需要一些训练素材,每个人需要至少需要100-120个训练素材(当然多多益善)。 我太懒了,并没有为每一个人挑选照片,并把它们复制粘帖到训练文件夹。所以,你可能已经猜到,这个脚本会打开一个图片,识别人脸,并显示每一个人脸(脚本会根据处于当前节点的训练素材给每一个人脸预测一个名字)。伴随着每次你标记的照片,Recognizer 会被更新,并且还会包含上一次的训练素材。 在训练过程中,你可以增加新的名字。我使用 python 库 tkinter 做了一个 GUI。 因此,大多数时候,你必须初始化一小部分照片(给照片中的人脸命名),其他的工作都可以交给训练算法。 因此,我训练了 Recognizer ,然后让它(Recognizer)去处理所有的图片。
我使用图片中包含的人的人名来命名图片,(例如: Tanmay&*****&*****)。 因此,我可以遍历整个文件夹,然后可以通过输入人名的方法来搜索图片。
初始状态下,当一个人脸还没有训练素材时(素材库中还没有包括这个人脸的名字),需要询问他/她的名字。
我可以增加一个名字,像这个样子:
当训练了几个素材后,它会像这个样子:
最后一个是针对应对那些垃圾随机方块而使用的变通解决方案。
带名字的最终文件夹。
所以,现在寻找图片变得相当简单。顺便提一下,很抱歉(我)放大了这些照片。
…
import cv2
import sys
import os , random , string
#choices=['Add a name']
import os
current_directory = os.path . dirname ( os.path . abspath ( __file__ ))
from Tkinter import Tk
from easygui import *
import numpy as np
x = os . listdir ( current_directory )
new_x = []
testing = []
for i in x :
if i . find ( '.' ) ==- 1 :
new_x += [ i ]
else :
testing += [ i ]
x = new _ x
g = x
choices = [ 'Add a name' ] + x
y = range ( 1 , len ( x ) + 1 )
def get_images_and_labels () :
global current_directory , x , y , g
if x == [] :
return ( False , False )
image_paths = []
for i in g :
path = current_directory + '' + i
for filename in os . listdir ( path ) :
final_path = path + '' + filename
image_paths += [ final_path ]
# images will contains face images
images = []
# labels will contains the label that is assigned to the image
labels = []
for image_path in image_paths :
# Read the image and convert to grayscale
img = cv2 . imread ( image_path , 0 )
# Convert the image format into numpy array
image = np . array ( img , 'uint8' )
# Get the label of the image
backslash = image_path . rindex ( '' )
underscore = image_path . index ( '_' , backslash )
nbr = image_path [ backslash + 1 : underscore ]
t = g . index ( nbr )
nbr = y [ t ]
# If face is detected, append the face to images and the label to labels
images . append ( image )
labels . append ( nbr )
#cv2.imshow("Adding faces to traning set...", image)
#cv2.waitKey(50)
# return the images list and labels list
return images , labels
# Perform the tranining
def train_recognizer () :
recognizer = cv2 . createLBPHFaceRecognizer ()
images , labels = get_images_and_labels ()
if images == False :
return False
cv2 . destroyAllWindows ()
recognizer . train ( images , np . array ( labels ))
return recognizer
def get_name ( image_path , recognizer ) :
global x , choices
#if recognizer=='':
# recognizer=train_recognizer()
cascadePath = "haarcascade_frontalface_default.xml"
faceCascade = cv2 . CascadeClassifier ( cascadePath )
#recognizer=train_recognizer()
x1 = testing
global g
print image_path
image = cv2 . imread ( image_path )
img = cv2 . cvtColor ( image , cv2 . COLOR_BGR2GRAY )
predict_image = np . array ( img , 'uint8' )
faces = faceCascade . detectMultiScale (
img ,
scaleFactor = 1.3 ,
minNeighbors = 5 ,
minSize = ( 30 , 30 ),
flags = http :// cv2 . cv . CV_HAAR_SCALE _ IMAGE
)
for ( x , y , w , h ) in faces :
f = image [ y : y + w , x : x + h ]
cv2 . imwrite ( 'temp.jpg' , f )
im = 'temp.jpg'
nbr_predicted , conf = recognizer . predict ( predict_image [ y : y + h , x : x + w ])
predicted_name = g [ nbr_predicted - 1 ]
print "{} is Correctly Recognized with confidence {}" . format ( predicted_name , conf )
if conf & gt ; = 140 :
continue
msg = 'Is this ' + predicted_name
reply = buttonbox ( msg , image = im , choices = [ 'Yes' , 'No' ])
if reply == 'Yes' :
reply = predicted_name
directory = current_directory + '' + reply
if not os.path . exists ( directory ) :
os . makedirs ( directory )
random_name = '' . join ( random . choice ( string . ascii_uppercase + string . digits ) for _ in range ( 7 ))
path = directory + '' + random_name + '.jpg'
cv2 . imwrite ( path , f )
else :
msg = "Who is this?"
reply = buttonbox ( msg , image = im , choices = choices )
if reply == 'Add a name' :
name = enterbox ( msg = 'Enter the name' , title = 'Training' , strip = True )
print name
choices += [ name ]
reply = name
directory = current_directory + '' + reply
if not os.path . exists ( directory ) :
os . makedirs ( directory )
random_name = '' . join ( random . choice ( string . ascii_uppercase + string . digits ) for _ in range ( 7 ))
path = directory + '' + random_name + '.jpg'
print path
cv2 . imwrite ( path , f )
# calculate window position
root = Tk ()
pos = int ( root . winfo_screenwidth () * 0.5 ), int ( root . winfo_screenheight () * 0.2 )
root . withdraw ()
WindowPosition = "+%d+%d" % pos
# patch rootWindowPosition
rootWindowPosition = WindowPosition
def detect_faces ( img ) :
global choices , current_directory
imagePath = img
faceCascade = cv2 . CascadeClassifier ( cascPath )
image = cv2 . imread ( imagePath )
gray = cv2 . cvtColor ( image , cv2 . COLOR_BGR2GRAY )
faces = faceCascade . detectMultiScale (
gray ,
scaleFactor = 1.3 ,
minNeighbors = 5 ,
minSize = ( 30 , 30 ),
flags = http :// cv2 . cv . CV_HAAR_SCALE _ IMAGE
)
print "Found {0} faces!" . format ( len ( faces ))
m = 0
for ( x , y , w , h ) in faces :
m += 1
padding = 0
f = image [ y - padding : y + w + padding , x - padding : x + h + padding ]
cv2 . imwrite ( 'temp.jpg' , f )
im = 'temp.jpg'
msg = "Who is this?"
reply = buttonbox ( msg , image = im , choices = choices )
if reply == 'Add a name' :
name = enterbox ( msg = 'Enter the name' , title = 'Training' , strip = True )
print name
choices += [ name ]
reply = name
directory = current_directory + '' + reply
if not os.path . exists ( directory ) :
os . makedirs ( directory )
random_name = '' . join ( random . choice ( string . ascii_uppercase + string . digits ) for _ in range ( 7 ))
path = directory + '' + random_name + '.jpg'
print path
cv2 . imwrite ( path , f )
def new ( img , recognizer ) :
imagePath = current_directory + '' + img
print imagePath
get_name ( imagePath , recognizer )
cascPath = 'haarcascade_frontalface_default.xml'
b = 0
os . system ( "change_name.py" )
for filename in os . listdir ( "." ) :
b += 1
if b % 10 == 0 or b == 1 :
os . system ( "change_name.py" )
recognizer = train_recognizer ()
if filename . endswith ( '.jpg' ) or filename . endswith ( '.png' ) :
print filename
imagePath = filename
#detect_faces(imagePath)
new ( imagePath , recognizer )
os . remove ( filename )
raw_input ( 'Done with this photograph' )
…
我想进一步修改它的搜索功能,其中会包含更多的搜索类型,比如基于地理位置,微笑的脸,伤心的脸等等。(这样我就可以在 Skylawns 上 搜索快乐的 Tanmay & 沮丧的 Akshay & 快乐的…)
我还写了很多脚本,但那都是很久之前的事情了,我也懒得再去检查这些代码了,我会列出部分代码。
GitHub 链接: tanmay2893/Image-Sorting
在那段时间,我没有智能手机。 导致我常常错过来自于我所在的研究所的邮件(在我的研究所的邮件 ID),我写了一个脚本,可以在我的笔记本上运行,而且能给我的手机发信息。我使用 python 的 IMAP 库来获取邮件。我可以输入一些重要的人的名字,这样一来,当这些人给我发了邮件后,我可以收到短信通知。对于短信, 我使用了 way2sms.com(写了一个 python 脚本,自动登陆我的账户,然后发送 短信)。
铁路方面不经常发送 PNR 状态消息。因此,我写了一个脚本,可以从印度铁路网站获取 PNR 状态。这是非常容易的,因为那个网站没有验证码,即使有,也只是形同虚设的验证码(在过去,一些字母会被写在看起来像图片一样的东西上面,因为他们为这些字母使用了一个 “check” 的背景图)。 我们可以轻松地从 HTML 网页得到这些字母。我不明白他们这样做的目的是什么,难道仅仅是为了愚弄他们自己吗? 不管怎么样,我使用短信息脚本来处理它,经过一段时间间隔,它会在我的笔记本上运行一次,就像是一个定时任务,只要 PNR 状态有更新,它就会把更新信息发送给我。
这个脚本会从 Youtube 页面下载所有的 Youtube 视频 以及他们所有的字幕文件(从 Download and save subtitles 下载)。为了使下载速度更快一点,我使用了多线程。还有一个功能是,即使你的电脑重启了,仍然可以暂停和恢复播放下载的(视频)。我原本想做一个UI的,但是我太懒了… 一旦我的下载任务完成,我就不去关心 UI 的事情了。
我猜想这个功能已经在别的地方提到过了。一个窗口通知器。(在右下角的通知区域,它会告诉你实时比分以及评论信息)。如果你愿意的化,在某些时间段,你也可以关掉它。
这个并不太实用,我只是写着玩玩。因为 Whatsapp 有网页版,我使用 selenium 和 Python 下载我的所有联系人的显示图片,并且,一旦有人更新了他们的显示图片,我将会知道。(如何做到的?非常简单,在设定好时间间隔后,我会一遍又一遍的不停下载所有的头像信息,一旦照片的尺寸发生变化,我将会知道他/她更新了显示图片)。然后我会给他/她发一个信息,不错的头像。我仅仅使用了一次来测试它的可用性。
我们一般在这个叫 ‘Nalanda’ 的网站上下载一些教学课件以及其他的课程资料, ‘Nalanda’ 在 BITS Pilani ( Nalanda ). 我自己懒得在考试前一天下载所有的课件,所以,我写了这个这个下载器,它可以把每一门科的课件下载到相应的文件夹。
代码:
…
import mechanize , os , urllib2 , urllib , requests , getpass , time
start_time = time . time ()
from bs4 import BeautifulSoup
br = mechanize . Browser ()
br . open ( 'https://nalanda.bits-pilani.ac.in/login/index.php' )
br . select_form ( nr = 0 )
name = ''
while name == '' :
try :
print '*******'
username = raw_input ( 'Enter Your Nalanda Username: ' )
password = getpass . getpass ( 'Password: ' )
br . form [ 'username' ] = username
br . form [ 'password' ] = password
res = br . submit ()
response = res . read ()
soup = BeautifulSoup ( response )
name = str ( soup . find ( 'div' , attrs = { 'class' : 'logininfo' }). a . string )[ :- 2 ]
except :
print 'Wrong Password'
f = open ( 'details.txt' , 'w' )
f . write ( username + 'n' + password )
f . close ()
print 'Welcome, ' + name
print 'All the files will be downloaded in your Drive C in a folder named "nalanda"'
#print soup.prettify()
div = soup . find_all ( 'div' , attrs = { 'class' : 'box coursebox' })
l = len ( div )
a = []
for i in range ( l ) :
d = div [ i ]
s = str ( d . div . h2 . a . string )
s = s [ : s . find ( '(' )]
c = ( s , str ( d . div . h2 . a [ 'href' ]))
path = 'c:nalanda' + c [ 0 ]
if not os.path . exists ( path ) :
|
运维 · 再见,CDN 巨头:Akamai 宣布 2026 年终止中国服务 2 天前 |
|
人称T客 · 细数这些年被甲骨文炮轰的对手们? 7 年前 |
|
长安街知事 · 这位北京厅官正筹备一家新金融企业 7 年前 |
|
二次元观察 · 【漫谈】人类史上两个最大的草食系男子住在一起将会擦出什么火花? 7 年前 |
|
社会学吧 · 一位被骗老人背后,是一群缺少温度的儿女 7 年前 |
|
德外5号 · 加强导向全覆盖,视频网站如何主动有为 |德外荐读 7 年前 |