python爬虫(19)爬取论坛网站——网络上常见的gif动态图


http://blog.csdn.net/qiqiyingse http://blog.csdn.net/qiqiyingse/article/details/78501034
有段时间没有写爬虫相关的文章了,今天抽时间把之前做的一个程序分享给大家。

经常逛A站和B站的人,肯定对一个节目不陌生《网络上常见的GIF动态图

今天就来分享一下,怎么通过爬虫自动的将这些个动作收藏到自己的电脑中(其实这个程序5月份就写好了,一直拖到现在才想起来将它分享出来)。

一.思路分析

按照爬虫的基本规律:
1.找到目标
2.抓取目标
3.处理目标内容,获取有用的信息

1.首先我们的目标是:http://gifcc.com/forum.php    即找动图就上 GIFFCC.COM
python爬虫(19)爬取论坛网站——网络上常见的gif动态图

这个网站呢,是一个论坛式网站,里面分了几大类,反正试试各种动图。
我们的目标呢,就是找到这(收)些(藏)动(到)图(自)的(己)地(电)址(脑).

2.看一下各个模块的网址,看一下有什么规律

'http://gifcc.com/forum-37-1.html',#其他各种GIF动态图出处 
'http://gifcc.com/forum-38-1.html', #美女GIF动态图出处 
'http://gifcc.com/forum-47-1.html',#科幻奇幻电影GIF动态图出处
'http://gifcc.com/forum-48-1.html',#喜剧搞笑电影GIF动态图出处
'http://gifcc.com/forum-49-1.html',#动作冒险电影GIF动态图出处
'http://gifcc.com/forum-50-1.html'#恐怖惊悚电影GIF动态图出处
对的,没错,如果以游客身份访问,那么各个板块的网址就是这样的形式 http://gifcc.com/forum-XX -1.html
那么每个模块中的内容又有什么规律? 来直接上图:
python爬虫(19)爬取论坛网站——网络上常见的gif动态图


我们关注的是当前页的网址,以及这个页码数,跳到第二页之后,地址变成:http://gifcc.com/forum-38-2.html
那么也就是说 网址的 规律就是 http://gifcc.com/forum-XX-XX.html
这里注意一点,网站的图片是动态加载的, 只有你往下滑动的时候,下面的图片才会逐渐的显现出来,这个暂且记下


3.每一张动图的所在页面的规律

python爬虫(19)爬取论坛网站——网络上常见的gif动态图
其实这个没啥规律,但是只要我们找到单个图片的地址,就没啥难处理的了.

二 开工动手

python爬虫(19)爬取论坛网站——网络上常见的gif动态图
1.获取入口页面内容
即根据传入的URL,获取整个页面的源码
[python] view plain copy
  1. #仅仅获取页面内容  
  2. def get_html_Pages(self,url):    
  3.     try:     
  4.         #browser = webdriver.PhantomJS(executable_path=r'C:\Python27\Scripts\phantomjs.exe')   
  5.         browser = webdriver.PhantomJS()   
  6.         browser.get(url)  
  7.         html = browser.execute_script("return document.documentElement.outerHTML")  
  8.         browser.close()  
  9.         html=HTMLParser.HTMLParser().unescape(html).decode('utf-8')  
  10.         return html  
  11.        #捕捉异常,防止程序直接死掉      
  12.     except Exception,e:    
  13.         print u"连接失败,错误原因",e  
  14.         return None     
这里我们使用了webdriver以及PhantomJS 这些模块,为什么呢?因为网页是动态加载的,这样可以抓取的数据全一点.
那这里还有个疑问, 为什么没有滑动啊什么的,得到的数据

2.获取页码数
[python] view plain copy
  1. #获取页码         
  2. def get_page_num(self,html):  
  3.   
  4.     doc = pq(html)    
  5.     print u'开始获取总页码'  
  6.     #print doc('head')('title').text()#获取当前title  
  7.     try:  
  8.         #如果当前页面太多,超过8页以上,就使用另一种方式获取页码  
  9.         if doc('div[class="pg"]')('[class="last"]'):  
  10.             num_content= doc('div[class="pg"]')('[class="last"]').attr('href')  
  11.             print  num_content.split('-')[1].split('.')[0]  
  12.             return num_content.split('-')[1].split('.')[0]  
  13.         else:  
  14.             num_content= doc('div[class="pg"]')('span')  
  15.             return filter(str.isdigit,str(num_content.text()))[0]  
  16.     #如果获取页码失败,那么就返回1, 即值获取1页内容    
  17.     except Exception,e:  
  18.         print u'获取页码失败'.e  
  19.         return '1'  

这里的页码处理用到了一个模块pq, 即  PyQuery  
 from pyquery import PyQuery as pq 
采用PyQuery的方式查找我们需要的元素,感觉更好处理一点,挺方便的
同时这里的处理稍微有点意思,如果观察这个页面的话,会发现,每个模块的页码数,在上面和下面都有一个,然后我这里裁取的一下,因为我们只需要一个页码数字即可


3-6 第三步到第六步一起来说
其实就是根据页码数,来进行遍历,获取到每一页的内容
然后得到每一页中的所有图片地址

[python] view plain copy
  1. print  u'总共有 %d页内容' % int(page_num)  
  2. #3.遍历每一页的内容  
  3. for num in range(1,int(page_num)):  
  4.     #4.组装新的url  
  5.     new_url = self.url.replace( self.url.split('-')[2],(str(num)+'.html') )  
  6.     print u'即将获取的页面是:',new_url  
  7.     #5.加载每一页内容,获取gif list 的内容  
  8.     items=self.parse_items_by_html(self.get_all_page(new_url))  
  9.     print u'在第%d页,找到了%d 个图片内容' % (num,len(items))  
  10.     #6.处理每一个元素的内容  
  11.     self.get_items_url(items,num)  
在进行获取每一页的内容的时候,需要重新组装页面地址。
[python] view plain copy
  1. #4.组装新的url  
  2.                 new_url = self.url.replace( self.url.split('-')[2],(str(num)+'.html') )  
  3.                 print u'即将获取的页面是:',new_url  
有了新的地址,就可以获取当前页面的内容,并进行数据处理,得到每一张图片的地址列表

[python] view plain copy
  1. #5.加载每一页内容,获取gif list 的内容  
  2.                 items=self.parse_items_by_html(self.get_all_page(new_url))  
  3.                 print u'在第%d页,找到了%d 个图片内容' % (num,len(items))  
[python] view plain copy
  1. #解析页面内容,获取gif的图片list  
  2. def parse_items_by_html(self, html):    
  3.     doc = pq(html)    
  4.     print u'开始查找内容msg'       
  5.     return doc('div[class="c cl"]')  
