爬虫--爬取图片(1)

很多初学爬虫的朋友都会懵懂的跟随一些速成的教程来写一些网站的爬取代码,所以不可避免的会产生很多问题和疑问。我就是其中一个,所以也就有了这篇博客,记录一下浑浑噩噩的代码编程之旅。
第一步当然是分析所要抓取的网站,目标当然就是要抓取的图片链接。但是图片链接不可能都在一个页面里,有些页面可能一遍下拉一边加载,有的页面可能需要点击某个链接跳到另外的页面然后才能找到。
我们这里先针对通过链接跳转的方式来找具体的图片链接。
三大步:
(1)抓到可以抓到图片的链接 我们这里暂时叫 http://xxx.xxxx.xxx/index_n.html
(2)进入到这里链接后抓到图片的链接,可能是下面这种链接
http://xxxx.xxxx.xxxx/xxxxx.jpeg
(3)去下载这个链接

---------------------------------------------------------------------

那么下面开始写代码:
(1)当然是先写个入口url,然后把页面内容拿到本地 get_index_page

def get_index_page(url):
	headers = {
		"User-Agent":"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36"
	}
	respose = requests.get(url=url,headers=headers)

	# page = respose.content
	# #将bytes转换成字符串
	# page = page.decode('utf-8')
	# print(page)

	respose.encoding = 'utf-8'
	html = respose.text
	return html

先运用requests的get方法传入url和headers参数,headers需要传递User-Agent参数。
这时候接到的数据resopose打印出来是这样的: <Response [200]>
可见是200,成功返回页面了。
这里可以通过两种方法把页面的信息从response里拿出来:
注意:
respose.text 和 respose.content :
content返回的是byte型数据 需要,转换成字符串
respose.content.decode(‘utf-8’)
text 返回的是unicode 型的数据 需要
respose.encoding = ‘utf-8’
然后再取出来text

---------------------------------------------------------------------

现在把网页取出来了,我们要做的就是从网页中提取我们需要的链接。但是格式并不是规范的格式。可我们怎么要数据呢?这里也有两种方式。先上代码:
def get_index_urls(html):
	end = 0
	while html.find('<a class="item-img"',end)!=-1:
		start = html.find('<a class="item-img"',end)
		end = html.find('</span> </a>',start)+len('</span> </a>')
		each = html[start:end]
		print(each)
	# bf = BeautifulSoup(html, 'lxml')
	# targets_url = bf.find_all(class_='item-img')
	# for each in targets_url:
	# 	print(each)

没有注释的是第一种方式:
简单粗暴截取字符串,建议先截取你要的数据这块,然后在对取到的url做处理,截取出你想要的数据。如果要问我怎么截取?
简单说下:
(1)找到你想从哪儿截取 end 初始值,最开始肯定是 0 啊
(2)先找到你需要截取字符串的开头,你可逆find你要截取这个字符串前面几个字符串,也可以就截取你这个字符串的开头。如果截取的是你字符串之前的,不要忘记加个len。最终找到一个起始点 start
(3)截取你想要字符串的结尾,首先我们的起始值 end 在找start的时候已经用完了,我们要把它变成咱们这个字符串的结尾。这样他下一次就又成了下一个字符串的开头。一直到全部找完。
(4)start ,end都有了,去截取吧朋友们,已经详细的令人发指了吧。

其实我建议的还是能用第二种方式用第二种方式,什么个步骤呢?
我们再来说下。
(1)现在的html太乱看不懂,让我们用BeautifulSoup整治成标准格式。bf = BeautifulSoup(html, ‘lxml’)
(2)如果在这种格式下你需要的链接包裹在规则的标签下,那完美了,把他们全找出来。targets_url = bf.find_all(class_=‘item-img’)
(3)最后用我儿子的话说快快乐乐的去遍历吧 for each in targets_url:

后面的链接就从这个for循环中取,如果用第二种方法,那恭喜你,想怎么取怎么取。例如下面这样:取了两个。一个标题,一个链接。
urls.append(each.img.get(‘alt’) + ‘=’ + each.get(‘href’))
如果你说你任性用第一种方法,要么你已经拿到了链接,那完美,这种方法刚好适合你。要么再截取一次吧,宝贝儿!

----------------------到上面链接采集完毕,后面是处理链接啦!----

首先我们要知道我们要下载图片,那肯定要建个文件夹,所以为了方便在urls取完毕之后我们先在目录下建立一个文件夹。代码:
	if imageFileName not in os.listdir():
		os.makedirs(imageFileName)

imageFileName 可以是变量,在main方法传进来,这样维护man方法的目录就行了。

接下来我们可能已经拿到图片链接,如果拿到了那么直接取吧,我这里还有一个链接,然后到另外一个页面获取下载链接。看下代码:

	for each_img in urls:
		img_info = each_img.split('=') 
		#把'XXXXXXX'='http://xxx.xxxx.xxx/mingxing/16151.html'这种字符串变成数组['XXXXXXX', 'http://xxx.xxxx.xxx/mingxing/16151.html']
		target_url = img_info[1] #链接拿出来
		filename = img_info[0]+'.jpg' #给图片起个名字
		# print('下载:' + filename)
		img_html = get_index_page(target_url)
		img_bf = BeautifulSoup(img_html, 'lxml')
		img_url = img_bf.find_all('div', class_='wr-single-content-list')
		img_bf_2 = BeautifulSoup(str(img_url), 'lxml')
		img_url = img_bf_2.div.img.get('src')

