python基础知识准备
为了使服务器检测到它支持的浏览器标识,以便获得服务器的响应,需要在程序中加入浏览器请求头header,不然服务器会拒绝程序访问。
方法:打开网页–>右键检查–>在network中找到以下信息,复制粘贴到程序中。
1 header = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.164 Safari/537.36'
正则表达式
使用正则表达式匹配出网页里的图片。常用的正则有:
.*?
匹配不需要的内容,选取的内容加括号(.*?)
。例:(.*?)
、(.*?\.html)
、(.*?\.jpg)
;
?
匹配最短内容;
或|
的用法:[src|file]
匹配src或file、(.*?\.(?:jpg|JPG|jpeg|JPEG|gif|GIF|png|PNG))
匹配多种图片格式;
匹配数字字母[A-Za-z0-9]
;
提取数字.*?(\d+).*?
。
注意 :如果链接中有?
或\
,加\
转义,改成\?
、\\
;(
用[]
表示,[(]
。
下载网站图片或获取html时会用到如下正则表达式,照此修改。
1 2 3 4 5 reg = r'src="(.*?\.jpg)" /></a></p>' reg = r'[src|file]="(.*?\.(?:jpg|gif))" onload="' reg = r'v2-(.*?\.(?:jpg|gif)).*?noscript>?' reg = r'href="(.*?\.html)"><img width="234"' reg = r'<li><a>.*?(\d+).*?: </a></li><li id='
利用re.findall
找到html页面中的所有图片地址或新的链接地址:
1 2 allimage = re.findall(reg, html.decode('utf-8' , errors='ignore' )) allhtml = re.findall(reg, html.decode('utf-8' , errors='ignore' ))
异常处理
程序使用了循环,在不断访问服务器和下载图片时可能会发生异常,我们需要捕获处理它,否则程序会终止。try/except语句用来检测try语句块中的错误,从而让except语句捕获异常信息并处理。当try后的语句执行时发生异常,python就跳回到try并执行第一个匹配该异常的except子句,异常处理完毕,控制流就通过整个try语句,程序不会停止。以下为简单的try…except…else的语法:
1 2 3 4 5 6 7 8 try :<语句> except <名字>:<语句> except <名字>,<数据>:<语句> else :<语句>
在except里可以保存错误内容至某个文件,方便查看错误内容。
1 2 with open ('wrong_url.txt' ,'a' ) as f: f.write('\n' .join(url))
切片
有时候需要对某些网址做一些切片和合并处理。
num_str = "0123456789"
正序切片:
截取从 2 ~ 5位置的字符串print(num_str[2:6])
截取从 2 ~ 末尾的字符串print(num_str[2:])
截取从开始 ~ 5位置的字符串print(num_str[:6])
截取完整的字符串print(num_str[:])
从开始位置,每隔一个字符截取字符串print(num_str[::2])
从索引 1 开始,每隔一个取一个print(num_str[1::2])
倒序切片:
-1表示倒数第一个字符print(num_str[-1])
截取从 2 ~ 末尾-1的字符串print(num_str[2:-1])
截取字符串末尾两个字符print(num_str[-2:])
字符串的逆序print(num_str[::-1])
1 2 3 4 string = list [0 :8 ] url = '' + string + '&' + list [13 :] url_new = url[:-5 :] url_short = int (url[-11 :-5 :])
下载单个页面的图片
下载单个页面的图片程序很简单,一般不需要使用函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 import urllib.requestimport redef Header (): header = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.164 Safari/537.36' opener = urllib.request.build_opener() opener.addheaders = [('User-Agent' , header)] urllib.request.install_opener(opener) reg = r'v2-(.*?\.(?:jpg|gif)).*?noscript>?' reg = re.compile (reg) url = 'https://www.zhihu.com/question/' + str (num) print (url, end=' *** ' )Header() html = urllib.request.urlopen(url).read() imglist = re.findall(reg, html.decode('utf-8' , errors='ignore' )) n = 0 for imgurl in imglist: img = 'https://pic1.zhimg.com/v2-' + imgurl urllib.request.urlretrieve(img, "C:/file/%s.jpg" % n) n += 1 print (n, end='-' )
下载多个页面的图片
多个页面就需要用到for循环和try。程序运行过程中可能会出现异常,使用try防止退出循环。程序的主要部分:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 for i in range (num1, num2): try : url = '' + str (i) + '.html' print (url, end=' *** ' ) Header() html = urllib.request.urlopen(url).read() reg = r'file="(.*?\.jpg)"?' allimg = re.findall(reg, html.decode('utf-8' , errors='ignore' )) n = 0 for img in allimg: urllib.request.urlretrieve(img, "%s-%s.jpg" % (i, n)) print (n, end="-" ) n += 1 print (n) except : print ('----------' )
获取页面内的html链接
有些页面只显示了组图中的封面,点开封面图片后在新网页里才能查看所有图片,这就需要在网页里找到所有组图所在新网页的链接。建议使用自定义函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 reg1 = r'href="(.*?\.html)' reg2 = r'<li><a>.*?(\d+).*?:' reg3 = r'src="(.*?\.jpg)"' def GetHtml (url ): print (url, end=' ******\n' ) Header() html = urllib.request.urlopen(url).read() return html def GetImgUrl (html ): allurl = re.findall(reg1, html.decode('utf-8' , errors='ignore' )) for url in allurl: html = GetHtml(url) GetImage(html, url) def SaveImg (html, reg, name_1, name_2 ): allimg = re.findall(reg, html.decode('utf-8' , errors='ignore' )) for img in allimg: urllib.request.urlretrieve(img, "%s-%s.jpg" % (name_1, name_2)) def GetImage (html, url ): for i in range (num1, num2): url_n = '' try : html = urllib.request.urlopen(url_n).read() SaveImg(html, reg3, url, i) print (x, end="-" ) except : print ('----- %s -' % url) print ("" ) for i in range (num1, num2): url = '%s.html' % i html = GetHtml(url) GetImgUrl(html)
下载微博图片
python模拟登录
复制cookie
cookie保存在发起请求的客户端中,服务器利用cookie来区分不同的客户端。因为http是一种无状态的连接,当服务器一下子收到好几个请求时,是无法判断出哪些请求是同一个客户端发起的。而“访问登录后才能看到的页面”这一行为,恰恰需要客户端向服务器证明:“我是刚才登录过的那个客户端”。于是就需要cookie来标识客户端的身份,以存储它的信息(如登录状态)。这也意味着,只要得到了别的客户端的cookie,我们就可以假冒成它来和服务器对话。这给我们的程序带来了可乘之机。
先用浏览器登录微博,打开开发者工具,转到network。在左边的Name一栏找到当前的网址,选择右边的Headers,查看Request Headers,这里包含了该网站颁发给浏览器的cookie。复制到程序里,程序携带该cookie向网站发送请求,就能让程序假扮成刚才登录的浏览器,得到只有登录后才能看到的页面。
注意 ,最好是在运行程序前登录。如果过早登录,或是关闭浏览器,很可能复制的cookie就失效了。
查看图片链接
进入所要下载用户的界面–>相册–>相册专辑–>微博配图–>打开某张图片,查看网址,网址里的数字分别表示用户id、图片id和所在相册id–>查看网页源代码,选择自动换行,找到album_photo_ids,下面就是图片的id–>只复制数字和逗号到txt文件里,不要复制括号。这些图片都能下载,最多下载2000张,没有显示id的图片不知道怎么下载。
完整程序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 import urllib.requestimport reimport sysimport ioheader = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36' reg = r'src="(.*?\.(?:jpg|gif))" onload="?' sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf8' ) cookie = r'' def PhotoNum (): with open ('photo.txt' , 'r' ) as f: photoid = f.read().split(',' ) i = 0 for line in photoid: i += 1 return i def get_photo (User_id, Album_id ): with open ('photo.txt' , 'r' ) as f: photoid = f.read().split(',' ) i = 0 for Photo_id in photoid: url = 'https://photo.weibo.com/%s/wbphotos/large/photo_id/%s/album_id/%s' % ( User_id, Photo_id, Album_id) print (url, end=' ****** ' ) try : req = urllib.request.Request(url) req.add_header('cookie' , cookie) req.add_header('User-Agent' , header) html = urllib.request.urlopen(req).read() allimg = re.findall(reg, html.decode('utf-8' , errors='ignore' )) for img in allimg: urllib.request.urlretrieve(img, "C:/%s.jpg" % i) i += 1 print (i) if (i > photonum): return None except : print (url, end=' ------ ' ) photonum = PhotoNum() print (photonum) userid = '' albumid = '' get_photo(userid, albumid)
如果出现下载卡在某处,关闭程序,做好标记,从txt文件里删除已下载图片的id。重新命名接下来要下载的图片,不然会覆盖,从未下载的图片继续开始。
下载微博视频
安装you-get
使用you-get下载视频,安装方法:pip install you-get
。使用方法:
you-get url
默认下载到当前目录。
you-get -o dir -O name url
下载到指定文件夹,并命名。
you-get -i url
查看视频的清晰度,默认下载第一个。要下载的视频样式,比如高清是--format=mp4sd
,使用命令:you-get --format=mp4sd url
。
Ctrl + c
停止下载。
下载视频
进入用户主页–>相册–>视频,此时页面网址是https://weibo.com/p/%s/photos?type=video#place
其中%s是用户的id,复制id,程序会用到。右键–>查看网页源代码,其中https:\/\/video.weibo.com\/show?fid=1034:id
就是视频网址。只能查看到用户的前几十个视频id,所以如果视频很多,不能全部下载。视频网址是https://weibo.com/tv/show/1034:%s'
%s是视频的id,程序会使用正则表达式获取所有视频id.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 import urllib.requestimport reimport sysimport ioimport osheader = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36' sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf8' ) cookie = r'' def get_videos (User_id ): url = 'https://weibo.com/p/%s/photos?type=video#place' % User_id print (url, end=' ****** ' ) req = urllib.request.Request(url) req.add_header('cookie' , cookie) req.add_header('User-Agent' , header) html = urllib.request.urlopen(req).read() reg = r'fid=1034:(.*?)\\"><?' allvideos = re.findall(reg, html.decode('utf-8' , errors='ignore' )) for video in set (allvideos): url = 'https://weibo.com/tv/show/1034:%s' % video print (url) cmd = 'you-get ' + url os.system(cmd) userid = '' get_videos(userid)