在获取到图片列表后,再次解析,获取每一张图片的URL
[python] view plain copy
  1. #解析gif 的list ,处理每一个gif内容  
  2.     def get_items_url(self,items,num):  
  3.         i=1  
  4.         for article in items.items():  
  5.             print u'开始处理数据(%d/%d)' % (i, len(items))  
  6.             #print article  
  7.             self.get_single_item(article,i,num)  
  8.             i +=1  
  9.       
  10.     #处理单个gif内容,获取其地址,gif 最终地址  
  11.     def get_single_item(self,article,num,page_num):  
  12.         gif_dict={}  
  13.         #每个页面的地址  
  14.         gif_url= 'http://gifcc.com/'+article('a').attr('href')  
  15.         #每个页面的标题  
  16.         gif_title= article('a').attr('title')  
  17.           
  18.         #每张图的具体地址  
  19.         #html=self.get_html_Pages(gif_url)  
  20.         #gif_final_url=self.get_final_gif_url(html)  
  21.        
  22.         gif_dict['num']=num  
  23.         gif_dict['page_num']=page_num  
  24.         gif_dict['gif_url']=gif_url  
  25.         gif_dict['gif_title']=gif_title  
  26.         self.gif_list.append(gif_dict)  
  27.         data=u'第'+str(page_num)+'页|\t'+str(num)+'|\t'+gif_title+'|\t'+gif_url+'\n'  
  28.         self.file_flag.write(data)  
在这里,把数据整合一下,为将数据写入数据库做准备

7.将图片存到本地,以及将数据写入数据库

[python] view plain copy
  1. #使用urllib2来获取图片最终地址  
  2.     def get_final_gif_url_use_urllib2(self,url):  
  3.         try:  
  4.             html= urllib2.urlopen(url).read()  
  5.             gif_pattern=re.compile('<div align="center.*?<img id=.*?src="(.*?)" border.*?>',re.S)  
  6.             return re.search(gif_pattern,html).group(1)  
  7.         except Exception,e:  
  8.             print u'获取页面内容出错:',e  
  9.     #最终处理   存贮数据  
  10.     def get_gif_url_and_save_gif(self):  
  11.         def save_gif(url,name):  
  12.             try:  
  13.                 urllib.urlretrieve(url, name)  
  14.             except Exception,e:  
  15.                 print '存贮失败,原因:',e  
  16.         for i in range(0,len(self.gif_list)):  
  17.             gif_dict=self.gif_list[i]  
  18.             gif_url=gif_dict['gif_url']  
  19.             gif_title=gif_dict['gif_title']  
  20.               
  21.             #依然使用webdriver获取最终的gif地址  
  22.             final_html=self.get_html_Pages(gif_url)  
  23.             gif_final_url=self.get_final_gif_url(final_html)  
  24.             #使用另外一种方式(urllib2)获取最终地址  
  25.             #gif_final_url=self.get_final_gif_url_use_urllib2(gif_url)  
  26.               
  27.             gif_dict['gif_final_url']=gif_final_url  
  28.             print u'开始向数据库写入第%d页第%d项数据,并开始存贮图片到本地 ' % (gif_dict['page_num'],gif_dict['num'])  
  29.             self.BookTable.insert_one(gif_dict)  
  30.             gif_name=self.dir_name+'/'+gif_title+'.gif'  
  31.             save_gif(gif_final_url,gif_name)  
到这里其实大体的内容已经完成了.

我们能够将这个论坛各个模块的动图都存到本地,同时呢,也将数据放入到了数据库中

三 数据库的筛选

在完成了将数据放入到数据库的之后, 我想着可以直接通过调用数据库,将图片保存
(为什么有这个想法呢,因为我发现如果直接在主程序中存贮图片,它跑的太慢了,不如将数据都放到数据库中,之后专门调用数据库来贮存图片)
但是这里发现一个问题,数据中的内容挺多的,然后发现了好多内容是重复的,因此我们需要对数据库进行去重
关于数据去重的内容,其实我之前的文章已经写过了(写那篇文章的时候,这个爬虫已经完成了呢~)
主要思路是针对某一个元素的数量进行操作,pymongo里面有一个方法是可以统计指定元素的数量的,如果当前元素只有一个,就不管,不是一个元素,就删除
核心代码如下:

[python] view plain copy
  1. for url in collection.distinct('name'):#使用distinct方法,获取每一个独特的元素列表  
  2.         num= collection.count({"name":url})#统计每一个元素的数量  
  3.         print num  
  4.         for i in range(1,num):#根据每一个元素的数量进行删除操作,当前元素只有一个就不再删除  
  5.             print 'delete %s %d times '% (url,i)  
  6.             #注意后面的参数, 很奇怪,在mongo命令行下,它为1时,是删除一个元素,这里却是为0时删除一个  
  7.             collection.remove({"name":url},0)  
  8.         for i in  collection.find({"name":url}):#打印当前所有元素  
  9.             print i  
  10.     print collection.distinct('name')#再次打印一遍所要去重的元素  

四 读取数据库中的内容,存贮图片

数据去重之后,再次进行图片的存贮,就方便多了
之后如果图片删除了,也不用重新跑一边,或者说有时候本地图片占地方,那么只用保存有数据库的数据就好了
核心代码如下:

[python] view plain copy
  1. def save_gif(url,name):  
  2.     try:  
  3.         urllib.urlretrieve(url, name)  
  4.     except Exception,e:  
  5.         print u'存贮失败,原因:',e  
  6. client = pymongo.MongoClient('localhost'27017)   
  7. print client.database_names()  
  8.   
  9.   
  10. db = client.GifDB  
  11. for table in  db.collection_names():  
  12.     print 'table name is ',table  
  13.     collection=db[table]  
  14.   
  15.     for item in  collection.find():  
  16.         try:   
  17.             if item['gif_final_url']:  
  18.                 url,url_title= item['gif_final_url'],item['gif_title']  
  19.                 gif_filename=table+'/'+url_title+'.gif'  
  20.                 print 'start save %s, %s' % (url,gif_filename)  
  21.                 save_gif(url,gif_filename)  
  22.         except Exception,e:  
  23.             print u'错误原因:',e  
python爬虫(19)爬取论坛网站——网络上常见的gif动态图

完整代码

