来自 编程应用 2019-09-04 19:47 的文章
当前位置: 六合联盟网 > 编程应用 > 正文

python抓取网页图片,python爬取网站数据保存使用

=======================

编码难题 因为涉嫌到粤语,所以必然地关系到了编码的标题,这一遍借这一个时机终于深透搞明白了。
难点要从文字的编码讲起。原来的德文编码唯有0~255,刚好是8位1个字节。为了表示各样分歧的言语,自然要举办扩充。汉语的话有GB连串。大概还听闻过Unicode和UTF-8,那么,它们之间是怎么着关系呢?
Unicode是一种编码方案,又称万国码,可知其富含之广。但是实际存储到计算机上,并不用这种编码,可以说它起着一个中级人的效用。你能够再把Unicode编码(encode)为UTF-8,也许GB,再囤积到Computer上。UTF-8照旧GB也得以开展解码(decode)还原为Unicode。
在python中Unicode是一类对象,表现为以u打头的,譬如u'普通话',而string又是一类对象,是在现实编码格局下的实在存在Computer上的字符串。比如utf-8编码下的'粤语'和gbk编码下的'普通话',并分裂。能够看如下代码:

代码:

复制代码 代码如下:

# www.jbxue.com

= r===

= urllib2.urlopen(url).read().decode()


    x == str(x.())++str(x.())++str(x.(=r== imgurl =   %= = picpath+ % += urllib.urlretrieve(imgurl, target)
        time.sleep(1

   ==  = raw_input(  pageNo.isdigit()  int(pageNo) > 100 pageNo ==  = raw_input(
    html = getHtml(+= detail = 

>>> str=u'中文'
>>> str1=str.encode('utf8')
>>> str2=str.encode('gbk')
>>> print repr(str)
u'u4e2du6587'
>>> print repr(str1)
'xe4xb8xadxe6x96x87'
>>> print repr(str2)
'xd6xd0xcexc4'

# www.jbxue.com = r = = = = urllib2.urlopen(url).read().decode( ) x = = str(x. ( ))+ +str(x. ( ))+ +str(x. ( =r = = imgurl = % = = picpath+ % + = urllib.urlretrieve(imgur...

能够看到,其实存款和储蓄在管理器中的只是那般的编码,实际不是一个三个的汉字,在print的时候要懂妥当时是用的如何的编码形式,工夫科学的print出来。有二个说法提得很好,python中的Unicode才是的确的字符串,而string是字节串
文件编码
既然如此有例外的编码,那么一旦在代码文件中央市直机关接写string的话,那么它到底是哪个种类编码呢?那一个正是由文件的编码所调整的。文件三番五次以一定的编码方式保存的。而python文件能够写上coding的扬言语句,用来表明这一个文件是用什么编码情势保存的。如若注解的编码方式和骨子里保存的编码方式不平等就能够出现非凡。能够见下边例子: 以utf-8保存的公文宣称为gbk

复制代码 代码如下:

#coding:gbk
str=u'汉'
str1=str.encode('utf8')
str2=str.encode('gbk')
str3='汉'
print repr(str)
print repr(str1)
print repr(str2)
print repr(str3)

提示错误 File "test.py", line 1 SyntaxError: Non-ASCII character 'xe6' in file test.py on line 1, but no encodi ng declared; see for details 改为

复制代码 代码如下:

#coding:utf8
str=u'汉'
str1=str.encode('utf8')
str2=str.encode('gbk')
str3='汉'
print repr(str)
print repr(str1)
print repr(str2)
print repr(str3)

输出通常结果 u'u6c49' 'xe6xb1x89' 'xbaxba' 'xe6xb1x89'

主干方法 骨子里用python爬取网页很简短,唯有大约的几句话

复制代码 代码如下:

import urllib2
page=urllib2.urlopen('url').read()

如此那般就能够赢获得页面包车型大巴剧情。接下来再用正则相称去相配所急需的源委就行了。
可是,真正要做起来,就能够有两种三种的内部原因难题。
登录
那是八个须求报到认证的网址。也不太难,只要导入cookielib和urllib库就行。

复制代码 代码如下:

import urllib,urllib2,cookielib
cookiejar = cookielib.CookieJar()
urlOpener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookiejar))

这样就装载进三个cookie,用urlOpener去open登陆今后就足以记住音信。
断线重连
假诺只是实现上边的水准,不对open实行包装的话,只要网络境况有个别起伏,就间接抛出十一分,退出整个程序,是个比非常差的前后相继。这一年,只要对非常举行管理,多试五回就行了:

复制代码 代码如下:

def multi_open(opener,*arg):
    while True:
        retryTimes=20
        while retryTimes>0:
            try:
                return opener.open(*arg)
            except:
                print '.',
                retryTimes-=1

正则相配 骨子太师则相称并不到底叁个专程好的不二秘技,因为它的容错性很差,网页要完全统一。若是有稍许的不统一,就能倒闭。后来看来说有依附xpath来打开抉择的,后一次能够尝试一下。
写正则其实是有料定技术的:
非贪婪匹配。比方那样叁个标签:<span class='a'>hello</span>,要抽取a来,借使写成那样的表明式,就可怜了:<span class=.*>hello</span>。因为*开展了贪婪匹配。那是要用.?:<span class=.?>hello</span>。
跨行相配。达成跨行有一种思路是使用DOTALL标记位,那样.就能合营到换行。可是那样一来,整个相配进程就能够变得相当的慢。本来的相配是以行为单位的。整个经过最多就是O(nc2),n是行数,c是平均列数。现在极有望变为O((nc)2)。笔者的兑现方案是行使n来相称换行,这样能够分明建议相配最多跨跃多少行。举个例子:abcs*ns*def,就提出查找的是隔一行的。(.n)?就足以内定是卓殊尽大概少的行。
此间其实还要小心多少个点。有的行末是包括r的。相当于说一行是以rn结尾的。当初不知晓那或多或少,正则就调节和测量检验了比较久。今后平素用s,表示行末空格和r。
无捕获分组。为了不对捕获的分组变成影响,下面的(.n)能够改为(?:.n),那样捕获分组时,就能忽视它。
单括号要扩充转义。因为单括号在正则里是用来代表分组的,所感觉了合作单括号就开展转义。正则字符串最棒用的是饱含r前缀的字符串,要是还是不是的话,则要对再张开转义。
高速正则。写了那么多方式,也计算出一规律出来。先把要合营的字符相关的段子拿出去。要合营的事物用(.?)代替。把换行n替换为字符串sns*,再去掉行首行末的空格。整个经过在vim中得以神速就写好。
Excel操作
这一次的多少是放进Excel的。到末端才察觉到如若放进数据库的话,只怕就不曾那么多事了。不过曾经写到八分之四,难以回头了。
搜索Excel,能够吸取多少个方案来,一个是用xlrt/xlwt库,那些不管Computer上是还是不是安装了Excel,都能够运作,但不得不是xls格式的。还应该有一个是直接包装了com,需求计算机上安装了软件才行。小编动用的是前一种。
着力的读写没临时常。但是数据量一大起来,就有难题了。
内部存款和储蓄器相当不够。程序一跑起来,内部存款和储蓄器占用就一点一点往上涨。前边再查了须臾间,知道要用flush_row_data。不过仍然会出错。一看内部存款和储蓄器占用,未有怎么难题,平昔很稳固。但最后照旧会现出memory error。那正是见鬼了。又是每每地查, 一再地运作。一点结出都未曾。要命的是bug只在数据量大起来才出现,而等数据量大起来往往要许多少个钟头,那debug的本钱实际上是太高了。三个有的时候的火候,陡然发掘内部存款和储蓄器占用,即使总体平稳,但是会规律性的面世小的水涨船高,而那规律性,会不会和flush_row_data,有关。平昔狐疑的是data被flush到了哪个地方。原本xlwt的作法是很蛋疼的作法。把数据存在内部存款和储蓄器里,大概flush到二个temp,到save的时候,再一遍性写入。而难题正出在那二遍性写入,内部存款和储蓄器狂涨。那自身要flush_row_data何用?为啥不一同始就flush进要写入的位置。
行数限制。那一个是xls格式自个儿决定的,最多行数只可以是65536。并且数量第一次全国代表大会,文件打开也不便于。
重组以上两点,最后利用了那样叁个战术,假使行数是一千的翻番,实行一回flush,假如行数超过65536,新开一个sheet,要是超越3个sheet,则新建三个文书。为了便利,把xlwt包装了一晃

复制代码 代码如下:

#coding:utf-8#
import xlwt

class XLS:
    '''a class wrap the xlwt'''
    MAX_ROW=65536
    MAX_SHEET_NUM=3

    def __init__(self,name,captionList,typeList,encoding='utf8',flushBound=1000):
        self.name=name
        self.captionList=captionList[:]
        self.typeList=typeList[:]
        self.workbookIndex=1
        self.encoding=encoding
        self.wb=xlwt.Workbook(encoding=self.encoding)
        self.sheetIndex=1
        self.__addSheet()
        self.flushBound=flushBound

    def __addSheet(self):
        if self.sheetIndex != 1:
            self.wb.save(self.name+str(self.workbookIndex)+'.xls')
        if self.sheetIndex>XLS.MAX_SHEET_NUM:
            self.workbookIndex+=1
            self.wb=xlwt.Workbook(encoding=self.encoding)
            self.sheetIndex=1

        self.sheet=self.wb.add_sheet(self.name.encode(self.encoding)+str(self.sheetIndex))
        for i in range(len(self.captionList)):
            self.sheet.write(0,i,self.captionList[i])

        self.row=1

    def write(self,data):
        if self.row>=XLS.MAX_ROW:
            self.sheetIndex += 1
            self.__addSheet()

        for i in range(len(data)):
            if self.typeList[i]=="num":
                try:
                    self.sheet.write(self.row,i,float(data[i]))
                except ValueError:
                    pass
            else:
                self.sheet.write(self.row,i,data[i])

        if self.row % self.flushBound == 0:
            self.sheet.flush_row_data()
        self.row+=1

    def save(self):
        self.wb.save(self.name+str(self.workbookIndex)+'.xls')

改换网页特殊字符 鉴于网页也是有温馨特别的转义字符,在进展正则相配的时候就有一点点麻烦。在合日文档中查到八个用字典替换的方案,私以为不错,拿来做了一部分恢弘。在那之中有一对是为保证正则的科学。

复制代码 代码如下:

html_escape_table = {
    "&": "&",
    '"': """,
    "'": "'",
    ">": ">",
    "<": "<",
    u"·":"·",
    u"°":"°",
    #regular expression
    ".":r".",
    "^":r"^",
    "$":r"$",
    "{":r"{",
    "}":r"}",
    "\":r"\",
    "|":r"|",
    "(":r"(",
    ")":r")",
    "+":r"+",
    "*":r"*",
    "?":r"?",
}

def html_escape(text):
    """Produce entities within text."""
    tmp="".join(html_escape_table.get(c,c) for c in text)
    return tmp.encode("utf-8")

得出的经验大概正是这个了。然则最后写出来的主次自已也不忍再看。风格比相当差。一开始想着先写着试试。然后试着试着就不想改了。
最终的主次要跑十分久,当中网络通讯时间占了好多。是或不是足以牵记用二十二十四线程重构一下?想想,照旧就如此吧。

因为涉及到中文,所以自然地关乎到了编码的标题,那三次借这一个时机终于彻底搞明白了。 难题要从文字的编码讲起。原来的英...

本文由六合联盟网发布于编程应用,转载请注明出处:python抓取网页图片,python爬取网站数据保存使用

关键词: