一、基礎(chǔ)版本其實(shí)敦煌網(wǎng)是很客氣的網(wǎng)站,基本上沒(méi)有做針對(duì)的反爬措施,既然別" />

91香蕉视频黄在线观看|AV免费网站在线观看|亚洲AV无码久久|青青草人人澡国产AV第一页|欧美熟女在线超碰五月天成人|一级黄色片附近的大美女|三级黄色视频无码|中文在线无码熟女|日本成人黄色小电影网站|a国产理论在线观看

外貿(mào)課堂 外貿(mào)網(wǎng)站 外貿(mào)SEO 付費(fèi)廣告 社交營(yíng)銷(xiāo) 外貿(mào)營(yíng)銷(xiāo) 外貿(mào)推廣 外貿(mào)知識(shí) 外貿(mào)政策 外貿(mào)百科
當(dāng)前位置:首頁(yè) > 外貿(mào)課堂 > 外貿(mào)推廣 > 我用python爬取了敦煌網(wǎng)

我用python爬取了敦煌網(wǎng)

做跨境電商,產(chǎn)品的市場(chǎng)行情是非常關(guān)鍵的指標(biāo),無(wú)論是新品開(kāi)發(fā)還是市場(chǎng)調(diào)研都有需求,那么今天我們就來(lái)做個(gè)敦煌網(wǎng)的產(chǎn)品價(jià)格與銷(xiāo)量查詢(xún)的工具。

一、基礎(chǔ)版本

其實(shí)敦煌網(wǎng)是很客氣的網(wǎng)站,基本上沒(méi)有做針對(duì)的反爬措施,既然別人這么客氣,我們也要懂得禮貌,做爬蟲(chóng)的同學(xué)都知道爬蟲(chóng)的基本禮儀。那就是該停就停,能在晚上沒(méi)有太多人的時(shí)候運(yùn)行就放在人少的時(shí)候,頻率不要太高。不過(guò)還我們的工具,一開(kāi)始就打算按照關(guān)鍵詞進(jìn)行爬取,所以對(duì)網(wǎng)站的負(fù)擔(dān)不會(huì)太重,可以放心的使用。

話不多說(shuō),先上代碼

import requestsfrom bs4 import BeautifulSoupimport refrom urllib.parse import quote_plusimport sysdef save_data(url,path='dhgate.csv',data=None): web_data = requests.get(url) soup = BeautifulSoup(web_data.text,'lxml') prices = [] orders = [] for item in soup.select('#proList .price'): m = re.search(r'(/d*./d*) - (/d*./d*)',item.text) if m: price = float(m.group(1))+float(m.group(2)) prices.append(round(price/2,2)) else: pass for item in soup.select('#proList .attribute'): m = re.search(r'Sold: (/d+)',item.text) if m: orders.append(m.group(1)) else: orders.append(None) for price, order in zip(prices,orders): data = { 'price': price, 'order': order } print(data) with open(path,'a') as f: f.write('{},{}/n'.format(data['price'],data['order']))def get_data(key_word,page_num): key_word = quote_plus(key_word) urls = ['http://www.dhgate.com/w/{}/{}.html'.format(key_word,str(i)) for i in range(page_num)] for url in urls: save_data(url,key_word+'.csv')if __name__ == '__main__': key_word,page_num = sys.argv[1:3] get_data(key_word,int(page_num))內(nèi)容比較簡(jiǎn)單,為了讓大家不至于看的太累,注釋什么的大多被我刪除了。 下面我們來(lái)簡(jiǎn)單的講解下這段代碼。 首先,我們導(dǎo)入要用的包:

import requests # requests包主要用來(lái)獲取網(wǎng)頁(yè)內(nèi)容from bs4 import BeautifulSoup # BeautifulSoup用來(lái)解釋網(wǎng)頁(yè)內(nèi)容import re # re包是用正則來(lái)輔助解析用from urllib.parse import quote_plus # quote_plus用來(lái)處理關(guān)鍵詞import sys # sys用來(lái)獲取命令行的參數(shù)主要流程都在__main__里面,我們通過(guò)sys獲取的關(guān)鍵詞和頁(yè)數(shù),這里沒(méi)有異常處理,其實(shí)應(yīng)該對(duì)傳入的參數(shù)進(jìn)行異常處理下的。然后直接運(yùn)行get_data函數(shù)獲取我們所需的數(shù)據(jù)。我們直接在get_data函數(shù)里調(diào)用的save_data把數(shù)據(jù)存儲(chǔ)到csv文件中。 這個(gè)是最早的版本,大概是在2016寫(xiě)的,現(xiàn)在運(yùn)行還是能夠成功。這個(gè)版本,只獲取的價(jià)格與銷(xiāo)量。