01_get_gif_url.py
[python] view plain copy
  1. #coding: utf-8   
  2. from pyquery import PyQuery as pq    
  3. from selenium import webdriver   
  4. import HTMLParser,urllib2,urllib,re,os  
  5.   
  6. import pymongo  
  7.   
  8. import time  
  9. import sys    
  10. reload(sys)    
  11. sys.setdefaultencoding('utf-8')    
  12. class download_gif:  
  13.     def __init__(self):  
  14.         self.url='http://gifcc.com/forum-38-1.html'  
  15.         self.url_list=['http://gifcc.com/forum-37-1.html',#其他各种GIF动态图出处   
  16.         'http://gifcc.com/forum-38-1.html'#美女GIF动态图出处   
  17.         'http://gifcc.com/forum-47-1.html',#科幻奇幻电影GIF动态图出处  
  18.         'http://gifcc.com/forum-48-1.html',#喜剧搞笑电影GIF动态图出处  
  19.         'http://gifcc.com/forum-49-1.html',#动作冒险电影GIF动态图出处  
  20.         'http://gifcc.com/forum-50-1.html'#恐怖惊悚电影GIF动态图出处  
  21.         ]  
  22.         self.choices={'1':u'其他各种GIF动态图出处',  
  23.         '2':u'美女GIF动态图出处',  
  24.         '3':u'科幻奇幻电影GIF动态图出处',  
  25.         '4':u'喜剧搞笑电影GIF动态图出处',  
  26.         '5':u'动作冒险电影GIF动态图出处',  
  27.         '6':u'恐怖惊悚电影GIF动态图出处'  
  28.         }  
  29.           
  30.         self.dir_name=u'gif出处'  
  31.         self.gif_list=[]  
  32.           
  33.         self.connection = pymongo.MongoClient()    
  34.           
  35.         #BookTable.insert_one(dict_data)#插入单条数据    
  36.         #BookTable.insert(dict_data)#插入 字典list 数据   
  37.           
  38.     #获取页面内容,并且加载JS, 通过滚动获取页面更多的元素  
  39.     def get_all_page(self,url):  
  40.         try:  
  41.             #browser = webdriver.PhantomJS(executable_path=r'C:\Python27\Scripts\phantomjs.exe')   
  42.             browser = webdriver.PhantomJS()   
  43.             browser.get(url)  
  44.             #time.sleep(3)   
  45.             #页面滚动  
  46.             js = "var q=document.body.scrollTop=100000"      
  47.             #for i in range(5):  #调试语句,先暂时不加载太多次数  
  48.             for i in range(30):    
  49.                 #循环执行下滑页面50次    
  50.                 browser.execute_script(js)    
  51.                 #加载一次,休息一下    
  52.                 time.sleep(1)  
  53.                 print u'这是第 %d 次划动页面' % i  
  54.             # 执行js得到整个页面内容  
  55.             html = browser.execute_script("return document.documentElement.outerHTML")  
  56.             browser.close()  
  57.             html=HTMLParser.HTMLParser().unescape(html)  
  58.             return html  
  59.         except Exception,e:  
  60.             print u'发生错误:',e  
  61.       
  62.     #解析页面内容,获取gif的图片list  
  63.     def parse_items_by_html(self, html):    
  64.         doc = pq(html)    
  65.         print u'开始查找内容msg'       
  66.         return doc('div[class="c cl"]')  
  67.           
  68.     #解析gif 的list ,处理每一个gif内容  
  69.     def get_items_url(self,items,num):  
  70.         i=1  
  71.         for article in items.items():  
  72.             print u'开始处理数据(%d/%d)' % (i, len(items))  
  73.             #print article  
  74.             self.get_single_item(article,i,num)  
  75.             i +=1  
  76.       
  77.     #处理单个gif内容,获取其地址,gif 最终地址  
  78.     def get_single_item(self,article,num,page_num):  
  79.         gif_dict={}  
  80.         #每个页面的地址  
  81.         gif_url= 'http://gifcc.com/'+article('a').attr('href')  
  82.         #每个页面的标题  
  83.         gif_title= article('a').attr('title')  
  84.           
  85.         #每张图的具体地址  
  86.         #html=self.get_html_Pages(gif_url)  
  87.         #gif_final_url=self.get_final_gif_url(html)  
  88.        
  89.         gif_dict['num']=num  
  90.         gif_dict['page_num']=page_num  
  91.         gif_dict['gif_url']=gif_url  
  92.         gif_dict['gif_title']=gif_title  
  93.         self.gif_list.append(gif_dict)  
  94.         data=u'第'+str(page_num)+'页|\t'+str(num)+'|\t'+gif_title+'|\t'+gif_url+'\n'  
  95.         self.file_flag.write(data)  
  96.       
  97.     #通过webdriver获得页面内容后,获得最终地址  
  98.     def get_final_gif_url(self,html):  
  99.         doc = pq(html)   
  100.         image_content= doc('td[class="t_f"]')  
  101.         gif_url= image_content('img').attr('src')  
  102.         return gif_url  
  103.       
  104.     #使用urllib2来获取图片最终地址  
  105.     def get_final_gif_url_use_urllib2(self,url):  
  106.         try:  
  107.             html= urllib2.urlopen(url).read()  
  108.             gif_pattern=re.compile('<div align="center.*?<img id=.*?src="(.*?)" border.*?>',re.S)  
  109.             return re.search(gif_pattern,html).group(1)  
  110.         except Exception,e:  
  111.             print u'获取页面内容出错:',e  
  112.     #最终处理   存贮数据  
  113.     def get_gif_url_and_save_gif(self):  
  114.         def save_gif(url,name):  
  115.             try:  
  116.                 urllib.urlretrieve(url, name)  
  117.             except Exception,e:  
  118.                 print '存贮失败,原因:',e  
  119.         for i in range(0,len(self.gif_list)):  
  120.             gif_dict=self.gif_list[i]  
  121.             gif_url=gif_dict['gif_url']  
  122.             gif_title=gif_dict['gif_title']  
  123.               
  124.             #依然使用webdriver获取最终的gif地址  
  125.             final_html=self.get_html_Pages(gif_url)  
  126.             gif_final_url=self.get_final_gif_url(final_html)  
  127.             #使用另外一种方式(urllib2)获取最终地址  
  128.             #gif_final_url=self.get_final_gif_url_use_urllib2(gif_url)  
  129.               
  130.             gif_dict['gif_final_url']=gif_final_url  
  131.             print u'开始向数据库写入第%d页第%d项数据,并开始存贮图片到本地 ' % (gif_dict['page_num'],gif_dict['num'])  
  132.             self.BookTable.insert_one(gif_dict)  
  133.             gif_name=self.dir_name+'/'+gif_title+'.gif'  
  134.             save_gif(gif_final_url,gif_name)  
  135.           
  136.     #仅仅获取页面内容  
  137.     def get_html_Pages(self,url):    
  138.         try:     
  139.             #browser = webdriver.PhantomJS(executable_path=r'C:\Python27\Scripts\phantomjs.exe')   
  140.             browser = webdriver.PhantomJS()   
  141.             browser.get(url)  
  142.             html = browser.execute_script("return document.documentElement.outerHTML")  
  143.             browser.close()  
  144.             html=HTMLParser.HTMLParser().unescape(html).decode('utf-8')  
  145.             return html  
  146.         #捕捉异常,防止程序直接死掉      
  147.         except Exception,e:    
  148.             print u"连接失败,错误原因",e  
  149.             return None     
  150.       
  151.     #获取页码         
  152.     def get_page_num(self,html):  
  153.   
  154.         doc = pq(html)    
  155.         print u'开始获取总页码'  
  156.         #print doc('head')('title').text()#获取当前title  
  157.         try:  
  158.             #如果当前页面太多,超过8页以上,就使用另一种方式获取页码  
  159.             if doc('div[class="pg"]')('[class="last"]'):  
  160.                 num_content= doc('div[class="pg"]')('[class="last"]').attr('href')  
  161.                 print  num_content.split('-')[1].split('.')[0]  
  162.                 return num_content.split('-')[1].split('.')[0]  
  163.             else:  
  164.                 num_content= doc('div[class="pg"]')('span')  
  165.                 return filter(str.isdigit,str(num_content.text()))[0]  
  166.         #如果获取页码失败,那么就返回1, 即值获取1页内容    
  167.         except Exception,e:  
  168.             print u'获取页码失败'.e  
  169.             return '1'  
  170.               
  171.         # filter(str.isdigit,num_content)#从字符串中提取数字  
  172.           
  173.     #创建文件夹    
  174.     def mk_dir(self,path):  
  175.         if not os.path.exists(path):    
  176.             os.makedirs(path)   
  177.               
  178.     def set_db(self,tablename):  
  179.         self.BookDB = self.connection.GifDB         #数据库db的名字    
  180.         self.BookTable =self.BookDB[tablename]           #数据库table表的名字    
  181.               
  182.     #主函数          
  183.     def run(self):  
  184.         choice_type=5  
  185.         if choice_type:  
  186.         #for choice_type in range(len(self.choices)):   
  187.             if  choice_type+1:  
  188.                   
  189.                 self.dir_name=self.choices[str(choice_type+1)].strip()  
  190.                 self.url=self.url_list[int(choice_type)]  
  191.                   
  192.                   
  193.                 print self.dir_name,self.url  
  194.           
  195.           
  196.             #0.创建文件夹存贮图片,建立文件存贮内容  
  197.             self.mk_dir(self.dir_name)  
  198.             self.filename=self.dir_name+'/'+self.dir_name+'.txt'  
  199.             print self.filename  
  200.             self.file_flag=open(self.filename,'w')  
  201.               
  202.             self.set_db(self.dir_name)  
  203.             self.BookTable .insert({'filename':self.dir_name})  
  204.               
  205.             print self.url  
  206.             #1.获取入口页面内容  
  207.             html=self.get_html_Pages(self.url)  
  208.               
  209.             #2.获取页码数目  
  210.             page_num=self.get_page_num(html)  
  211.               
  212.             print  u'总共有 %d页内容' % int(page_num)  
  213.             #3.遍历每一页的内容  
  214.               
  215.             #page_num=3#调试语句,先暂时将页面内容设置的小一点  
  216.             for num in range(1,int(page_num)):  
  217.                 #4.组装新的url  
  218.                 new_url = self.url.replace( self.url.split('-')[2],(str(num)+'.html') )  
  219.                 print u'即将获取的页面是:',new_url  
  220.                 #5.加载每一页内容,获取gif list 的内容  
  221.                 items=self.parse_items_by_html(self.get_all_page(new_url))  
  222.                 print u'在第%d页,找到了%d 个图片内容' % (num,len(items))  
  223.                 #6.处理每一个元素的内容  
  224.                 self.get_items_url(items,num)  
  225.               
  226.             #5.数据全部抓取完毕,开始处理数据  
  227.             self.get_gif_url_and_save_gif()  
  228.             print 'success'  
  229.               
  230.             self.file_flag.close()  
  231.           
  232.               
  233. if __name__ == '__main__':    
  234.     print u''''' 
  235.             **************************************************   
  236.             **    Welcome to Spider of  GIF 出处图片        **   
  237.             **         Created on 2017-05-21                **   
  238.             **         @author: Jimy _Fengqi                **   
  239.             **************************************************  
  240.     '''           
  241.     print u''''' 选择你要下载的gif图片类型 
  242.         1:'其他各种GIF动态图出处' 
  243.         2:'美女GIF动态图出处' 
  244.         3:'科幻奇幻电影GIF动态图出处' 
  245.         4:'喜剧搞笑电影GIF动态图出处' 
  246.         5:'动作冒险电影GIF动态图出处' 
  247.         6:'恐怖惊悚电影GIF动态图出处' 
  248.         '''  
  249.     #选择要下载的类型     
  250.   
  251.     mydownload=download_gif()  
  252.     html=mydownload.run()  
02_delete_repeat_url_in_mongodb.py

[python] view plain copy
  1. #coding: utf-8   
  2. from pyquery import PyQuery as pq    
  3. from selenium import webdriver   
  4. import HTMLParser,urllib2,urllib,re,os  
  5.   
  6. import pymongo  
  7.   
  8. import time  
  9. import sys    
  10. reload(sys)    
  11. sys.setdefaultencoding('utf-8')    
  12.   
  13. import pymongo    
  14.   
  15. def save_gif(url,name):  
  16.     try:  
  17.         urllib.urlretrieve(url, name)  
  18.     except Exception,e:  
  19.         print '存贮失败,原因:',e  
  20.           
  21. def print_database_and_table_name():      
  22.     import pymongo  
  23.     client = pymongo.MongoClient('localhost'27017)   
  24.     print client.database_names()  
  25.   
  26.     for database in client.database_names():  
  27.         for table in  client[database].collection_names():  
  28.             print 'table  [%s]  is in database [%s]' % (table,database)  
  29.   
  30. def delete_single_database_repeat_data():  
  31.     import pymongo  
  32.     client = pymongo.MongoClient('localhost'27017)   
  33.     db=client.GifDBtemptemp2#这里是将要清洗数据的数据库名字  
  34.     for table in  db.collection_names():  
  35.         print 'table name is ',table  
  36.         collection=db[table]  
  37.         for url in collection.distinct('gif_title'):#使用distinct方法,获取每一个独特的元素列表  
  38.             num= collection.count({"gif_title":url})#统计每一个元素的数量  
  39.             print num  
  40.             for i in range(1,num):#根据每一个元素的数量进行删除操作,当前元素只有一个就不再删除  
  41.                 print 'delete %s %d times '% (url,i)  
  42.                 #注意后面的参数, 很奇怪,在mongo命令行下,它为1时,是删除一个元素,这里却是为0时删除一个  
  43.                 collection.remove({"gif_title":url},0)  
  44.             for i in  collection.find({"gif_title":url}):#打印当前所有元素  
  45.                 print i  
  46.   
  47. def delete_repeat_data():  
  48.     import pymongo  
  49.     client = pymongo.MongoClient('localhost'27017)   
  50.     db = client.local  
  51.     collection = db.person  
  52.       
  53.     for url in collection.distinct('name'):#使用distinct方法,获取每一个独特的元素列表  
  54.         num= collection.count({"name":url})#统计每一个元素的数量  
  55.         print num  
  56.         for i in range(1,num):#根据每一个元素的数量进行删除操作,当前元素只有一个就不再删除  
  57.             print 'delete %s %d times '% (url,i)  
  58.             #注意后面的参数, 很奇怪,在mongo命令行下,它为1时,是删除一个元素,这里却是为0时删除一个  
  59.             collection.remove({"name":url},0)  
  60.         for i in  collection.find({"name":url}):#打印当前所有元素  
  61.             print i  
  62.     print collection.distinct('name')#再次打印一遍所要去重的元素  
  63. delete_single_database_repeat_data()  

03_from_mongodb_save_pic.py

[python] view plain copy
  1. #coding: utf-8   
  2. from pyquery import PyQuery as pq    
  3. from selenium import webdriver   
  4. import HTMLParser,urllib2,urllib,re,os  
  5.   
  6. import pymongo  
  7.   
  8. import time  
  9. import sys    
  10. reload(sys)    
  11. sys.setdefaultencoding('utf-8')    
  12.   
  13. import pymongo    
  14.   
  15. def save_gif(url,name):  
  16.     try:  
  17.         urllib.urlretrieve(url, name)  
  18.     except Exception,e:  
  19.         print u'存贮失败,原因:',e  
  20. client = pymongo.MongoClient('localhost'27017)   
  21. print client.database_names()  
  22.   
  23.   
  24. db = client.GifDB  
  25. for table in  db.collection_names():  
  26.     print 'table name is ',table  
  27.     collection=db[table]  
  28.   
  29.     for item in  collection.find():  
  30.         try:   
  31.             if item['gif_final_url']:  
  32.                 url,url_title= item['gif_final_url'],item['gif_title']  
  33.                 gif_filename=table+'/'+url_title+'.gif'  
  34.                 print 'start save %s, %s' % (url,gif_filename)  
  35.                 save_gif(url,gif_filename)  
  36.         except Exception,e:  
  37.             print u'错误原因:',e  
