Python爬蟲實戰--58同城二手商品爬蟲
阿新 • • 發佈:2018-11-23
嗚嗚~~本來說今天就把程式碼上傳上來,可惜了,還是有點差錯,今天估計趕不上啦!明天加油吧!
今天我們一起來好好分析一下,看看我們該如何去爬去58二手商品。
這裡我們分成四步來完成本次任務~
目標站點分析
目標URL:http://bj.58.com/sale.shtml
第一步:主頁分析
在主頁裡面,我們需要提取說有的二級分類,特別注意,綠色框的內容,它的格式和內容,如其他的內容相差較大,所以我們一開始就把它剔除,從而在一定程度上減輕程式碼量和工作內容。
# 解析main_url = "http://bj.58.com/sale.shtml" 獲取分類URL def parse_index(self): category_urls = [] html = self.parse_url(self.main_url) soup = BeautifulSoup(html.text, 'lxml') links = soup.select("ul.ym-submnu > li > b > a") for link in links: link_url = urljoin(self.main_url, link.attrs['href']) category_urls.append(link_url) self.DB.insert(collection='Category_urls', item=category_urls)
第二步:提取詳情頁連結
觀察列表頁,我們發現,有一些的詳情頁中不存在‘價格’,所以我們可以在提取詳情頁連結的時候直接將其篩選出來,這樣我們在資料分析的時候就可以少做一點事了。
# 解析分類連結並提取獲取商品詳情URL def parse_page_url(self): items = self.DB.find_data(collection='Category_urls') for item in items: cate_urls = item['category_urls'] for cate_url in cate_urls: page_urls = [] self.proxy = self.get_proxy() if 'tongxunyw' in cate_url: print("error", cate_url) pass elif 'ershouqiugou' in cate_url: print("error", cate_url) pass else: print(cate_url) for i in range(1, 100): print("Parse page ", i) url = cate_url + 'pn{}/'.format(i) html = self.parse_url(url) soup = BeautifulSoup(html.text, 'lxml') trs = soup.select("tr[_pos='0']") for tr in trs: price = tr.select("b.pri")[0].get_text() if price != '面議': temp_link = tr.select("td.t > a:nth-of-type(1)")[0].attrs['href'] page_url = urljoin(self.main_url, temp_link) page_urls.append(page_url) item = dict( page_urls=page_urls, ) self.DB.insert(collection='Page_urls', items=item)
第三步:提取詳情頁資料
由於該詳情頁大致分為三種,所以必須採用三種模式去提取資料,如圖
一眼看上去都差不多,但實際上裡面的內容卻有著很大的差別,比如說來之轉轉的內容,你不能直接衝網頁裡提取,而是的痛過轉轉API,獲取json資料,在提取!筆者在編碼時,也是除錯了很多次才發現,原來這裡有三種頁面。醉了!沒有辦法,只好硬著頭皮,寫下去~
# 解析Old58_urls網頁,pp def parse_page_58(self, page_url): html = self.parse_url(page_url) soup = BeautifulSoup(html.text, 'lxml') temp_title = soup.title.get_text() title = temp_title.split(" - ")[0] try: temp_time = soup.select("div.detail-title__info > div")[0].get_text() time = temp_time.split(" ")[0] temp_price = soup.select("span.infocard__container__item__main__text--price")[0].get_text() price = temp_price.split()[0] temp = soup.select("div.infocard__container > div:nth-of-type(2) > div:nth-of-type(2)")[0].get_text() if '成新' in temp: color = temp temp_area = soup.select("div.infocard__container > div:nth-of-type(3) > div:nth-of-type(2)")[0] else: color = None temp_area = soup.select("div.infocard__container > div:nth-of-type(2) > div:nth-of-type(2)")[0] temp_area = list(temp_area.stripped_strings) area = list(filter(lambda x: x.replace("-", ''), temp_area)) temp_cate = list(soup.select("div.nav")[0].stripped_strings) cate = list(filter(lambda x: x.replace(">", ''), temp_cate)) item = dict( title=title, time=time, price=price, color=color, area=area, cate=cate, ) print(item) self.DB.insert(collection='Page_data', items=item) except: print("Error 404!") # 解析New58_urls網頁,並提取資料 def parse_page_now58(self, page_url): html = self.parse_url(page_url) soup = BeautifulSoup(html.text, 'lxml') try: title = soup.select("div.detail-info-tit")[0].get_text() temp_cate = soup.select("div.nav")[0] temp_cate = list(temp_cate.stripped_strings) cate = list(filter(lambda x: x.replace(">", ''), temp_cate)) ul = soup.select("ul.detail-info-bd")[0] time = ul.select("li:nth-of-type(1) > span:nth-of-type(2)")[0].get_text() color = ul.select("li:nth-of-type(2) > span:nth-of-type(2)")[0].get_text() area = ul.select("li:nth-of-type(3) > span:nth-of-type(2)")[0].get_text() temp_price = soup.select("span.info-price-money")[0].get_text() price = temp_price.split("¥")[-1] item = dict( title=title, time=time, price=price, color=color, area=area, cate=cate, ) print(item) self.DB.insert(collection='Page_data', items=item) except: print("Error 404!") # 解析來自ZZ58_urls網頁,並提取json資料 def parse_page_zz(self, page_url): pattern = re.compile('infoId=(.*?)&', re.S) infoId = re.findall(pattern, page_url) html = self.parse_url(self.temp_api.format(infoId[0])) try: data_json = html.json() data = data_json.get('respData') local = data.get("location") item = dict( title=data.get('title'), browse_times=data.get("browseCount"), price=data.get("nowPrice"), origin_price=data.get("oriPrice"), area=local.get("local"), ) print(item) self.DB.insert(collection='Page_data', items=item) except: print("Error 404!")
第四步:爬蟲邏輯
由於整個的爬去量有點大,內容也相當的多,所以,我把資料都儲存到了MongoDB裡面,方便後續的使用,在爬蟲時,也採用多程序分步的方式去爬去內容。減輕伺服器的承擔量~
# 邏輯實現
def run(self):
if INDEX_ENABLED:
Index_process = Process(target=self.parse_index)
Index_process.start()
if LINK_ENABLED:
PageUrl_process = Process(target=self.parse_page_url)
PageUrl_process.start()
if ITEM_ENABLED:
Page_process = Process(target=self.parse_page)
Page_process.start()
好了,今天的爬蟲,就先講到這裡啦,程式碼裡還有一些問題,明天除錯好了,上傳上來~
原始碼地址:https://github.com/NO1117/Sale58_Spider
Python交流群:942913325 歡迎大家一起交流學習
Question:如何進一步提高爬蟲效率?大家可以考慮一下多執行緒多程序的方式~實現的可以找我聊聊哈