因业务需要,在系统中需要将新加坡的地址之邮政编码输入后自动填入除了单元号的其他信息,比如街道名称,门牌号码等资料。靠谱的方法是去购买这个数据,价格在50英镑左右。方便起见,最终是会去购买这个数据的,另外里面还包含了坐标,估计以后也有用处。

在这个网站上http://sgp.postcodebase.com/上找到类似的资料,但是该网站不提供数据下载或购买,如果没有上面的渠道的话,那么只能去抓取这里的内容,处理成自己需要的材料。这个网站网页的结构比较简单,12万多条地址是根据“http://sgp.postcodebase.com/node/1”中的最后那个数字来区分。需要的字段有Postal Code,Street Name,Building No.,Building Name四个而已。看它的源代码,发现它前面的title信息就是要找的资料(这里title前后加了减号是为了注释掉它的属性):

<-title->Og Albert Complex, Albert Street, 60, Singapore, Albert, Bugis, Victoria Street, Rochor, Central: 189969 | Singapore Postcode<-/title->

其中第一个是Building Name,顺着是Street Name,Building No.,Postal Code则是“|”前面的那六位数字。将这个title里面的信息提取出来,稍微处理下就是所要的资料了:

import urllib.request

urls = ['http://sgp.postcodebase.com/node/' + str(i) \
for i in range(1, 3)]

def get_content(url):
    try:
        request = urllib.request.Request(url)
        response = urllib.request.urlopen(request)
        the_page = response.read()
    except:
        the_page = ''
    result = str(the_page)[:1500]
    #print(result)
    return result

def get_address(url):
    page = get_content(url)
    start_quote = page.find('<title>')
    end_quote = page.find('</title>')
    address = page[start_quote + 7:end_quote]
    return address


def modify_address(url):
    old_address = get_address(url)
    #print(old_address)
    address = []
    if len(old_address) > 6:
        temp = old_address.split(', ')
        #print(temp)
        address.append(temp[-1].split(': ')[1][:6])
        if temp[3] == 'Singapore':
            for i in range(2, -1, -1):
                address.append(temp[i])
        else:
            for i in range(1, -1, -1):
                address.append(temp[i])
            address.append('')
    new_address = '    '.join(address)
    return new_address

def update_file(urls):
    for url in urls:
        f = open('e:/address.txt', 'a')
        f.write('%s\n' % modify_address(url))
        f.close()

代码中的urllib.request只能在3.0以上的版本才能够用吧。写入txt文本的地址大概是这样的形式:

189969-**-60-**-Albert Street-**-Og Albert Complex

试运行的结果是,原则上可用,但是实际效果很差。原因如下:

  • 当网络有问题时,程序没有对应的处理方法。
  • 网页有延迟或者抓取不下来时,没有步骤重新去抓取。
  • 由于是单线程,网页的抓取需要一定的时间,估计每个页面需要1到2秒,因此12万多的页面需要几天的时间来抓取下来。
  • 因为以上原因,才做成每次抓取一个信息后,将它写入文件中,以免抓取过程有问题出错前功尽弃。

这样很非常相当不靠谱。搜索了下,要多线程或者同时抓取多个网页,似乎有multiprocessing之类的库可以辅助一下。我得再研究研究。

Leave a Reply

Your email address will not be published. Required fields are marked *

Post Navigation