Github地址:https://github.com/JimyFengqi/Gif_Spide
r

经常逛A站和B站的人,肯定对一个节目不陌生《网络上常见的GIF动态图

今天就来分享一下,怎么通过爬虫自动的将这些个动作收藏到自己的电脑中(其实这个程序5月份就写好了,一直拖到现在才想起来将它分享出来)。

一.思路分析

按照爬虫的基本规律:
1.找到目标
2.抓取目标
3.处理目标内容,获取有用的信息

1.首先我们的目标是:http://gifcc.com/forum.php    即找动图就上 GIFFCC.COM
python爬虫(19)爬取论坛网站——网络上常见的gif动态图

这个网站呢,是一个论坛式网站,里面分了几大类,反正试试各种动图。
我们的目标呢,就是找到这(收)些(藏)动(到)图(自)的(己)地(电)址(脑).

2.看一下各个模块的网址,看一下有什么规律

'http://gifcc.com/forum-37-1.html',#其他各种GIF动态图出处 
'http://gifcc.com/forum-38-1.html', #美女GIF动态图出处 
'http://gifcc.com/forum-47-1.html',#科幻奇幻电影GIF动态图出处
'http://gifcc.com/forum-48-1.html',#喜剧搞笑电影GIF动态图出处
'http://gifcc.com/forum-49-1.html',#动作冒险电影GIF动态图出处
'http://gifcc.com/forum-50-1.html'#恐怖惊悚电影GIF动态图出处
对的,没错,如果以游客身份访问,那么各个板块的网址就是这样的形式 http://gifcc.com/forum-XX -1.html
那么每个模块中的内容又有什么规律? 来直接上图:
python爬虫(19)爬取论坛网站——网络上常见的gif动态图


我们关注的是当前页的网址,以及这个页码数,跳到第二页之后,地址变成:http://gifcc.com/forum-38-2.html
那么也就是说 网址的 规律就是 http://gifcc.com/forum-XX-XX.html
这里注意一点,网站的图片是动态加载的, 只有你往下滑动的时候,下面的图片才会逐渐的显现出来,这个暂且记下


3.每一张动图的所在页面的规律

python爬虫(19)爬取论坛网站——网络上常见的gif动态图
其实这个没啥规律,但是只要我们找到单个图片的地址,就没啥难处理的了.

二 开工动手

python爬虫(19)爬取论坛网站——网络上常见的gif动态图
1.获取入口页面内容
即根据传入的URL,获取整个页面的源码
[python] view plain copy
  1. #仅仅获取页面内容  
  2. def get_html_Pages(self,url):    
  3.     try:     
  4.         #browser = webdriver.PhantomJS(executable_path=r'C:\Python27\Scripts\phantomjs.exe')   
  5.         browser = webdriver.PhantomJS()   
  6.         browser.get(url)  
  7.         html = browser.execute_script("return document.documentElement.outerHTML")  
  8.         browser.close()  
  9.         html=HTMLParser.HTMLParser().unescape(html).decode('utf-8')  
  10.         return html  
  11.        #捕捉异常,防止程序直接死掉      
  12.     except Exception,e:    
  13.         print u"连接失败,错误原因",e  
  14.         return None     
这里我们使用了webdriver以及PhantomJS 这些模块,为什么呢?因为网页是动态加载的,这样可以抓取的数据全一点.
那这里还有个疑问, 为什么没有滑动啊什么的,得到的数据

2.获取页码数
[python] view plain copy
  1. #获取页码         
  2. def get_page_num(self,html):  
  3.   
  4.     doc = pq(html)    
  5.     print u'开始获取总页码'  
  6.     #print doc('head')('title').text()#获取当前title  
  7.     try:  
  8.         #如果当前页面太多,超过8页以上,就使用另一种方式获取页码  
  9.         if doc('div[class="pg"]')('[class="last"]'):  
  10.             num_content= doc('div[class="pg"]')('[class="last"]').attr('href')  
  11.             print  num_content.split('-')[1].split('.')[0]  
  12.             return num_content.split('-')[1].split('.')[0]  
  13.         else:  
  14.             num_content= doc('div[class="pg"]')('span')  
  15.             return filter(str.isdigit,str(num_content.text()))[0]  
  16.     #如果获取页码失败,那么就返回1, 即值获取1页内容    
  17.     except Exception,e:  
  18.         print u'获取页码失败'.e  
  19.         return '1'  

这里的页码处理用到了一个模块pq, 即  PyQuery  
 from pyquery import PyQuery as pq 
采用PyQuery的方式查找我们需要的元素,感觉更好处理一点,挺方便的
同时这里的处理稍微有点意思,如果观察这个页面的话,会发现,每个模块的页码数,在上面和下面都有一个,然后我这里裁取的一下,因为我们只需要一个页码数字即可


3-6 第三步到第六步一起来说
其实就是根据页码数,来进行遍历,获取到每一页的内容
然后得到每一页中的所有图片地址

[python] view plain copy
  1. print  u'总共有 %d页内容' % int(page_num)  
  2. #3.遍历每一页的内容  
  3. for num in range(1,int(page_num)):  
  4.     #4.组装新的url  
  5.     new_url = self.url.replace( self.url.split('-')[2],(str(num)+'.html') )  
  6.     print u'即将获取的页面是:',new_url  
  7.     #5.加载每一页内容,获取gif list 的内容  
  8.     items=self.parse_items_by_html(self.get_all_page(new_url))  
  9.     print u'在第%d页,找到了%d 个图片内容' % (num,len(items))  
  10.     #6.处理每一个元素的内容  
  11.     self.get_items_url(items,num)  
在进行获取每一页的内容的时候,需要重新组装页面地址。
[python] view plain copy
  1. #4.组装新的url  
  2.                 new_url = self.url.replace( self.url.split('-')[2],(str(num)+'.html') )  
  3.                 print u'即将获取的页面是:',new_url  
有了新的地址,就可以获取当前页面的内容,并进行数据处理,得到每一张图片的地址列表

[python] view plain copy
  1. #5.加载每一页内容,获取gif list 的内容  
  2.                 items=self.parse_items_by_html(self.get_all_page(new_url))  
  3.                 print u'在第%d页,找到了%d 个图片内容' % (num,len(items))  
[python] view plain copy
  1. #解析页面内容,获取gif的图片list  
  2. def parse_items_by_html(self, html):    
  3.     doc = pq(html)    
  4.     print u'开始查找内容msg'       
  5.     return doc('div[class="c cl"]')  
在获取到图片列表后,再次解析,获取每一张图片的URL
[python] view plain copy
  1. #解析gif 的list ,处理每一个gif内容  
  2.     def get_items_url(self,items,num):  
  3.         i=1  
  4.         for article in items.items():  
  5.             print u'开始处理数据(%d/%d)' % (i, len(items))  
  6.             #print article  
  7.             self.get_single_item(article,i,num)  
  8.             i +=1  
  9.       
  10.     #处理单个gif内容,获取其地址,gif 最终地址  
  11.     def get_single_item(self,article,num,page_num):  
  12.         gif_dict={}  
  13.         #每个页面的地址  
  14.         gif_url= 'http://gifcc.com/'+article('a').attr('href')  
  15.         #每个页面的标题  
  16.         gif_title= article('a').attr('title')  
  17.           
  18.         #每张图的具体地址  
  19.         #html=self.get_html_Pages(gif_url)  
  20.         #gif_final_url=self.get_final_gif_url(html)  
  21.        
  22.         gif_dict['num']=num  
  23.         gif_dict['page_num']=page_num  
  24.         gif_dict['gif_url']=gif_url  
  25.         gif_dict['gif_title']=gif_title  
  26.         self.gif_list.append(gif_dict)  
  27.         data=u'第'+str(page_num)+'页|\t'+str(num)+'|\t'+gif_title+'|\t'+gif_url+'\n'  
  28.         self.file_flag.write(data)  
