今天遇朋友求助,要從某商業(yè)網(wǎng)站上搜集供應(yīng)商信息。因?yàn)榇耸律跫保旆畔率诸^事情,著手寫(xiě)python3爬蟲(chóng)。話說(shuō)這還是我第一次正式寫(xiě)python3程序,也是第一次寫(xiě)爬蟲(chóng)。還好,比預(yù)想的順利。
以下是爬蟲(chóng)主要代碼,其中略有處理及刪節(jié):
#!/usr/bin/env python3
import requests
import json
from lxml import etree
# url已打馬賽克
url_main = 'https://xxxx.com/data/ajax/get_offer_list.json?beginpage='
url_params = '&keywords=%XX%XX%XX%XX%XX%XX%XX&sortType=&descendOrder=....'
page_count = 50 #源數(shù)據(jù)有分頁(yè),頁(yè)碼越界會(huì)仍舊返回最后一頁(yè)。干脆直接設(shè)定總頁(yè)數(shù)
for pi in range(page_count):
url_req = url_main + str(pi) + url_params
resp = requests.get(url_req).content.decode('utf-8')
idx_from = resp.find('(') + 1
json_obj = resp[idx_from:-1] #取得返回的JSON對(duì)象
hjson = json.loads(json_obj)
count = hjson['data']['offerCount'] #每頁(yè)里的總條數(shù)
for i in range(count):
idx = pi*20+i+1 #每條數(shù)據(jù)設(shè)一個(gè)序列號(hào)
cname = hjson['data']['content']['offerResult'][i]['attr']['company']['name'] #使用XPATH定位到供應(yīng)商名稱
eurl = hjson['data']['content']['offerResult'][i]['eurl'] #找到供應(yīng)商URL鏈接
if eurl.startswith('//'):
eurl = "https:" + eurl #部分鏈接需要加上協(xié)議頭
res_detail = requests.get(eurl) #獲取供應(yīng)商詳情頁(yè)面內(nèi)容
res_detail = res_detail.content.decode('GBK') #頁(yè)面用的GBK編碼,需要解碼
selector = etree.HTML(res_detail)
names = selector.xpath('//a[@class="membername"]') #找到聯(lián)系人名稱
name = ''
if len(names) > 0:
name = names[0].text
else:
names = selector.xpath('//span[@class="disc"]/a') #聯(lián)系人有時(shí)候會(huì)存在另外一處
if len(names) > 0 and not names[0].text.isspace():
name = names[0].text
else:
names = selector.xpath('//div[@class="contactSeller"]/a') #聯(lián)系人還有可能放在這里
if len(names) > 0 and not names[0].text.isspace():
name = names[0].text
cells = selector.xpath('//dl[@class="m-mobilephone"]/@data-no') #找到聯(lián)系電話
cell = ''
if len(cells) > 0:
cell = cells[0]
print(idx, cname, name, cell) #找到了,輸出相關(guān)信息
為了方便使用,爬蟲(chóng)程序的輸出結(jié)果存在test.txt里。檢查文檔發(fā)現(xiàn),供應(yīng)商數(shù)據(jù)填的不完全規(guī)范,比如有的就沒(méi)有填聯(lián)系電話,或者把聯(lián)系電話制作進(jìn)了圖片里。為了簡(jiǎn)化,凡是不符合規(guī)范的一律忽略。
恰好此前還有一份朋友給的Excel通訊錄,后來(lái)稍經(jīng)處理轉(zhuǎn)成了CSV,正好跟這次的爬蟲(chóng)結(jié)果一并整合,直接生成VCF文件,這樣用起來(lái)也方便。于是乎說(shuō)干就干:
#!/usr/bin/env python3
//聯(lián)系人字典
mans = {}
#這個(gè)是爬蟲(chóng)結(jié)果文件
txtFile = open('test.txt', 'r')
for line in txtFile:
segs = line.split()
if len(segs) < 4: #格式不規(guī)范的一律忽略
continue
mobile = int(segs[3]) #電話號(hào)碼作為字典索引,防止重復(fù)
if mobile not in mans:
mans[mobile] = segs[1] + ' ' + segs[2]
txtFile.close()
#這個(gè)是已有的CSV通訊錄
csvFile = open('test.csv', 'r')
for line in csvFile:
segs = line.split(',')
if (segs[2].endswith('\n')): #從Windown平臺(tái)生成的,去掉末尾換行符
segs[2] = segs[2][:-1]
if not segs[2].isdigit(): #不規(guī)范的忽略
continue
mobile = int(segs[2])
if mobile not in mans:
mans[mobile] = segs[1] + ' ' + segs[0]
csvFile.close()
#準(zhǔn)備寫(xiě)入的VCF文件
vcfFile = open('final.vcf', 'w')
#逐行生成VCard聯(lián)系人信息
for mobile, addr_name in mans.items():
idx = addr_name.find(' ')
addr = addr_name[:idx]
name = addr_name[idx+1:]
vcfFile.write('BEGIN:VCARD\n')
vcfFile.write('VERSION:3.0\n')
vcfFile.write('TEL;type=CELL;type=VOICE;type=pref:' + str(mobile) + '\n')
vcfFile.write('N:' + name + '\n')
vcfFile.write('ORG:' + addr + '\n')
vcfFile.write('END:VCARD\n')
vcfFile.close()
朋友測(cè)試使用后,十分高興,以前至少一個(gè)禮拜的工作,讓我半天搞定了。
你的贊賞,我的動(dòng)力!