zoukankan      html  css  js  c++  java
  • 最全Python爬虫总结(转载)

    [html] view plain copy

     
    1. 最近总是要爬取一些东西,索性就把Python爬虫的相关内容都总结起来了,自己多动手还是好。  
    (1)普通的内容爬取
    (2)保存爬取的图片/视频和文件和网页
    (3)普通模拟登录
    (4)处理验证码登录
    (5)爬取js网站
    (6)全网爬虫
    (7)某个网站的站内所有目录爬虫
    (8)多线程 
    (9)爬虫框架Scrapy   


    一,普通的内容爬取
    [html] view plain copy
     
    1. #coding=utf-8  
    2. import urllib    
    3. import urllib2    
    4. url = 'http://www.dataanswer.top'    
    5. headers = {   
    6.     'Host':'www.dataanswer.top',  
    7.     'User-Agent':'Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:31.0) Gecko/20100101 Firefox/31.0',  
    8.     #'Accept':'application/json, text/javascript, */*; q=0.01',  
    9.     #'Accept-Language':'zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3',  
    10.     #'Accept-Encoding':'gzip,deflate',  
    11.     #'Referer':'http://www.dataanswer.top'  
    12. }     
    13. request = urllib2.Request(url,headers=headers)    
    14. response = urllib2.urlopen(request)    
    15. page = response.read()  
    16. print page  
    二,保存爬取的图片/视频和文件和网页
    #图片/视频和文件和网页的地址抓取下来后,利用模块urllib里的urlretrieve()方法下载下来:
    [html] view plain copy
     
    1. #coding=utf-8  
    2. import urllib    
    3. import urllib2    
    4. import os  
    5. def getPage(url):       
    6.     request = urllib2.Request(url)    
    7.         response = urllib2.urlopen(request)    
    8.         return response.read()    
    9.   
    10.   
    11. url='http://www.dataanswer.top/'    
    12. result=getPage(url)    
    13. file_name='test.doc'  
    14. file_path='doc'  
    15. if os.path.exists(file_path) == False:  
    16.     os.makedirs(file_path)  
    17. local=os.path.join(file_path,file_name)  
    18. f = open(local,"w+")    
    19. f.write(result)   
    20. f.close()  
    21.   
    22.   
    23. #coding=utf-8  
    24. import urllib    
    25. import urllib2    
    26. import os  
    27. def getPage(url):       
    28.     request = urllib2.Request(url)    
    29.         response = urllib2.urlopen(request)    
    30.         return response.read()    
    31.   
    32.   
    33. url='http://www.dataanswer.top/'  #把该地址改成图片/文件/视频/网页的地址即可  
    34. result=getPage(url)    
    35. file_name='test.doc'  
    36. file_path='doc'  
    37. if os.path.exists(file_path) == False:  
    38.     os.makedirs(file_path)  
    39. local=os.path.join(file_path,file_name)  
    40. urllib.urlretrieve(url,local)  
    三,普通模拟登录
    [html] view plain copy
     
    1. import urllib  
    2. import urllib2  
    3. import cookielib  
    4.    
    5. filename = 'cookie.txt'  
    6. #声明一个MozillaCookieJar对象实例来保存cookie,之后写入文件  
    7. cookie = cookielib.MozillaCookieJar(filename)  
    8. opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookie))  
    9. postdata = urllib.urlencode({  
    10. 'name':'春天里',  
    11. 'pwd':'1222222'  
    12. })  
    13. #登录的URL  
    14. loginUrl = 'http://www.dataanswer.top/LoginService?action=tologin'  
    15. #模拟登录,并把cookie保存到变量  
    16. result = opener.open(loginUrl,postdata)  
    17. #保存cookie到cookie.txt中  
    18. cookie.save(ignore_discard=True, ignore_expires=True)  
    19. #利用cookie请求访问另一个网址  
    20. gradeUrl = 'http://www.dataanswer.top/LoginService?action=myHome'  
    21. #请求访问  
    22. result = opener.open(gradeUrl)  
    23. print result.read()  
    四,处理验证码登录
    #先把验证码图片下载下来保存,再人工读入
    [html] view plain copy
     
    1. #coding=utf-8  
    2. import sys, time, os, re  
    3. import urllib, urllib2, cookielib  
    4. loginurl = 'https://www.douban.com/accounts/login'  
    5. cookie = cookielib.CookieJar()  
    6. opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookie))  
    7. params = {  
    8. "form_email":"13161055481",  
    9. "form_password":"wwwwwww",  
    10. "source":"index_nav" #没有的话登录不成功  
    11. }  
    12. #从首页提交登录  
    13. response=opener.open(loginurl)  
    14. #验证成功跳转至登录页  
    15. print(response.geturl())  
    16. if response.geturl() == "https://www.douban.com/accounts/login":  
    17.     html=response.read()  
    18.     print(html)  
    19.     #验证码图片地址--图片地址加密怎么办???  
    20.     imgurl=re.search('<img id="captcha_image" src="(.+?)" alt="captcha" class="captcha_image"/>', html)  
    21.     print(imgurl)  
    22.     if imgurl:  
    23.             url=imgurl.group(1)  
    24.             #将图片保存至同目录下  
    25.             res=urllib.urlretrieve(url,'v.jpg')  
    26.             #获取captcha-id参数  
    27.             captcha=re.search('<input type="hidden" name="captcha-id" value="(.+?)"/>',html)  
    28.             if captcha:  
    29.                 vcode=raw_input('请输入图片上的验证码:')  
    30.                 params["captcha-solution"]=vcode  
    31.                 params["captcha-id"]=captcha.group(1)  
    32.                 params["user_login"]="登录"  
    33.                 #提交验证码验证  
    34.                 response=opener.open(loginurl, urllib.urlencode(params))  
    35.                 ''' 登录成功跳转至首页 '''  
    36.                 if response.geturl() == "https://www.douban.com/":  
    37.                     print 'login success ! '  
    38.                     print '准备进行发帖'  
    39.                     addtopicurl="http://www.douban.com/group/python/new_topic"  
    40.                     res=opener.open(addtopicurl)  
    41.                     html=res.read()  
    42.             else:  
    43.                 print("Fail3")  
    44.         else:  
    45.             print("Fail2")  
    46.     else:  
    47.         print("Fail1")  
    48. else:  
    49.     print("Fail0")  
    五,爬取js网站
    #利用selenium模拟浏览器,结合html的解析
    [html] view plain copy
     
    1. #coding=utf-8  
    2. #1、安装 python-pip  
    3. #sudo apt-get install python-pip  
    4. #2、安装selenium  
    5. #sudo pip install -U selenium  
    6.   
    7.   
    8. from selenium import webdriver  
    9. driver = webdriver.Firefox()   
    10. driver.get('http://www.newsmth.net/nForum/#!article/Intern/206790')  
    11. html=driver.page_source.encode('utf-8','ignore') #这个函数获取页面的html  
    12. print(html)  
    13. driver.close()  

    六,全网爬虫
    #广度优先,模拟爬取队列
    [html] view plain copy
     
    1. #coding=utf-8  
    2. """  
    3. 全网爬取所有链接,包括外链--广度优先  
    4. """  
    5. import urllib2  
    6. import re  
    7. from bs4 import BeautifulSoup  
    8. import time  
    9.   
    10.   
    11. #爬虫开始的时间  
    12. t=time.time()  
    13. #设置的暂停爬取条数  
    14. N_STOP=10  
    15.   
    16.   
    17. #存放已经爬取过的url  
    18. CHECKED_URL=[]  
    19. #存放待爬取的url  
    20. CHECKING_URL=[]  
    21. #存放连接失败的url  
    22. FAIL_URL=[]  
    23. #存放不能连接的url  
    24. ERROR_URL=[]  
    25. #失败后允许连接的次数  
    26. RETRY=3  
    27. #连接超时时间  
    28. TIMEOUT=20  
    29.   
    30.   
    31. class url_node:  
    32.     def __init__(self,url):  
    33.         """  
    34.         url节点初始化  
    35.         :param url:String 当前url  
    36.         """  
    37.         self.url=url  
    38.         self.content=''  
    39.   
    40.   
    41.     def __is_connectable(self):  
    42.         """  
    43.         检验url是否可以连接  
    44.         """  
    45.         #在允许连接次数下连接  
    46.         for i in range(RETRY):  
    47.             try:  
    48.                 #打开url没有报错,则表示可连接  
    49.                 response=urllib2.urlopen(self.url,timeout=TIMEOUT)  
    50.                 return True  
    51.             except:  
    52.                 #如果在尝试允许连接次数下报错,则不可连接  
    53.                 if i==RETRY-1:  
    54.                     return False  
    55.   
    56.   
    57.     def get_next(self):  
    58.         """  
    59.         获取爬取该页中包含的其他所有的url  
    60.         """  
    61.         soup=BeautifulSoup(self.content)  
    62.         #******************在此处可以从网页中解析你想要的内容************************************  
    63.         next_urls=soup.findAll('a')  
    64.         if len(next_urls)!=0:  
    65.             for link in next_urls:  
    66.                 tmp_url=link.get('href')  
    67.                 #如果url不在爬取过的列表中也不在待爬取列表中则把其放到待爬列表中(没有确保该url有效)  
    68.                 if tmp_url not in CHECKED_URL and tmp_url not in CHECKING_URL:  
    69.                     CHECKING_URL.append(tmp_url)  
    70.           
    71.     def run(self):  
    72.         if self.url:  
    73.             if self.__is_connectable():  
    74.                 try:  
    75.                     #获取爬取页面的所有内容  
    76.                     self.content=urllib2.urlopen(self.url,timeout=TIMEOUT).read()  
    77.                     #从该页面中获取url  
    78.                     self.get_next()  
    79.   
    80.   
    81.                 except:  
    82.                     #把连接失败的存放起来  
    83.                     FAIL_URL.append(self.url)  
    84.                     print('[!]Connect Failed')  
    85.             else:  
    86.                 #把不能连接的存放起来  
    87.                 ERROR_URL.append(self.url)  
    88.         else:  
    89.             print("所给的初始url有问题!")             
    90.   
    91.   
    92. if __name__=='__main__':  
    93.     #把初始的url放到待爬的列表中  
    94.     CHECKING_URL.append('http://www.36dsj.com/')  
    95.     #不断的从待爬的列表中获取url进行爬取  
    96.     ff=open("Mytest.txt",'w')  
    97.     i=0  
    98.     for url in CHECKING_URL:  
    99.         #对该url进行爬取  
    100.         url_node(url).run()  
    101.         #存放已经爬取过的url  
    102.         CHECKED_URL.append(url)   
    103.         #删除CHECKING_URL中已经爬取过的url  
    104.         CHECKING_URL.remove(url)  
    105.   
    106.   
    107.         i+=1  
    108.         if i==N_STOP:  
    109.             #打出停止时的url,下次可以把该url作为初始继续  
    110.             print url  
    111.             print("爬取过的列表长度:%d") % len(CHECKED_URL)  
    112.             print("待爬取的列表长度:%d") % len(CHECKING_URL)  
    113.             print("连接失败的列表长度:%d") % len(FAIL_URL)  
    114.             print("不能连接的列表长度:%d") % len(ERROR_URL)  
    115.             break  
    116.     ff.close()  
    117.     print("time:%d s") % (time.time()-t)      

    七,某个网站的站内所有目录爬虫
    #把缩写的站内网址还原
    [html] view plain copy
     
    1. #coding=utf-8  
    2. """  
    3. 爬取同一个网站所有的url,不包括外链  
    4. """  
    5. import urllib2  
    6. import re  
    7. from bs4 import BeautifulSoup  
    8. import time  
    9.   
    10. t=time.time()  
    11.   
    12. HOST=''  
    13. CHECKED_URL=[]  
    14. CHECKING_URL=[]  
    15. RESULT=[]  
    16. RETRY=3  
    17. TIMEOUT=20  
    18.   
    19. class url_node:  
    20.     def __init__(self,url):  
    21.         """  
    22.         url节点初始化  
    23.         :param url:String 当前url  
    24.         """  
    25.         self.url=self.handle_url(url,is_next_url=False)  
    26.         self.next_url=[]  
    27.         self.content=''  
    28.   
    29.   
    30.     def handle_url(self,url,is_next_url=True):  
    31.         """  
    32.         将所有的url处理成标准形式  
    33.         """  
    34.         global CHECKED_URL  
    35.         global CHECKING_URL  
    36.   
    37.         #去掉尾部的‘/’  
    38.         url=url[0:len(url)-1] if url.endswith('/') else url  
    39.   
    40.         if url.find(HOST)==-1:  
    41.             if not url.startswith('http'):  
    42.                 url='http://'+HOST+url if url.startswith('/') else 'http://'+HOST+'/'+url  
    43.             else:  
    44.                 #如果含有http说明是外链,url的host不是当前的host,返回空  
    45.                 return  
    46.         else:  
    47.             if not url.startswith('http'):  
    48.                 url='http://'+url  
    49.   
    50.   
    51.         if is_next_url:  
    52.             #下一层url放入待检测列表  
    53.             if url not in CHECKING_URL:  
    54.                 CHECKING_URL.append(url)  
    55.         else:  
    56.             #对于当前需要检测的url将参数都替换为1,然后加入规则表  
    57.             #参数相同类型不同的url只检测一次  
    58.             rule=re.compile(r'=.*?&|=.*?$')  
    59.             result=re.sub(rule,'=1&',url)  
    60.             if result in CHECKED_URL:  
    61.                 return '[!] Url has checked!'  
    62.             else:  
    63.                 CHECKED_URL.append(result)  
    64.                 RESULT.append(url)  
    65.         return url  
    66.   
    67.   
    68.     def __is_connectable(self):  
    69.         print("进入__is_connectable()函数")  
    70.         #检验是否可以连接  
    71.         retry=3  
    72.         timeout=2  
    73.         for i in range(RETRY):  
    74.             try:  
    75.                 #print("进入_..............函数")  
    76.                 response=urllib2.urlopen(self.url,timeout=TIMEOUT)  
    77.                 return True  
    78.               
    79.             except:  
    80.                 if i==retry-1:  
    81.                     return False  
    82.   
    83.   
    84.     def get_next(self):  
    85.         #获取当前所有的url  
    86.         #print("进入get_next()函数")  
    87.         soup=BeautifulSoup(self.content)  
    88.         next_urls=soup.findAll('a')  
    89.         if len(next_urls)!=0:  
    90.             for link in next_urls:  
    91.                 self.handle_url(link.get('href'))  
    92.                 #print(link.text)  
    93.   
    94.   
    95.           
    96.     def run(self):  
    97.         #print("进入run()函数")  
    98.         if self.url:  
    99.             #print self.url  
    100.             if self.__is_connectable():  
    101.                 try:  
    102.                     self.content=urllib2.urlopen(self.url,timeout=TIMEOUT).read()  
    103.                     self.get_next()  
    104.   
    105.   
    106.                 except:  
    107.                     print('[!]Connect Failed')  
    108. #处理https开头的url的类和方法  
    109. class Poc:  
    110.     def run(self,url):  
    111.         global HOST  
    112.         global CHECKING_URL  
    113.         url=check_url(url)  
    114.   
    115.   
    116.         if not url.find('https'):  
    117.             HOST=url[:8]  
    118.         else:  
    119.             HOST=url[7:]  
    120.   
    121.   
    122.         for url in CHECKING_URL:  
    123.             print(url)  
    124.             url_node(url).run()  
    125.   
    126.   
    127. def check_url(url):  
    128.     url='http://'+url if not url.startswith('http') else url  
    129.     url=url[0:len(url)-1] if url.endswith('/') else url  
    130.   
    131.   
    132.     for i in range(RETRY):  
    133.         try:  
    134.             response=urllib2.urlopen(url,timeout=TIMEOUT)  
    135.             return url  
    136.         except:  
    137.             raise Exception("Connect error")  
    138.   
    139.   
    140. if __name__=='__main__':  
    141.     HOST='www.dataanswer.com'  
    142.     CHECKING_URL.append('http://www.dataanswer.com/')  
    143.     f=open('36大数据','w')  
    144.     for url in CHECKING_URL:  
    145.         f.write(url+' ')  
    146.         print(url)  
    147.         url_node(url).run()  
    148.     print RESULT  
    149.     print "URL num:"+str(len(RESULT))  
    150.     print("time:%d s") % (time.time()-t)      
    八,多线程
    #对列和线程的结合
    [html] view plain copy
     
    1. #!/usr/bin/env python  
    2. # -*- coding:utf-8 -*-  
    3. """  
    4. 一个简单的Python爬虫, 使用了多线程,   
    5. 爬取豆瓣Top前250的所有电影  
    6. """  
    7.   
    8. import urllib2, re, string  
    9. import threading, Queue, time  
    10. import sys  
    11.   
    12. reload(sys)  
    13. sys.setdefaultencoding('utf8')  
    14. _DATA = []  
    15. FILE_LOCK = threading.Lock()  
    16. SHARE_Q = Queue.Queue()  #构造一个不限制大小的的队列  
    17. _WORKER_THREAD_NUM = 3  #设置线程的个数  
    18.   
    19.   
    20. class MyThread(threading.Thread) :  
    21.   
    22.   
    23.     def __init__(self, func) :  
    24.         super(MyThread, self).__init__()  #调用父类的构造函数  
    25.         self.func = func  #传入线程函数逻辑  
    26.   
    27.   
    28.     def run(self) :  
    29.         self.func()  
    30.   
    31.   
    32. def worker() :  
    33.     global SHARE_Q  
    34.     while not SHARE_Q.empty():  
    35.         url = SHARE_Q.get() #获得任务  
    36.         my_page = get_page(url)  
    37.         find_title(my_page)  #获得当前页面的电影名  
    38.         #write_into_file(temp_data)  
    39.         time.sleep(1)  
    40.         SHARE_Q.task_done()  
    41.   
    42.   
    43. def get_page(url) :  
    44.     """  
    45.     根据所给的url爬取网页HTML  
    46.     Args:   
    47.         url: 表示当前要爬取页面的url  
    48.     Returns:  
    49.         返回抓取到整个页面的HTML(unicode编码)  
    50.     Raises:  
    51.         URLError:url引发的异常  
    52.     """  
    53.     try :  
    54.         my_page = urllib2.urlopen(url).read().decode("utf-8")  
    55.     except urllib2.URLError, e :  
    56.         if hasattr(e, "code"):  
    57.             print "The server couldn't fulfill the request."  
    58.             print "Error code: %s" % e.code  
    59.         elif hasattr(e, "reason"):  
    60.             print "We failed to reach a server. Please check your url and read the Reason"  
    61.             print "Reason: %s" % e.reason  
    62.     return my_page  
    63.   
    64.   
    65. def find_title(my_page) :  
    66.     """  
    67.     通过返回的整个网页HTML, 正则匹配前100的电影名称  
    68.     Args:  
    69.         my_page: 传入页面的HTML文本用于正则匹配  
    70.     """  
    71.     temp_data = []  
    72.     movie_items = re.findall(r'<span.*?class="title">(.*?)</span>', my_page, re.S)  
    73.     for index, item in enumerate(movie_items) :  
    74.         if item.find(" ") == -1 :  
    75.             #print item,  
    76.             temp_data.append(item)  
    77.     _DATA.append(temp_data)  
    78.   
    79. def main() :  
    80.     global SHARE_Q  
    81.     threads = []  
    82.     douban_url = "http://movie.douban.com/top250?start={page}&filter=&type="  
    83.     #向队列中放入任务, 真正使用时, 应该设置为可持续的放入任务  
    84.     for index in xrange(10) :     
    85.         SHARE_Q.put(douban_url.format(page = index * 25))  
    86.     for i in xrange(_WORKER_THREAD_NUM) :  
    87.         thread = MyThread(worker)  
    88.         thread.start()  #线程开始处理任务  
    89.     print("第%s个线程开始工作") % i  
    90.         threads.append(thread)  
    91.     for thread in threads :  
    92.         thread.join()  
    93.     SHARE_Q.join()  
    94.     with open("movie.txt", "w+") as my_file :  
    95.         for page in _DATA :  
    96.             for movie_name in page:  
    97.                 my_file.write(movie_name + " ")  
    98.     print "Spider Successful!!!"  
    99.   
    100.   
    101. if __name__ == '__main__':  
    102.     main()  
    九,爬虫框架Scrapy

    items.py:用来定义需要保存的变量,其中的变量用Field来定义,有点像python的字典
    pipelines.py:用来将提取出来的Item进行处理,处理过程按自己需要进行定义
    spiders:定义自己的爬虫


    爬虫的类型也有好几种:
      1)spider:最基本的爬虫,其他的爬虫一般是继承了该最基本的爬虫类,提供访问url,返回response的功能,会默认调用parse方法
      2)CrawlSpider:继承spider的爬虫,实际使用比较多,设定rule规则进行网页的跟进与处理, 注意点:编写爬虫的规则的时候避免使用parse名,因为这会覆盖继承的spider的的方法parse造成错误。   其中比较重要的是对Rule的规则的编写,要对具体的网页的情况进行分析。
      3)XMLFeedSpider 与 CSVFeedSpider 

    (1)打开命令行,执行:scrapy startproject tutorial(项目名称)
    (2)scrapy.cfg是项目的配置文件,用户自己写的spider要放在spiders目录下面
    (3)解析:name属性很重要,不同spider不能使用相同的name
    start_urls是spider抓取网页的起始点,可以包括多个url
    parse方法是spider抓到一个网页以后默认调用的callback,避免使用这个名字来定义自己的方法。
    当spider拿到url的内容以后,会调用parse方法,并且传递一个response参数给它,response包含了抓到的网页的内容,在parse方法里,你可以从抓到的网页里面解析数据。
    (3)开始抓取,进入生成的项目根目录tutorial/,执行 scrapy crawl dmoz, dmoz是spider的name。
    (4)保存对象:在items.py中添加一些类,这些类用来描述我们要保存的数据

    from scrapy.item import Item, Field
    class DmozItem(Item):
        title = Field()
        link = Field()
        desc = Field()
    (5)执行scrapy crawl dmoz --set FEED_URI=items.json --set FEED_FORMAT=json后得到保存的文件
    (6)让scrapy自动抓取网页上的所有链接

    在parse方法里面提取我们需要的链接,然后构造一些Request对象,并且把他们返回,scrapy会自动的去抓取这些链接

  • 相关阅读:
    MongoDB Shell
    mongo 日记
    java 堆栈 静态
    面向对象(2)
    面向对象(1)
    mongo 学习笔记
    深入浅出学Spring Data JPA
    java记录
    mongodb 2.6 window 安装启动服务
    CF1012F Passports
  • 原文地址:https://www.cnblogs.com/it-tsz/p/8726801.html
Copyright © 2011-2022 走看看