二、第一次重構(gòu)

其實(shí)很早就想重構(gòu)一下,一直沒(méi)有動(dòng)力,大概是2017年3月的時(shí)候,有朋友問(wèn)我對(duì)標(biāo)題是怎么做的,終于找到理由重構(gòu)一下了, 簡(jiǎn)單重構(gòu)了下,新代碼比較丑,數(shù)據(jù)儲(chǔ)存還有bug, 當(dāng)時(shí)太晚了,就沒(méi)優(yōu)化了,實(shí)現(xiàn)了獲取產(chǎn)品標(biāo)題,價(jià)格,起訂量,銷(xiāo)量,好評(píng),店鋪地址,賣(mài)家名,店鋪好評(píng)率的獲取。

import requestsfrom bs4 import BeautifulSoupimport refrom urllib.parse import quote_plusimport sysfrom numpy import meandef save_data(url,path='dhgate.csv',data=None): web_data = requests.get(url) soup = BeautifulSoup(web_data.text,'lxml') info = [] items = soup.find_all("div", "listitem") for item in items: title = item.find("h3").find("a").text # 標(biāo)題 price = item.find("li","price").text # 價(jià)格 m = re.findall(r'(/d+/.*/d+)', price) price = mean(list(map(float, m))) # 計(jì)算均價(jià) attribute = item.find("ul", "attribute").text min_order = re.findall(r'Min. Order: (/d+)', attribute)[0] # 起訂量 order = re.findall(r'Sold: (/d+)', attribute) order = order[0] if len(order) > 0 else 0 # 訂單量 feedback = item.find("span","reviewnum") feedback = re.findall(r"/d+", feedback.text)[0] if feedback else 0 seller = list(item.find("span","seller").stripped_strings)[-1] store_url = item.find("span","seller").find("a")['href'] store_feedback = item.find("li","feedback") store_feedback = re.findall(r"/d+/.*/d+", store_feedback.text)[0] if store_feedback else 0 data = { 'title': title, 'price': price, 'min_order': min_order, 'order': order, 'feedback': feedback, 'seller': seller, 'store_url': store_url, 'store_feedback': store_feedback } print(data) with open(path,'a') as f: f.write('{}/t{}/t{}/t{}/t{}/t{}/t{}/t{}/n'.format( data['title'], data['price'], data['min_order'], data['order'], data['feedback'], data['seller'], data['store_url'], data['store_feedback'] ))def get_data(key_word,page_num): key_word = quote_plus(key_word) urls = ['http://www.dhgate.com/w/{}/{}.html'.format(key_word,str(i)) for i in range(page_num)] for url in urls: save_data(url,key_word+'.csv')if __name__ == '__main__': key_word,page_num = sys.argv[1:3] get_data(key_word,int(page_num))老樣子,簡(jiǎn)單講解下,其實(shí)主體和第一次寫(xiě)的沒(méi)有太大差別,主要是字段解析這里,多添加了一些內(nèi)容:

for item in items: title = item.find("h3").find("a").text # 標(biāo)題 price = item.find("li","price").text # 價(jià)格 m = re.findall(r'(/d+/.*/d+)', price) price = mean(list(map(float, m))) # 計(jì)算均價(jià) attribute = item.find("ul", "attribute").text min_order = re.findall(r'Min. Order: (/d+)', attribute)[0] # 起訂量 order = re.findall(r'Sold: (/d+)', attribute) order = order[0] if len(order) > 0 else 0 # 訂單量 feedback = item.find("span","reviewnum") feedback = re.findall(r"/d+", feedback.text)[0] if feedback else 0 seller = list(item.find("span","seller").stripped_strings)[-1] store_url = item.find("span","seller").find("a")['href'] store_feedback = item.find("li","feedback") store_feedback = re.findall(r"/d+/.*/d+", store_feedback.text)[0] if store_feedback else 0BeautifulSoupcss selector其實(shí)還是很好用的,當(dāng)然,解析速度是相當(dāng)來(lái)說(shuō)慢了點(diǎn),不過(guò)影響不是太大。后面我們會(huì)用lxmlxpath來(lái)重構(gòu),速度會(huì)好很多。對(duì)于新手,或者前端不是太理解的人來(lái)說(shuō),做爬蟲(chóng)還是比較坑的,我的經(jīng)驗(yàn)來(lái)說(shuō),做爬蟲(chóng)最好還是要懂點(diǎn)前端, 當(dāng)然懂得越多越好,爬蟲(chóng)與前端的反爬蟲(chóng)一直是這樣相愛(ài)相殺,所以你越了解你的敵人,你就越得心就手。

