當然可以。
爬蟲代碼分析
我們首先需要爬取得頁面為?
我們可以看到url為www.mafengwo.cn/group/s.php?q=曼谷&p=1&t=cate&kt=1。主要參數有q?,p?,t,其中q為城市名,p為頁碼,t為分類,cate為美食,kt為不影響參數。
需要獲取該頁面,detail為域名以後的參數,這個函數可以用於獲得域名主頁下的網頁
#獲取下級頁面
def getDetailPage(detailURL):
try:
url = ""+detailURL"
request = urllib2.Request(url)
response = urllib2.urlopen(request)
#利用urllib2的Request方法返回壹個request對象並用urlopen打開
page = response.read()
#用read()方法讀取頁面內容,Input: print page Output: 頁面html
pageCode = re.sub(r'<br[ ]?/?>', '\n', page)
#去掉html裏的回車空行
return pageCode
except urllib2.URLError, e:
if hasattr(e, "reason"):
print e.reason
return None12345678910111213141516
獲得每家美食店鋪的鏈接,首先進行元素檢查查看鏈接位於的位置
#獲得美食單頁店鋪鏈接
def getFoodHref(self,pageid):
url = "/group/s.php?q="+self.city+"&p=" +str(pageid)+ "&t=cate&kt=1"
page = getDetailPage(url) #調用getDetailPage獲得頁面
soup = BeautifulSoup(page,'html.parser') #用BeautifulSoup進行頁面解析
FoodHref = []
FoodLists = ?soup.find(name="div",attrs={'data-category':'poi'}).ul
FoodHrefList = FoodLists.find_all("h3") #找出<div class="_j_search_section" data-category="poi">標簽下所有的<h3>標簽的內容,結果為店鋪列表的html
for FoodHrefs in FoodHrefList:
FoodWebsite = FoodHrefs.a['href'] #對列表循環找出a標簽href屬性的值,即為店鋪的url
FoodHrefShort = str(FoodWebsite).replace('','') #去掉url前的域名,以便等會調用getDetaiL函數,傳入它獲得店鋪頁面
FoodHref.append(FoodHrefShort) return FoodHref123456789101112131415161718
接下來再次調用getDetailPage(),傳入FoodHref,即可可以獲得店鋪的頁面,通過BeautifulSoup進行信息獲取了。但我在抓取的時候遇到壹個問題。?
這是壹個信息齊全的店鋪,但有的店鋪沒有網址,沒有交通信息該怎麽辦。比如這個?
經過元素檢查發現標簽也是壹樣的,無法通過標簽特有的屬性或者class的值進行定向抓取。用<div class="bd">的子節點兄弟節點查也不行。後來想出壹個方法。
先寫壹個匹配函數hasAttr,list參數為壹個中文的完整信息名列表,在getShopInfo方法裏通過循環列表內容與抓取的<div class="bd">標簽內容匹配,如果返回True則表示存在該信息項,否則繼續匹配下壹項。比如上面的圖,先匹配簡介,匹配失敗,繼續匹配英文名字,也失敗,知道匹配到地址,成功,保存地址下壹個標簽的內容。直到獲得所有信息。
#判斷是否存在信息列表
def hasAttr(self,list):
soup = BeautifulSoup(page, 'html.parser')
col = soup.find("div", class_="col-main").find("div", class_="bd")
str_col = str(col) if list in str_col: return True
else: return False
#抓取店鋪信息
def getShopInfo(self,page):
shopInfoList = ['brief','localName','location', 'telephone', 'website', 'ticket', 'openTime','shopName','shopScore']
infoItem = ['簡介', '英文名稱', '地址', '電話', '網址', '門票', '開放時間','名字','星評']
soup = BeautifulSoup(page, 'html.parser')
shopName = soup.find("div", class_="wrapper").h1.string
shopScore = soup.find("div", class_="col-main").span.em.string for i in range(0,6): #信息項循環查找
if self.hasAttr(page, infoItem[i]):
pattern_shopinfo = re.compile( '<div class="col-main.*?<div class="bd">.*?'+ infoItem[i] +'</h3>.*?>(.*?)</p>', re.S)
shopInfos = re.findall(pattern_shopinfo, page) #存在該項則用正則取出其標簽內容
for shopInfo in shopInfos:
shopInfoList[i] = shopInfo else: #繼續查找下壹項
continue
shopInfoList[7] = shopName
shopInfoList[8] = shopScore return shopInfoList1234567891011121314151617181920212223242526272829303132333435
最後將數據加入字典,如果壹鍵對多值,比如dict = {a:[]},調用set default(鍵名,[]).append(列表值)?
dict.setdefault('comment',[]).appnd(comment)
然後json.dumps(dict,indent=1).decode("unicode_escape")。indent參數是為了以json樹形式表現出數據,如果內容中有中文要用decode("unicode_escape"),否則結果為”\u”的unicode編碼