当前位置: 移动技术网 > IT编程>脚本编程>Python > 史上最最最最最最最最全Python爬虫总结

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

2018年09月08日  | 移动技术网IT编程  | 我要评论

秀才奇遇记,哈利波特 下载,玉林市

(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会自动的去抓取这些链接

 

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网