三、用類(lèi)的思想做個(gè)小框架

前面的內(nèi)容基本已經(jīng)能滿足我們的需求了,但是類(lèi)的思想可以讓我們做到解耦,功能模塊更清晰。 先上一個(gè)scrapy的框架圖來(lái)鎮(zhèn)樓:







主要內(nèi)容有scrapy引擎,scheduler調(diào)度器,itempipline數(shù)據(jù)處理,downloader下載,spiders爬蟲(chóng)程序。 我們就模仿這個(gè)框架做一個(gè)簡(jiǎn)單的:

main.py # 主程序url_manager.py # url管理器html_downloader.py # 下載器 相當(dāng)于scrapy的downloaderhtml_parser.py # 網(wǎng)頁(yè)解析器 scrapy的解析直接就是在spiders里html_outputer.py # 數(shù)據(jù)處理器 相當(dāng)于scrapy的item pipeline有了這幾個(gè)類(lèi),我們已經(jīng)可以完成一個(gè)簡(jiǎn)單的框架了。main.py 里主要是保證任務(wù)的進(jìn)行。

import url_managerimport html_downloaderimport html_outputerimport html_parserclass SpiderMain(object): def __init__(self): self.urls = url_manager.UrlManager() self.downloader = html_downloader.HtmlDownloader() self.parser = html_parser.HtmlParser() self.outputer = html_outputer.HtmlOutputer() def craw(self, key_word, page_num): count = 1 self.urls.build_url(key_word, int(page_num)) while self.urls.has_new_url(): try: new_url = self.urls.get_new_url() print(f"craw {count} : {new_url}") html_cont = self.downloader.download(new_url) new_data = self.parser.parse(new_url, html_cont) self.outputer.collect_data(new_data) count += 1 except Exception as e: print("craw failed", e) self.outputer.to_csv() # return self.outputer.datasif __name__ == "__main__": spider = SpiderMain() print(spider.craw("women dress", "2"))主程序內(nèi)容比較簡(jiǎn)單,導(dǎo)入相應(yīng)的類(lèi),構(gòu)建了一個(gè)爬蟲(chóng)主類(lèi),傳入關(guān)鍵詞和頁(yè)數(shù),爬蟲(chóng)就愉快的開(kāi)始爬網(wǎng)了。 核心就在這個(gè)craw函數(shù)。 1. 首先url管理器構(gòu)建一個(gè)初始url,告訴爬蟲(chóng)從哪兒開(kāi)始爬取。 2. 然后爬蟲(chóng)開(kāi)始看url管理器里有沒(méi)有新的url,有就獲取新的url,把新的url傳入下載器進(jìn)行下載。 3. 然后下載器把下載的數(shù)據(jù)傳入解析器進(jìn)行解析。 4. 數(shù)據(jù)處理器收集解析器解析出來(lái)的新數(shù)據(jù)。 5. 數(shù)據(jù)處理器保存數(shù)據(jù)到本地。

下面我們一個(gè)一個(gè)講解這幾個(gè)功能類(lèi): - url_manage.py url管理器







build_url 構(gòu)建初始網(wǎng)址 add_new_url 添加新的url到管理器 has_new_url 檢查管理器里有沒(méi)有新的url get_new_url 從管理器里獲取新的url show_urls 遍歷管理器里的url 這里的功能實(shí)際上都是針對(duì)的__init__里面設(shè)置的兩個(gè)set,這里沒(méi)有使用數(shù)據(jù)庫(kù),使用數(shù)據(jù)庫(kù)也是一樣的效果。

def __init__(self): self.new_urls = set() self.old_urls = set() self.site = 'http://www.dhgate.com/w/{0}/{1}.html'
  • html_downloader.py 下載器






下載器其實(shí)很簡(jiǎn)單,只有一個(gè)方法,就是下載,這里直接引入requests包,使用其相關(guān)方法就完成了download方法。

  • html_parser.py 網(wǎng)頁(yè)解析器






解析器是整個(gè)項(xiàng)目的核心,不過(guò)核心代碼其實(shí)和第二次重構(gòu)里差不多,基本上就是把第二次的核心代碼挪過(guò)來(lái)就可以用了。

