python爬虫

原创 2016年08月28日 22:25:34

再不写点东西就真不会写代码了
最近一直在学习云计算的东西,慢慢的也准备整理一下。
今天试试手,写一个简单的爬虫,之前就写了,但一直没有实现。很简单,正好熟悉一下python

# coding=utf-8
import sys
import os
import urllib
import urllib2
import threading

base_uri = "http://www.csdn.net/"
connect_flag = True
running = False
from time import sleep
import re

LINK_RE = r'(http://[\w,\b,/,\.,-]*)'
IMAGE_RE = r"<img.*src\s?=\s?\"[^\w]*([^>]*?)\""
link_set = set()

#初始化参数
link_set_copy = set()
link_set.add(base_uri)
link_set_copy.add(base_uri)
SUCCESS_COUNT=1
ERROR_COUNT=0
IMAGE_COUNT=0



# 创建一个类去处理爬虫程序
class Crawler(object):
    def __init__(self):
        pass

    def writeLinks(self, link):
        file_obj = open("./links/links.txt","a")
        file_obj.write(link+"\n")
        file_obj.close()

    def getImages(self, contents):
        global IMAGE_COUNT
        imagere = re.compile(IMAGE_RE)
        image_list = imagere.findall(contents)
        n=0
        for image in image_list:
            try:

                if image.index("http") == -1:
                    image = "http://"+image
                #print str(image)
                data = urllib.urlopen(image).read()
                f = file("./images/"+str(IMAGE_COUNT)+".jpg", 'wb')
                f.write(data)
                f.close()
                IMAGE_COUNT+=1
            except Exception, e:
                # print "download image failed: "+image

                #print e
                pass

    def getLink(self,contents):
        '''
        :param contents: 获取出来的网页内容
        :return: 无
        '''
        global link_set, link_set_copy
        linkre = re.compile(LINK_RE)
        link_list = linkre.findall(contents, )
        #print "链接数量: " + str(len(link_list))
        #如果不在已经删除的链接的集合就加进去
        for link in link_list:
            if link not in link_set_copy:
                link_set.add(link)

    def req_contents(self):
        global link_set, link_set_copy,ERROR_COUNT,SUCCESS_COUNT,connect_flag, running

        uri = link_set.pop()
        link_set_copy.add(uri)
        #print uri
        self.writeLinks(uri)

        try :
            request = urllib2.Request(uri)
            response = urllib2.urlopen(request)
            result = response.read().decode('utf8')
            self.getImages(result)
            SUCCESS_COUNT += 1
            if connect_flag:
                connect_flag = False
            if not running:
                running = True
            self.getLink(result)
        except UnicodeDecodeError, e:
            ERROR_COUNT += 1
            # print "decoding error"
        except Exception, e:
            ERROR_COUNT += 1
            # print e
        except urllib2.URLError, e:
            ERROR_COUNT += 1
            # print e



    def start(self):
        global link_set
        #import pdb;pdb.set_trace()
        while len(link_set) > 0:
            self.req_contents()



#也是添加一个不断更新的效果,在第一次请求的时候,如果需要时间比较长久能看得到。
class IsGrabbig(threading.Thread):
    def run(self):
        n = 1
        global connect_flag
        # print "grbbing ",
        while connect_flag:

            if n % 4 == 0:
                sys.stdout.write("\r || grabbing || \r")
            elif n % 4 == 1:
                sys.stdout.write("\r /\\ grabbing /\\ \r")
            elif n % 4 == 2:
                sys.stdout.write("\r -- grabbing -- \r")
            else:
                sys.stdout.write("\r \\/ grabbing \\/ \r")
            sys.stdout.flush()
            sleep(0.5)
            n += 1
        #一直想实现一下linux上的进度条的效果,之前没有试过怎么在一行输出并不断更新。sys.stdout.write("\r")就可以实现,\r的效果是从头开始重新输入,会覆盖之前的输出。
        # \r从头开始,覆盖后面的数据,中间不能有换行的输出
        sys.stdout.write("\r 已获取到数据" + " " * 100 + "\n")
        sys.stdout.flush()
#输出一个不断更新的效果
class LinkCount(threading.Thread):

    def run(self):
        global running,SUCCESS_COUNT,ERROR_COUNT
        while not running:
            sleep(0.1)
            pass
        while running:
            sys.stdout.write("\r 已读取的网页数量: "+str(SUCCESS_COUNT) + "\t失败数量:"+str(ERROR_COUNT) + "\t")
            sys.stdout.flush()
            sleep(1)



def generateReport():
    global link_set_copy, link_set
    print "\n"+"*" * 10 + "Report" + "*" * 10
    print " " * 10 + "over" + " " * 10
    print "总共识别出了"+str(len(link_set_copy)+len(link_set))+"个网页"
    print "已经读取"+str(SUCCESS_COUNT)+"个网页"
    print "读取出错的数量" + str(ERROR_COUNT) + "个网页"
    print "*" * 26


if __name__ == "__main__":
    # raw_input("please input the uri")
    # uri_confirm = raw_input("confirm the uri is : " + base_uri + " (Y/N) \n")                                                             "")
    # if uri_confirm is "N" or uri_confirm is "n":
    # sys.exit(0)
    print "program is starting ... "
    IsGrabbig().start()

    crawler = Crawler()
    try:

        LinkCount().start()
        crawler.start()
        print
    except KeyboardInterrupt,e:

        print
    except UnicodeDecodeError,e:
        print
    finally:
        running = False
        connect_flag = True
        generateReport()

很简单,输出的结果也就是这样

sh-3.2# python main.py
program is starting ... 
 已获取到数据                                                                                                    
 已读取的网页数量: 11   失败数量:5  ^C

**********Report**********
          over          
总共识别出了739个网页
已经读取11个网页
读取出错的数量5个网页
**************************
版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

用Python写网络爬虫 PDF

  • 2017-10-12 13:56
  • 10.62MB
  • 下载

Python爬虫-用迅雷下载电影

前段时间用Python写了一个爬取豆瓣电影的脚本,可以把评分高于8.0和评价人数高于10w人的电影保存下来,保存的格式是json的, 然后熬夜用c#写了一个界面软件可以显示和读取电影信息, ...

Python爬虫ALLITEbook和Amazon

其实,早就想学习爬虫了,这周末就尝试了一下。下面进行简单的整理和记录。 第一次拿http://www.allitebooks.com/该网站(俗称程序员电子书)开刀,从该网站获取书名及其国际标准书号...

Python实现简单的爬虫

通过python 来实现这样一个简单的爬虫功能,把我们想要的代码爬取到本地。下面就看看如何使用python来实现这样一个功能。     一,获取整个页面数据   首先我们...

用Python写网络爬虫

  • 2017-09-23 17:40
  • 9.87MB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)