(1)我们循环了urls,把之前存的东西拿出来,如果拿出来直接就是图片url那么就去之后的方法下载,如果像我这儿拿出来不是,那就先处理。
(2)这里拿出来的str用“=”隔开了,所以我们用split方法把它变成数组each_img.split(’=’) ,取出数组的数据一般也就是拿到另外一个页面。
(3)我们之前写了BeautifulSoup方法获取页面,这就是方法的好处,可以复用,这时我们用到了,拿过来取出html。
(4)img_html = get_index_page(target_url)之后的四行代码还是一个解析,目的就是拿到图片的img_url 。所以这里怎么玩看你需要,我们这里的意思显然是

格式化页面BeautifulSoup(img_html, ‘lxml’)
找到链接img_bf.find_all(‘div’, class_=‘wr-single-content-list’)
格式化链接 BeautifulSoup(str(img_url), ‘lxml’)
找到图片url img_bf_2.div.img.get(‘src’)
这里可以看出来BeautifulSoup,和find_all不要省,多用!

---------------------------------------------------------------------

url来了我们也终于可以开始下载了。不过,万万没想到,这里来个高级货 import threading 多线程。讲多了可以再开个博客,所以直接用!
(1)
import threading #多线程用
(2)
#设置最大线程锁(一次性接受十个线程)一定要加,否则cpu会变红
thread_lock = threading.BoundedSemaphore(value=10)
(3)

	#上锁
	thread_lock.acquire()
	t = threading.Thread(target=download_pics,args=(imageFileName,img_url,filename))
	time.sleep(1)
	t.start()

(4)
#下载完了,解锁(在下载方法里download_pics)
thread_lock.release()

清晰的三个部分拿去用,第一部分你懂的(我要玩线程),第二部分不限制最大线程,牛啊!不怕cpu爆掉!一定别忘加(最多几个线程跑呢?),第三部分thread_lock.acquire()是设置好的锁头拿过来用, t = threading.Thread(target=download_pics,args=(xx,xx,xx)) 就是用线程开跑下载的方法download_pics,args就是要的参数喽。随后小睡会儿不怕累就不睡,然后start走起。第四部分前面都锁了,还不快开开,别的小朋友还要跑步呢!

---------------------------------------------------------------------

小伙伴们,上一部分提到的download_pics方法,走起:

def download_pics(imageFileName,img_url,filename):
    path = imageFileName + '/' + filename
	# urlretrieve(url = img_url,filename = path)

	# r = requests.get(img_url)
	# with open(path,'wb') as f:
	# 	f.write(r.content)  #如偏要写入用r.content

	resp = urllib.request.urlopen(img_url)
	respHtml = resp.read()
	picFile = open(path, "wb")
	picFile.write(respHtml)
	picFile.close()
	
	thread_lock.release()  #下载完了,解锁

这个方法里我们首先要拼凑出一个正确的图片网址
path = imageFileName + ‘/’ + filename
怎么拼看你自己,最后出来的网址在浏览器可以看到图片就可以。
之后是我了解的三个下载方式,怎么选看你自己(前两个注释了)
(1)# urlretrieve(url = img_url,filename = path) #额。就这么写吧!
(2)# r = requests.get(img_url) #给我url对应的内容
# with open(path,‘wb’) as f:
# f.write(r.content) #如偏要写入用r.content
url东西拿过来r,由于是图片要它的二进制数据 r.content,复习一下想要html的话就要 .text 喽!这里用了个with,为什么呢?如果不知道只能说,兄弟你要好好学基础哦,这个low哥都知道滴!文件open了就要close嘛,不想麻烦就可以这样简写代替喽!如果想麻烦,那看看第三个例子吧!
(3)
resp = urllib.request.urlopen(img_url) #打开链接返回Responses
respHtml = resp.read() #read()理解一下,read完的Resp才能写进去
picFile = open(path, “wb”) #打开这个路径,给个权限
picFile.write(respHtml) #图片弄进去
picFile.close() #2里刚说的,回去看。
三种方法,第一种简单,第二种喜欢但有时候可能下载不下来,也就是我遇到的问题,那么就换第三种解决一下吧。三种下载方法收好!
thread_lock.release() #下载方法里可别忘了去解锁啊。

download_pics 方法走完我们的爬虫也就达到了目的,下载好了图片。

方法的入口在这里:
def main(url,imageFileName):
。。。。。。。。。。
总入口:

if __name__ == '__main__':
	main("http://www.shuaia.net/index_3.html","images5")

---------------------------------------------------------------------

说了这么多来个总结吧,爬个简单页面的简单图片大多–比较简单,但是作为小白来说这里也有很多知识点。我觉得看到了就细细品味一下,之后再碰到就脸熟了。再看看他们:
(网上的实例太多了,我就不留完整例子代码了,不过看不弄那些代码的话,可以来这儿看看。)

thread_lock = threading.BoundedSemaphore(value=10)  #锁
thread_lock.acquire() #上锁
t = threading.Thread(target=download_pics,args=(path,img_url))
t.start() #跑线程
thread_lock.release() #解锁

respose.text
respose.content #这俩货都什么时候用

with open(path,'wb') as f: #这么写的另外一种写法?

BeautifulSoup(img_html, 'lxml')  #代码不好看,我查找不方便

img_bf.find_all('div', class_='wr-single-content-list')
img_bf_2.div.img.get('src')  #用尽方法找到我的好朋友,find,get 多写写,多走走。

猜你喜欢

转载自blog.csdn.net/weixin_29080725/article/details/86504915
今日推荐