def _get_new_data(self, page_url, soup): items = soup.find_all("div", "listitem") datas = [] for item in items: title = item.find("h3").find("a").text # 標(biāo)題 product_url = HtmlParser.format_str( item.select("h3 > a.subject")[0].get("href")) price = item.find("li", "price").text # 價(jià)格 min_price, max_price = re.findall(r'(/d+/.*/d+)', price) # 最低價(jià),最高價(jià) attribute = item.find("ul", "attribute").text min_order = re.findall(r'Min. Order: (/d+)', attribute)[0] # 起訂量 order = re.findall(r'Sold: (/d+)', attribute) order = order[0] if len(order) > 0 else 0 # 訂單量 feedback = item.find("span", "reviewnum") feedback = re.findall(r"/d+", feedback.text)[0] if feedback else 0 # 產(chǎn)品好評(píng) seller = list(item.find("span", "seller").stripped_strings)[-1] # 賣(mài)家 store_url = item.find("span", "seller").find("a")['href'] # 店鋪鏈接 store_feedback = item.find("li", "feedback") store_feedback = re.findall( r"/d+/.*/d+", store_feedback.text)[0] if store_feedback else 0 # 店鋪評(píng)價(jià) data = { 'page_url': page_url, 'title': title, 'product_url': 'http:' + product_url, 'min_price': min_price, 'max_price': max_price, 'min_order': min_order, 'order': order, 'feedback': feedback, 'seller': seller, 'store_url': store_url, 'store_feedback': store_feedback } datas.append(data) return datas就不多說(shuō)了,parse方法里引用_get_new_data解析完成返回?cái)?shù)據(jù)。

  • html_outputer.py 數(shù)據(jù)處理器
其實(shí)這一個(gè)叫做數(shù)據(jù)處理器可能不太準(zhǔn)確,叫做輸出器可能更好,因?yàn)樗闹饕鲇弥皇禽敵鰯?shù)據(jù)到本地存儲(chǔ)。而且我們真正的數(shù)據(jù)處理其實(shí)都在解析器里已經(jīng)完成了,大家可以看上面的代碼。而且這里只有三個(gè)方法.







collect_data 收集前面處理好的數(shù)據(jù) to_html 把數(shù)據(jù)輸出成html格式 to_csv 把數(shù)據(jù)輸出成csv格式,這個(gè)就和我們之前做的一樣,不過(guò)這里使用了csv包,效率更高

def to_html(self): with open('output.html', 'w') as f: f.write("<html>") f.write("<body>") f.write("<table>") f.write("<tr>") for key in self.datas[0].keys(): f.write(f"<td>{key}</td>") f.write("</tr>") for data in self.datas: f.write("<tr>") for key, value in data.items(): f.write(f"<td>{value}</td>") f.write("</tr>") f.write("</table>") f.write("</body>") f.write("</html>") def to_csv(self, path="output.csv"): with open(path, 'w', newline="") as f: try: writer = csv.DictWriter(f, self.datas[0].keys()) except IndexError: print(self.datas[0].keys()) writer.writeheader() for data in self.datas: writer.writerow(data)可以看到輸出到html稍微麻煩點(diǎn),主要是要寫(xiě)html特有的標(biāo)簽,而csv就相當(dāng)簡(jiǎn)單了,csv包里有相應(yīng)的方法,可以直接使用。

就這樣,整體項(xiàng)目被我們用小框架實(shí)現(xiàn)了。

后記

下一篇,我們用python自帶的圖形庫(kù)tk來(lái)實(shí)現(xiàn)一個(gè)界面,方便普通用法使用。大家記得關(guān)注我公眾號(hào),想要 源碼可以在公眾號(hào)后臺(tái)輸入 0020 獲取。

上一篇:Tik Tok聯(lián)合敦煌網(wǎng)打造私域頂級(jí)帶貨

下一篇:【Max觀察】一帶一路上的敦煌網(wǎng)之夢(mèng)想合作人名錄


相關(guān)文章:

杭州市濱江區(qū)偉業(yè)路3號(hào)

業(yè)務(wù)熱線(微信同號(hào)):18143453325

業(yè)務(wù)郵箱:2848414880@qq.com

業(yè)務(wù)QQ:2848414880

目標(biāo):致力于幫助中國(guó)企業(yè)出海淘金

使命:為國(guó)內(nèi)企業(yè)跨境出海提供動(dòng)力支持

愿景:打造用戶期待和尊重的外貿(mào)服務(wù)商

Copy © 外貿(mào)巴巴 www.cqzsxx.cn 版權(quán)所有備案號(hào):浙ICP備18013128號(hào)-2