动态网页抓取(关于with语句与上下文管理器三、思路整理(组图))

优采云 发布时间: 2021-11-21 06:09

  动态网页抓取(关于with语句与上下文管理器三、思路整理(组图))

  退出首页,在目标页面()下,如图,可以通过选择我们设置的charles来设置全局代理(网站的所有数据请求都经过代理)

  

  也可以只为这个网站设置代理

  

  二、知识储备

  requests.get():请求官方文档

  在这里,在 request.get() 中,我使用了两个附加参数 verify=False, stream=True

  verify = False 可以绕过网站的SSL验证

  stream=True 保持流打开,直到流关闭。在下载图片的过程中,可以在图片下载完成之前保持数据流不关闭,以保证图片下载的完整性。如果去掉这个参数,重新下载图片,会发现图片无法下载成功。

  contextlib.closure():contextlib 库下的关闭方法,其作用是将一个对象变成一个上下文对象来支持。

  使用with open()后,我们知道with的好处是可以帮助我们自动关闭资源对象,从而简化代码。其实任何对象,只要正确实现了上下文管理,都可以在with语句中使用。还有一篇关于 with 语句和上下文管理器的文章

  三、思想的组织

  这次爬取的动态网页是一张壁纸网站,上面有精美的壁纸,我们的目的是通过爬虫把网站上的原壁纸下载到本地

  网站网址:

  知道网站是动态的网站,那么就需要通过抓取网站的js包以及它是如何获取数据来分析的。

  打开网站时使用Charles获取请求。从json中找到有用的json数据,对比下载链接的url,发现下载链接的变化部分是图片的id,图片的id是从json中爬出来的。填写下载链接上的id部分,进行下载操作四、 具体步骤是通过Charles打开网站时获取请求,如图

  

  从图中不难发现,headers中有一个授权Client-ID参数,需要记下来,添加到我们自己的请求头中。(因为学习笔记,知道这个参数是反爬虫需要的参数。具体检测反爬虫操作,估计可以一一加参数试试)从中找到有用的json

  存在

  

  这里我们发现有一个图片ID。在网页上点击下载图片,从抓包中抓取下载链接,发现下载链接更改的部分是图片的id。

  

  这样就可以确定爬取图片的具体步骤了。从json中爬取图片id,在下载链接上填写id部分,执行下载操作并分析,总结代码步骤

  五、代码整理

  代码步骤

  1. 抓取图片id并保存到列表中

  # -*- coding:utf-8 -*-

import requests,json

def get_ids():

# target_url = \'http://unsplash.com/napi/feeds/home\'

id_url = \'http://unsplash.com/napi/feeds/home\'

header = {

\'User-Agent\': \'Mozilla/5.0 (Windows NT 6.1; WOW64) \'

\'AppleWebKit/537.36 (KHTML, like Gecko) \'

\'Chrome/61.0.3163.79 Safari/537.36\',

\'authorization\': \'*************\'#此部分参数通过抓包获取

}

id_lists = []

# SSLerror 通过添加 verify=False来解决

try:

response = requests.get(id_url, headers=header, verify=False, timeout=30)

response.encoding = \'utf-8\'

print(response.text)

dic = json.loads(response.text)

# print(dic)

print(type(dic))