在这里,把数据整合一下,为将数据写入数据库做准备

7.将图片存到本地,以及将数据写入数据库

[python] view plain copy
  1. #使用urllib2来获取图片最终地址  
  2.     def get_final_gif_url_use_urllib2(self,url):  
  3.         try:  
  4.             html= urllib2.urlopen(url).read()  
  5.             gif_pattern=re.compile('<div align="center.*?<img id=.*?src="(.*?)" border.*?>',re.S)  
  6.             return re.search(gif_pattern,html).group(1)  
  7.         except Exception,e:  
  8.             print u'获取页面内容出错:',e  
  9.     #最终处理   存贮数据  
  10.     def get_gif_url_and_save_gif(self):  
  11.         def save_gif(url,name):  
  12.             try:  
  13.                 urllib.urlretrieve(url, name)  
  14.             except Exception,e:  
  15.                 print '存贮失败,原因:',e  
  16.         for i in range(0,len(self.gif_list)):  
  17.             gif_dict=self.gif_list[i]  
  18.             gif_url=gif_dict['gif_url']  
  19.             gif_title=gif_dict['gif_title']  
  20.               
  21.             #依然使用webdriver获取最终的gif地址  
  22.             final_html=self.get_html_Pages(gif_url)  
  23.             gif_final_url=self.get_final_gif_url(final_html)  
  24.             #使用另外一种方式(urllib2)获取最终地址  
  25.             #gif_final_url=self.get_final_gif_url_use_urllib2(gif_url)  
  26.               
  27.             gif_dict['gif_final_url']=gif_final_url  
  28.             print u'开始向数据库写入第%d页第%d项数据,并开始存贮图片到本地 ' % (gif_dict['page_num'],gif_dict['num'])  
  29.             self.BookTable.insert_one(gif_dict)  
  30.             gif_name=self.dir_name+'/'+gif_title+'.gif'  
  31.             save_gif(gif_final_url,gif_name)  
到这里其实大体的内容已经完成了.

我们能够将这个论坛各个模块的动图都存到本地,同时呢,也将数据放入到了数据库中

三 数据库的筛选

在完成了将数据放入到数据库的之后, 我想着可以直接通过调用数据库,将图片保存
(为什么有这个想法呢,因为我发现如果直接在主程序中存贮图片,它跑的太慢了,不如将数据都放到数据库中,之后专门调用数据库来贮存图片)
但是这里发现一个问题,数据中的内容挺多的,然后发现了好多内容是重复的,因此我们需要对数据库进行去重
关于数据去重的内容,其实我之前的文章已经写过了(写那篇文章的时候,这个爬虫已经完成了呢~)
主要思路是针对某一个元素的数量进行操作,pymongo里面有一个方法是可以统计指定元素的数量的,如果当前元素只有一个,就不管,不是一个元素,就删除
核心代码如下:

[python] view plain copy
  1. for url in collection.distinct('name'):#使用distinct方法,获取每一个独特的元素列表  
  2.         num= collection.count({"name":url})#统计每一个元素的数量  
  3.         print num  
  4.         for i in range(1,num):#根据每一个元素的数量进行删除操作,当前元素只有一个就不再删除  
  5.             print 'delete %s %d times '% (url,i)  
  6.             #注意后面的参数, 很奇怪,在mongo命令行下,它为1时,是删除一个元素,这里却是为0时删除一个  
  7.             collection.remove({"name":url},0)  
  8.         for i in  collection.find({"name":url}):#打印当前所有元素  
  9.             print i  
  10.     print collection.distinct('name')#再次打印一遍所要去重的元素  

四 读取数据库中的内容,存贮图片

数据去重之后,再次进行图片的存贮,就方便多了
之后如果图片删除了,也不用重新跑一边,或者说有时候本地图片占地方,那么只用保存有数据库的数据就好了
核心代码如下:

[python] view plain copy
  1. def save_gif(url,name):  
  2.     try:  
  3.         urllib.urlretrieve(url, name)  
  4.     except Exception,e:  
  5.         print u'存贮失败,原因:',e  
  6. client = pymongo.MongoClient('localhost'27017)   
  7. print client.database_names()  
  8.   
  9.   
  10. db = client.GifDB  
  11. for table in  db.collection_names():  
  12.     print 'table name is ',table  
  13.     collection=db[table]  
  14.   
  15.     for item in  collection.find():  
  16.         try:   
  17.             if item['gif_final_url']:  
  18.                 url,url_title= item['gif_final_url'],item['gif_title']  
  19.                 gif_filename=table+'/'+url_title+'.gif'  
  20.                 print 'start save %s, %s' % (url,gif_filename)  
  21.                 save_gif(url,gif_filename)  
  22.         except Exception,e:  
  23.             print u'错误原因:',e  
python爬虫(19)爬取论坛网站——网络上常见的gif动态图

完整代码

