欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

史上最最最最最最最最全Python爬虫总结

程序员文章站 2022-07-02 21:07:25
(1)普通的内容爬取(2)保存爬取的图片/视频和文件和网页(3)普通模拟登录(4)处理验证码登录(5)爬取js网站(6)全网爬虫(7)某个网站的站内所有目录爬虫(8)多线程 (9)爬虫框架Scrapy 一,普通的内容爬取 二,保存爬取的图片/视频和文件和网页#图片/视频和文件和网页的地址抓取下来后, ......

(1)普通的内容爬取
(2)保存爬取的图片/视频和文件和网页
(3)普通模拟登录
(4)处理验证码登录
(5)爬取js网站
(6)全网爬虫
(7)某个网站的站内所有目录爬虫
(8)多线程 
(9)爬虫框架scrapy   

一,普通的内容爬取 

 1 #coding=utf-8
 2 #python学习交流群:548377875
 3 import urllib  
 4 import urllib2  
 5 url = 'http://www.dataanswer.top'  
 6 headers = { 
 7     'host':'www.dataanswer.top',
 8     'user-agent':'mozilla/5.0 (x11; ubuntu; linux i686; rv:31.0) gecko/20100101 firefox/31.0',
 9     #'accept':'application/json, text/javascript, */*; q=0.01',
10     #'accept-language':'zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3',
11     #'accept-encoding':'gzip,deflate',
12     #'referer':'http://www.dataanswer.top'
13 }   
14 request = urllib2.request(url,headers=headers)  
15 response = urllib2.urlopen(request)  
16 page = response.read()
17 print page

二,保存爬取的图片/视频和文件和网页
#图片/视频和文件和网页的地址抓取下来后,利用模块urllib里的urlretrieve()方法下载下来:

 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(local)

三,普通模拟登录

 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()

四,处理验证码登录
#先把验证码图片下载下来保存,再人工读入

 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的解析

 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()

六,全网爬虫
#广度优先,模拟爬取队列

  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)    

七,某个网站的站内所有目录爬虫
#把缩写的站内网址还原

  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+'\n')
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)    

八,多线程
#对列和线程的结合

  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 + "\n")
 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会自动的去抓取这些链接