print("next_page:{}".format(dic[\'next_page\']))

for each in dic[\'photos\']:

# print("图片ID:{}".format(each[\'id\']))

id_lists.append(each[\'id\'])

print("图片id读取完成")

return id_lists

except:

print("图片id读取发生异常")

return False

if __name__==\'__main__\':

id_lists = get_ids()

if not id_lists is False:

for id in id_lists:

print(id)

  结果如图,已经成功打印出图片ID

  

  根据图片id下载图片

  import os

from contextlib import closing

import requests

from datetime import datetime

def download(img_id):

header = {

\'User-Agent\': \'Mozilla/5.0 (Windows NT 6.1; WOW64) \'

\'AppleWebKit/537.36 (KHTML, like Gecko) \'

\'Chrome/61.0.3163.79 Safari/537.36\',

\'authorization\': \'***********\'#此参数需从包中获取

}

file_path = \'images\'

download_url = \'https://unsplash.com/photos/{}/download?force=true\'

download_url = download_url.format(img_id)

if file_path not in os.listdir():

os.makedirs(\'images\')

# 2种下载方法

# 方法1

# urlretrieve(download_url,filename=\'images/\'+img_id)

# 方法2 requests文档推荐方法

# response = requests.get(download_url, headers=self.header,verify=False, stream=True)

# response.encoding=response.apparent_encoding

chunk_size = 1024

with closing(requests.get(download_url, headers=header, verify=False, stream=True)) as response:

file = \'{}/{}.jpg\'.format(file_path, img_id)

if os.path.exists(file):

print("图片{}.jpg已存在,跳过本次下载".format(img_id))

else:

try:

start_time = datetime.now()

with open(file, \'ab+\') as f:

for chunk in response.iter_content(chunk_size=chunk_size):

f.write(chunk)

f.flush()

end_time = datetime.now()

sec = (end_time - start_time).seconds

print("下载图片{}完成,耗时:{}s".format(img_id, sec))

except:

if os.path.exists(file):

os.remove(file)

print("下载图片{}失败".format(img_id))

if __name__==\'__main__\':

img_id = \'vgpHniLr9Uw\'

download(img_id)

  

  下载前

  下载后

  

  合码批量下载

  # -*- coding:utf-8 -*-

import requests,json

from urllib.request import urlretrieve

import os

from datetime import datetime

from contextlib import closing

import time

class UnsplashSpider:

def __init__(self):

self.id_url = \'http://unsplash.com/napi/feeds/home\'

self.header = {

\'User-Agent\': \'Mozilla/5.0 (Windows NT 6.1; WOW64) \'

\'AppleWebKit/537.36 (KHTML, like Gecko) \'

\'Chrome/61.0.3163.79 Safari/537.36\',

\'authorization\': \'***********\'#此部分需要自行添加

}

self.id_lists = []

self.download_url=\'https://unsplash.com/photos/{}/download?force=true\'

print("init")

def get_ids(self):

# target_url = \'http://unsplash.com/napi/feeds/home\'

# target_url = \'https://unsplash.com/\'

#SSLerror 通过添加 verify=False来解决

try:

response = requests.get(self.id_url,headers=self.header,verify=False, timeout=30)

response.encoding = \'utf-8\'

# print(response.text)

dic = json.loads(response.text)

# print(dic)

print(type(dic))

print("next_page:{}".format(dic[\'next_page\']))

for each in dic[\'photos\']:

# print("图片ID:{}".format(each[\'id\']))

self.id_lists.append(each[\'id\'])

print("图片id读取完成")

return self.id_lists

except:

print("图片id读取发生异常")

return False

def download(self,img_id):

file_path = \'images\'

download_url = self.download_url.format(img_id)

if file_path not in os.listdir():

os.makedirs(\'images\')

# 2种下载方法

# 方法1

# urlretrieve(download_url,filename=\'images/\'+img_id)

# 方法2 requests文档推荐方法

# response = requests.get(download_url, headers=self.header,verify=False, stream=True)

# response.encoding=response.apparent_encoding

chunk_size=1024

with closing(requests.get(download_url, headers=self.header,verify=False, stream=True)) as response:

file = \'{}/{}.jpg\'.format(file_path,img_id)

if os.path.exists(file):

print("图片{}.jpg已存在,跳过本次下载".format(img_id))

else:

try:

start_time = datetime.now()

with open(file,\'ab+\') as f:

for chunk in response.iter_content(chunk_size = chunk_size):

f.write(chunk)

f.flush()

end_time = datetime.now()

sec = (end_time - start_time).seconds

print("下载图片{}完成,耗时:{}s".format(img_id,sec))

except:

print("下载图片{}失败".format(img_id))

if __name__==\'__main__\':

us = UnsplashSpider()

id_lists = us.get_ids()

if not id_lists is False:

for id in id_lists:

us.download(id)

#合理的延时,以尊敬网站

time.sleep(1)

  六、结论

  由于本文为学习笔记,中间省略了一些细节。

  结合其他资料,发现爬取动态网站的关键点是抓包分析。只要能从包中分析出关键数据,就剩下写爬虫的步骤了

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线