01_get_gif_url.py
[python] view plain copy
  1. #coding: utf-8   
  2. from pyquery import PyQuery as pq    
  3. from selenium import webdriver   
  4. import HTMLParser,urllib2,urllib,re,os  
  5.   
  6. import pymongo  
  7.   
  8. import time  
  9. import sys    
  10. reload(sys)    
  11. sys.setdefaultencoding('utf-8')    
  12. class download_gif:  
  13.     def __init__(self):  
  14.         self.url='http://gifcc.com/forum-38-1.html'  
  15.         self.url_list=['http://gifcc.com/forum-37-1.html',#其他各种GIF动态图出处   
  16.         'http://gifcc.com/forum-38-1.html'#美女GIF动态图出处   
  17.         'http://gifcc.com/forum-47-1.html',#科幻奇幻电影GIF动态图出处  
  18.         'http://gifcc.com/forum-48-1.html',#喜剧搞笑电影GIF动态图出处  
  19.         'http://gifcc.com/forum-49-1.html',#动作冒险电影GIF动态图出处  
  20.         'http://gifcc.com/forum-50-1.html'#恐怖惊悚电影GIF动态图出处  
  21.         ]  
  22.         self.choices={'1':u'其他各种GIF动态图出处',  
  23.         '2':u'美女GIF动态图出处',  
  24.         '3':u'科幻奇幻电影GIF动态图出处',  
  25.         '4':u'喜剧搞笑电影GIF动态图出处',  
  26.         '5':u'动作冒险电影GIF动态图出处',  
  27.         '6':u'恐怖惊悚电影GIF动态图出处'  
  28.         }  
  29.           
  30.         self.dir_name=u'gif出处'  
  31.         self.gif_list=[]  
  32.           
  33.         self.connection = pymongo.MongoClient()    
  34.           
  35.         #BookTable.insert_one(dict_data)#插入单条数据    
  36.         #BookTable.insert(dict_data)#插入 字典list 数据   
  37.           
  38.     #获取页面内容,并且加载JS, 通过滚动获取页面更多的元素  
  39.     def get_all_page(self,url):  
  40.         try:  
  41.             #browser = webdriver.PhantomJS(executable_path=r'C:\Python27\Scripts\phantomjs.exe')   
  42.             browser = webdriver.PhantomJS()   
  43.             browser.get(url)  
  44.             #time.sleep(3)   
  45.             #页面滚动  
  46.             js = "var q=document.body.scrollTop=100000"      
  47.             #for i in range(5):  #调试语句,先暂时不加载太多次数  
  48.             for i in range(30):    
  49.                 #循环执行下滑页面50次    
  50.                 browser.execute_script(js)    
  51.                 #加载一次,休息一下    
  52.                 time.sleep(1)  
  53.                 print u'这是第 %d 次划动页面' % i  
  54.             # 执行js得到整个页面内容  
  55.             html = browser.execute_script("return document.documentElement.outerHTML")  
  56.             browser.close()  
  57.             html=HTMLParser.HTMLParser().unescape(html)  
  58.             return html  
  59.         except Exception,e:  
  60.             print u'发生错误:',e  
  61.       
  62.     #解析页面内容,获取gif的图片list  
  63.     def parse_items_by_html(self, html):    
  64.         doc = pq(html)    
  65.         print u'开始查找内容msg'       
  66.         return doc('div[class="c cl"]')  
  67.           
  68.     #解析gif 的list ,处理每一个gif内容  
  69.     def get_items_url(self,items,num):  
  70.         i=1  
  71.         for article in items.items():  
  72.             print u'开始处理数据(%d/%d)' % (i, len(items))  
  73.             #print article  
  74.             self.get_single_item(article,i,num)  
  75.             i +=1  
  76.       
  77.     #处理单个gif内容,获取其地址,gif 最终地址  
  78.     def get_single_item(self,article,num,page_num):  
  79.         gif_dict={}  
  80.         #每个页面的地址  
  81.         gif_url= 'http://gifcc.com/'+article('a').attr('href')  
  82.         #每个页面的标题  
  83.         gif_title= article('a').attr('title')  
  84.           
  85.         #每张图的具体地址  
  86.         #html=self.get_html_Pages(gif_url)  
  87.         #gif_final_url=self.get_final_gif_url(html)  
  88.        
  89.         gif_dict['num']=num  
  90.         gif_dict['page_num']=page_num  
  91.         gif_dict['gif_url']=gif_url  
  92.         gif_dict['gif_title']=gif_title  
  93.         self.gif_list.append(gif_dict)  
  94.         data=u'第'+str(page_num)+'页|\t'+str(num)+'|\t'+gif_title+'|\t'+gif_url+'\n'  
  95.         self.file_flag.write(data)  
  96.       
  97.     #通过webdriver获得页面内容后,获得最终地址  
  98.     def get_final_gif_url(self,html):  
  99.         doc = pq(html)   
  100.         image_content= doc('td[class="t_f"]')  
  101.         gif_url= image_content('img').attr('src')  
  102.         return gif_url  
  103.       
  104.     #使用urllib2来获取图片最终地址  
  105.     def get_final_gif_url_use_urllib2(self,url):  
  106.         try:  
  107.             html= urllib2.urlopen(url).read()  
  108.             gif_pattern=re.compile('<div align="center.*?<img id=.*?src="(.*?)" border.*?>',re.S)  
  109.             return re.search(gif_pattern,html).group(1)  
  110.         except Exception,e:  
  111.             print u'获取页面内容出错:',e  
  112.     #最终处理   存贮数据  
  113.     def get_gif_url_and_save_gif(self):  
  114.         def save_gif(url,name):  
  115.             try:  
  116.                 urllib.urlretrieve(url, name)  
  117.             except Exception,e:  
  118.                 print '存贮失败,原因:',e  
  119.         for i in range(0,len(self.gif_list)):  
  120.             gif_dict=self.gif_list[i]  
  121.             gif_url=gif_dict['gif_url']  
  122.             gif_title=gif_dict['gif_title']  
  123.               
  124.             #依然使用webdriver获取最终的gif地址  
  125.             final_html=self.get_html_Pages(gif_url)  
  126.             gif_final_url=self.get_final_gif_url(final_html)  
  127.             #使用另外一种方式(urllib2)获取最终地址  
  128.             #gif_final_url=self.get_final_gif_url_use_urllib2(gif_url)  
  129.               
  130.             gif_dict['gif_final_url']=gif_final_url  
  131.             print u'开始向数据库写入第%d页第%d项数据,并开始存贮图片到本地 ' % (gif_dict['page_num'],gif_dict['num'])  
  132.             self.BookTable.insert_one(gif_dict)  
  133.             gif_name=self.dir_name+'/'+gif_title+'.gif'  
  134.             save_gif(gif_final_url,gif_name)  
  135.           
  136.     #仅仅获取页面内容  
  137.     def get_html_Pages(self,url):    
  138.         try:     
  139.             #browser = webdriver.PhantomJS(executable_path=r'C:\Python27\Scripts\phantomjs.exe')   
  140.             browser = webdriver.PhantomJS()   
  141.             browser.get(url)  
  142.             html = browser.execute_script("return document.documentElement.outerHTML")  
  143.             browser.close()  
  144.             html=HTMLParser.HTMLParser().unescape(html).decode('utf-8')  
  145.             return html  
  146.         #捕捉异常,防止程序直接死掉      
  147.         except Exception,e:    
  148.             print u"连接失败,错误原因",e  
  149.             return None     
  150.       
  151.     #获取页码         
  152.     def get_page_num(self,html):  
  153.   
  154.         doc = pq(html)    
  155.         print u'开始获取总页码'  
  156.         #print doc('head')('title').text()#获取当前title  
  157.         try:  
  158.             #如果当前页面太多,超过8页以上,就使用另一种方式获取页码  
  159.             if doc('div[class="pg"]')('[class="last"]'):  
  160.                 num_content= doc('div[class="pg"]')('[class="last"]').attr('href')  
  161.                 print  num_content.split('-')[1].split('.')[0]  
  162.                 return num_content.split('-')[1].split('.')[0]  
  163.             else:  
  164.                 num_content= doc('div[class="pg"]')('span')  
  165.                 return filter(str.isdigit,str(num_content.text()))[0]  
  166.         #如果获取页码失败,那么就返回1, 即值获取1页内容    
  167.         except Exception,e:  
  168.             print u'获取页码失败'.e  
  169.             return '1'  
  170.               
  171.         # filter(str.isdigit,num_content)#从字符串中提取数字  
  172.           
  173.     #创建文件夹    
  174.     def mk_dir(self,path):  
  175.         if not os.path.exists(path):    
  176.             os.makedirs(path)   
  177.               
  178.     def set_db(self,tablename):  
  179.         self.BookDB = self.connection.GifDB         #数据库db的名字    
  180.         self.BookTable =self.BookDB[tablename]           #数据库table表的名字    
  181.               
  182.     #主函数          
  183.     def run(self):  
  184.         choice_type=5  
  185.         if choice_type:  
  186.         #for choice_type in range(len(self.choices)):   
  187.             if  choice_type+1:  
  188.                   
  189.                 self.dir_name=self.choices[str(choice_type+1)].strip()  
  190.                 self.url=self.url_list[int(choice_type)]  
  191.                   
  192.                   
  193.                 print self.dir_name,self.url  
  194.           
  195.           
  196.             #0.创建文件夹存贮图片,建立文件存贮内容  
  197.             self.mk_dir(self.dir_name)  
  198.             self.filename=self.dir_name+'/'+self.dir_name+'.txt'  
  199.             print self.filename  
  200.             self.file_flag=open(self.filename,'w')  
  201.               
  202.             self.set_db(self.dir_name)  
  203.             self.BookTable .insert({'filename':self.dir_name})  
  204.               
  205.             print self.url  
  206.             #1.获取入口页面内容  
  207.             html=self.get_html_Pages(self.url)  
  208.               
  209.             #2.获取页码数目  
  210.             page_num=self.get_page_num(html)  
  211.               
  212.             print  u'总共有 %d页内容' % int(page_num)  
  213.             #3.遍历每一页的内容  
  214.               
  215.             #page_num=3#调试语句,先暂时将页面内容设置的小一点  
  216.             for num in range(1,int(page_num)):  
  217.                 #4.组装新的url  
  218.                 new_url = self.url.replace( self.url.split('-')[2],(str(num)+'.html') )  
  219.                 print u'即将获取的页面是:',new_url  
  220.                 #5.加载每一页内容,获取gif list 的内容  
  221.                 items=self.parse_items_by_html(self.get_all_page(new_url))  
  222.                 print u'在第%d页,找到了%d 个图片内容' % (num,len(items))  
  223.                 #6.处理每一个元素的内容  
  224.                 self.get_items_url(items,num)  
  225.               
  226.             #5.数据全部抓取完毕,开始处理数据  
  227.             self.get_gif_url_and_save_gif()  
  228.             print 'success'  
  229.               
  230.             self.file_flag.close()  
  231.           
  232.               
  233. if __name__ == '__main__':    
  234.     print u''''' 
  235.             **************************************************   
  236.             **    Welcome to Spider of  GIF 出处图片        **   
  237.             **         Created on 2017-05-21                **   
  238.             **         @author: Jimy _Fengqi                **   
  239.             **************************************************  
  240.     '''           
  241.     print u''''' 选择你要下载的gif图片类型 
  242.         1:'其他各种GIF动态图出处' 
  243.         2:'美女GIF动态图出处' 
  244.         3:'科幻奇幻电影GIF动态图出处' 
  245.         4:'喜剧搞笑电影GIF动态图出处' 
  246.         5:'动作冒险电影GIF动态图出处' 
  247.         6:'恐怖惊悚电影GIF动态图出处' 
  248.         '''  
  249.     #选择要下载的类型     
  250.   
  251.     mydownload=download_gif()  
  252.     html=mydownload.run()  
