博主一个月前接触python,不得不说python身为胶水语言,有着自己得天独厚的优势。博主作为编程小白,在经过一天的奋战后,写出来个凑合能用的python spider 在对代码进行改进捕捉了requestException错误之后,爬虫实测可以一直运行下去,爬到一堆污污的东西。。。
兄弟们你们贴代码给我个评论啊,冷清的一批,谢谢啊各位
爬取结果如下图:
源代码如下:
import os
import requests
from bs4 import BeautifulSoup
from multiprocessing import Pool
import time
from requests.exceptions import RequestException
def Download_gif(url,path):
headers={
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36',
'Connection':'close'
}
html=requests.get(url,headers=headers)
soup=BeautifulSoup(html.text,'html.parser')
gif_url=soup.find_all('a',class_='focus') #找出单页上的所有链接,返回一个list,这个list由一系列字典组成
for gif_url in gif_url: #迭代出每个字典
gif_url=gif_url['href'] #每个字典的key为href时对应的value为链接
html=requests.get(gif_url,headers=headers) #对解析出的链接进行请求
soup=BeautifulSoup(html.text,'html.parser') #soup库进行解析
page=soup.find('div',class_='article-paging').find_all('span') #进入链接发现是分页形式,所有找出链接上的总页数
page=page[-1].text #发现div标签,class为article-paging的标签内的最后一个span标签为页数
each_url=gif_url #这里一定要将url区分开来,一个用each_url,一个用gif_url,否则会发生未知错误,调试过程会发现
for i in range(1,int(page)+1): #构造列表生成式,对应每一页链接进行图片或gif下载
pic=each_url+str(i) #每一页链接
html=requests.get(pic,headers=headers) #请求每一页链接
soup=BeautifulSoup(html.text,'html.parser') #解析每一页链接
pic_url=soup.find_all('img',class_='aligncenter') #发现每一页链接上的img标签,class_为aligncenter的为图片或gif_url
for a_url in pic_url: #迭代出每个图片或Gif链接(为字典形式)
os.chdir(path) #将目录切换至自己电脑上的path目录
a_url=a_url['src'] #gif链接中的src对应图片链接
if a_url==None: #加入判断,如果图片无链接,pass,让爬虫能够运行下去
pass
try:
html=requests.get(a_url,headers=headers) #请求图片链接,得到图片或Gif的文件流
requests.adapters.DEFAULT_RETRIES = 5 #加入重复请求次数
file_name=a_url.split('/')[-1] #给出文件名
f=open(file_name,'wb') #写入文件
f.write(html.content)
time.sleep(0.000001)
f.close()
time.sleep(0.2)
except RequestException:
return None
if __name__=='__main__':
path='C://Users/panenmin/Desktop/GIF/' #定义path,这里可以更改为自己电脑上的路径,一定用正斜线
start_url='https://www.gifjia5.com/category/neihan/page/' #定义start_url
pool=Pool(6) #构建进程池
for i in range(1,23): #构造列表生成式
url=start_url+str(i) #构造每一页链接
pool.apply_async(Download_gif,args=(url,path)) #传入函数和函数的参数
pool.close()
pool.join()
代码的逻辑确实有点混乱,主要思路是定义一个爬取单页的函数。该函数有三层迭代嵌套。第一层迭代出所有的单页上的链接,找出每个链接上的页数之后,构造列表生成式,对每一页进行循环,筛选出真正的图片Gif链接,对于每一个gif or jpg链接,requests请求得到图片或gif文件流,并写入文件。
对于Main函数,思路为对于首页的分页进行循环执行定义的Download_gif函数,即对每页上的链接进行函数流程的执行。同时加入了多进程Pool。
在函数内部,用到了time模块,time.sleep()是让spider向服务器请求的不那么频繁,防止封ip等等骚操作。
虽然这个spider比较rubbish,但是也是我code半天写出来的,还希望刚入门爬虫的朋友们能够从里边学到一点东西,同时明天我将贴上具体的开发过程。(楼主苦逼上班族,但是比较闲。)
附上我最喜欢的一句话,talk is cheap,show me the code
开发过程:
1:首先进入gif发源地首页,查看页面布局
用chrome浏览器开发者选项,发现如下:
可以发现a标签,class属性为focus的节点里面包含有首页所有的链接
href对应的即为首页上所有的链接
打开开发者选项,找出最大页数以及jpg or gif链接
找出最大页数:
找出链接后,对每页进行循环请求图片or gif 链接,得到文件流,写入文件。
以上函数部分的爬取思路,即爬单页思路,对于爬取多页,思路很简单了,总共23页,循环爬取
if name==‘main’:
path=‘C://Users/panenmin/Desktop/GIF/’ #定义path,这里可以更改为自己电脑上的路径,一定用正斜线
start_url=‘https://www.gifjia5.com/category/neihan/page/’ #定义start_url
pool=Pool(6) #构建进程池
for i in range(1,23): #构造列表生成式
url=start_url+str(i) #构造每一页链接
pool.apply_async(Download_gif,args=(url,path)) #传入函数和函数的参数
pool.close()
pool.join()
并且将爬取单页的函数参数传进去,大功告成。但是博主发现,该爬虫需要改进的地方仍有很多,比如爬取一段时间,会发现远程主机强制让爬虫掉线(短暂性封Ip),考虑加入代理池 。开发过程中遇到许多问题,也算是边学边用,知行合一。希望刚入门爬虫的朋友们争取自己写出点东西出来,这样理解才更深刻。
更新一下代码,博主在爬取的时候出现了关于file_name的os错误,故更新源代码。对file_name进行判断`
import os
import requests
from bs4 import BeautifulSoup
from multiprocessing import Pool
import time
from requests.exceptions import RequestException
def Download_gif(url,path):
headers={
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36',
'Connection':'close'
}
html=requests.get(url,headers=headers)
soup=BeautifulSoup(html.text,'html.parser')
gif_url=soup.find_all('a',class_='focus') #找出单页上的所有链接,返回一个list,这个list由一系列字典组成
for gif_url in gif_url: #迭代出每个字典
gif_url=gif_url['href'] #每个字典的key为href时对应的value为链接
html=requests.get(gif_url,headers=headers) #对解析出的链接进行请求
soup=BeautifulSoup(html.text,'html.parser') #soup库进行解析
page=soup.find('div',class_='article-paging').find_all('span') #进入链接发现是分页形式,所有找出链接上的总页数
page=page[-1].text #发现div标签,class为article-paging的标签内的最后一个span标签为页数
each_url=gif_url #这里一定要将url区分开来,一个用each_url,一个用gif_url,否则会发生未知错误,调试过程会发现
for i in range(1,int(page)+1): #构造列表生成式,对应每一页链接进行图片或gif下载
pic=each_url+str(i) #每一页链接
html=requests.get(pic,headers=headers) #请求每一页链接
soup=BeautifulSoup(html.text,'html.parser') #解析每一页链接
pic_url=soup.find_all('img',class_='aligncenter') #发现每一页链接上的img标签,class_为aligncenter的为图片或gif_url
for a_url in pic_url: #迭代出每个图片或Gif链接(为字典形式)
os.chdir(path) #将目录切换至自己电脑上的path目录
a_url=a_url['src'] #gif链接中的src对应图片链接
file_name=a_url.split(r'/')[-1]
if file_name[-4:]!='.gif' and file_name[-4:]!='.jpg' and file_name[-4:]!='jpeg':
return None
if a_url==None: #加入判断,如果图片无链接,pass,让爬虫能够运行下去
pass
try:
html=requests.get(a_url,headers=headers) #请求图片链接,得到图片或Gif的文件流
requests.adapters.DEFAULT_RETRIES = 5 #加入重复请求次数
f=open(file_name,'wb')
f.write(html.content)
time.sleep(0.000001)
f.close()
time.sleep(0.2)
except RequestException:
return None
if __name__=='__main__':
path='D://GIF/' #定义path,这里可以更改为自己电脑上的路径,一定用正斜线
start_url='https://www.gifjia5.com/category/neihan/page/' #定义start_url
pool=Pool(6) #构建进程池
for i in range(1,23): #构造列表生成式
url=start_url+str(i) #构造每一页链接
pool.apply(Download_gif,args=(url,path)) #传入函数和函数的参数
print('第i页已爬完')
pool.close()
pool.join()
这里说明一下,写代码时一定要加注释,这样不只是便于别人阅读,在将来对代码出现bug时,自己可以对代码有一个清晰的思路,可以便于维护。当然,大神除外。。。