02_delete_repeat_url_in_mongodb.py

[python] view plain copy
  1. #coding: utf-8   
  2. from pyquery import PyQuery as pq    
  3. from selenium import webdriver   
  4. import HTMLParser,urllib2,urllib,re,os  
  5.   
  6. import pymongo  
  7.   
  8. import time  
  9. import sys    
  10. reload(sys)    
  11. sys.setdefaultencoding('utf-8')    
  12.   
  13. import pymongo    
  14.   
  15. def save_gif(url,name):  
  16.     try:  
  17.         urllib.urlretrieve(url, name)  
  18.     except Exception,e:  
  19.         print '存贮失败,原因:',e  
  20.           
  21. def print_database_and_table_name():      
  22.     import pymongo  
  23.     client = pymongo.MongoClient('localhost'27017)   
  24.     print client.database_names()  
  25.   
  26.     for database in client.database_names():  
  27.         for table in  client[database].collection_names():  
  28.             print 'table  [%s]  is in database [%s]' % (table,database)  
  29.   
  30. def delete_single_database_repeat_data():  
  31.     import pymongo  
  32.     client = pymongo.MongoClient('localhost'27017)   
  33.     db=client.GifDBtemptemp2#这里是将要清洗数据的数据库名字  
  34.     for table in  db.collection_names():  
  35.         print 'table name is ',table  
  36.         collection=db[table]  
  37.         for url in collection.distinct('gif_title'):#使用distinct方法,获取每一个独特的元素列表  
  38.             num= collection.count({"gif_title":url})#统计每一个元素的数量  
  39.             print num  
  40.             for i in range(1,num):#根据每一个元素的数量进行删除操作,当前元素只有一个就不再删除  
  41.                 print 'delete %s %d times '% (url,i)  
  42.                 #注意后面的参数, 很奇怪,在mongo命令行下,它为1时,是删除一个元素,这里却是为0时删除一个  
  43.                 collection.remove({"gif_title":url},0)  
  44.             for i in  collection.find({"gif_title":url}):#打印当前所有元素  
  45.                 print i  
  46.   
  47. def delete_repeat_data():  
  48.     import pymongo  
  49.     client = pymongo.MongoClient('localhost'27017)   
  50.     db = client.local  
  51.     collection = db.person  
  52.       
  53.     for url in collection.distinct('name'):#使用distinct方法,获取每一个独特的元素列表  
  54.         num= collection.count({"name":url})#统计每一个元素的数量  
  55.         print num  
  56.         for i in range(1,num):#根据每一个元素的数量进行删除操作,当前元素只有一个就不再删除  
  57.             print 'delete %s %d times '% (url,i)  
  58.             #注意后面的参数, 很奇怪,在mongo命令行下,它为1时,是删除一个元素,这里却是为0时删除一个  
  59.             collection.remove({"name":url},0)  
  60.         for i in  collection.find({"name":url}):#打印当前所有元素  
  61.             print i  
  62.     print collection.distinct('name')#再次打印一遍所要去重的元素  
  63. delete_single_database_repeat_data()  

03_from_mongodb_save_pic.py

[python] view plain copy
  1. #coding: utf-8   
  2. from pyquery import PyQuery as pq    
  3. from selenium import webdriver   
  4. import HTMLParser,urllib2,urllib,re,os  
  5.   
  6. import pymongo  
  7.   
  8. import time  
  9. import sys    
  10. reload(sys)    
  11. sys.setdefaultencoding('utf-8')    
  12.   
  13. import pymongo    
  14.   
  15. def save_gif(url,name):  
  16.     try:  
  17.         urllib.urlretrieve(url, name)  
  18.     except Exception,e:  
  19.         print u'存贮失败,原因:',e  
  20. client = pymongo.MongoClient('localhost'27017)   
  21. print client.database_names()  
  22.   
  23.   
  24. db = client.GifDB  
  25. for table in  db.collection_names():  
  26.     print 'table name is ',table  
  27.     collection=db[table]  
  28.   
  29.     for item in  collection.find():  
  30.         try:   
  31.             if item['gif_final_url']:  
  32.                 url,url_title= item['gif_final_url'],item['gif_title']  
  33.                 gif_filename=table+'/'+url_title+'.gif'  
  34.                 print 'start save %s, %s' % (url,gif_filename)  
  35.                 save_gif(url,gif_filename)  
  36.         except Exception,e:  
  37.             print u'错误原因:',e  
Github地址:https://github.com/JimyFengqi/Gif_Spide
r