一、基礎版本其實敦煌網是很客氣的網站,基本上沒有做針對的反爬措施,既然別" />

国产免费一区二区三区香蕉精_国产精品亚洲w码日韩中文ap_无套内射在线观看_中文字幕在线观看国产精品_日韩欧美丝袜另类_国产成人久久精品_清纯唯美亚洲综合激情_2021半夜好用的网站_一夲道岛国无码不卡视频_人妻精品动漫h无码网站

外貿課堂 外貿網站 外貿SEO 付費廣告 社交營銷 外貿營銷 外貿推廣 外貿知識 外貿政策 外貿百科
當前位置:首頁 > 外貿課堂 > 外貿推廣 > 我用python爬取了敦煌網

我用python爬取了敦煌網

做跨境電商,產品的市場行情是非常關鍵的指標,無論是新品開發(fā)還是市場調研都有需求,那么今天我們就來做個敦煌網的產品價格與銷量查詢的工具。

一、基礎版本

其實敦煌網是很客氣的網站,基本上沒有做針對的反爬措施,既然別人這么客氣,我們也要懂得禮貌,做爬蟲的同學都知道爬蟲的基本禮儀。那就是該停就停,能在晚上沒有太多人的時候運行就放在人少的時候,頻率不要太高。不過還我們的工具,一開始就打算按照關鍵詞進行爬取,所以對網站的負擔不會太重,可以放心的使用。

話不多說,先上代碼

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))內容比較簡單,為了讓大家不至于看的太累,注釋什么的大多被我刪除了。 下面我們來簡單的講解下這段代碼。 首先,我們導入要用的包:

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

二、第一次重構

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

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 # 標題 price = item.find("li","price").text # 價格 m = re.findall(r'(/d+/.*/d+)', price) price = mean(list(map(float, m))) # 計算均價 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))老樣子,簡單講解下,其實主體和第一次寫的沒有太大差別,主要是字段解析這里,多添加了一些內容:

for item in items: title = item.find("h3").find("a").text # 標題 price = item.find("li","price").text # 價格 m = re.findall(r'(/d+/.*/d+)', price) price = mean(list(map(float, m))) # 計算均價 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其實還是很好用的,當然,解析速度是相當來說慢了點,不過影響不是太大。后面我們會用lxmlxpath來重構,速度會好很多。對于新手,或者前端不是太理解的人來說,做爬蟲還是比較坑的,我的經驗來說,做爬蟲最好還是要懂點前端, 當然懂得越多越好,爬蟲與前端的反爬蟲一直是這樣相愛相殺,所以你越了解你的敵人,你就越得心就手。

三、用類的思想做個小框架

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







主要內容有scrapy引擎,scheduler調度器,itempipline數(shù)據(jù)處理,downloader下載,spiders爬蟲程序。 我們就模仿這個框架做一個簡單的:

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

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"))主程序內容比較簡單,導入相應的類,構建了一個爬蟲主類,傳入關鍵詞和頁數(shù),爬蟲就愉快的開始爬網了。 核心就在這個craw函數(shù)。 1. 首先url管理器構建一個初始url,告訴爬蟲從哪兒開始爬取。 2. 然后爬蟲開始看url管理器里有沒有新的url,有就獲取新的url,把新的url傳入下載器進行下載。 3. 然后下載器把下載的數(shù)據(jù)傳入解析器進行解析。 4. 數(shù)據(jù)處理器收集解析器解析出來的新數(shù)據(jù)。 5. 數(shù)據(jù)處理器保存數(shù)據(jù)到本地。

下面我們一個一個講解這幾個功能類: - url_manage.py url管理器







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

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






下載器其實很簡單,只有一個方法,就是下載,這里直接引入requests包,使用其相關方法就完成了download方法。

  • html_parser.py 網頁解析器






解析器是整個項目的核心,不過核心代碼其實和第二次重構里差不多,基本上就是把第二次的核心代碼挪過來就可以用了。

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 # 標題 product_url = HtmlParser.format_str( item.select("h3 > a.subject")[0].get("href")) price = item.find("li", "price").text # 價格 min_price, max_price = re.findall(r'(/d+/.*/d+)', price) # 最低價,最高價 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 = { '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就不多說了,parse方法里引用_get_new_data解析完成返回數(shù)據(jù)。

  • html_outputer.py 數(shù)據(jù)處理器
其實這一個叫做數(shù)據(jù)處理器可能不太準確,叫做輸出器可能更好,因為它的主要做用只是輸出數(shù)據(jù)到本地存儲。而且我們真正的數(shù)據(jù)處理其實都在解析器里已經完成了,大家可以看上面的代碼。而且這里只有三個方法.







collect_data 收集前面處理好的數(shù)據(jù) to_html 把數(shù)據(jù)輸出成html格式 to_csv 把數(shù)據(jù)輸出成csv格式,這個就和我們之前做的一樣,不過這里使用了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稍微麻煩點,主要是要寫html特有的標簽,而csv就相當簡單了,csv包里有相應的方法,可以直接使用。

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

后記

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

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

下一篇:【Max觀察】一帶一路上的敦煌網之夢想合作人名錄


相關文章:

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

業(yè)務熱線(微信同號):18143453325

業(yè)務郵箱:[email protected]

業(yè)務QQ:2848414880

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

使命:為國內企業(yè)跨境出海提供動力支持

愿景:打造用戶期待和尊重的外貿服務商

Copy © 外貿巴巴 176study.cn 版權所有備案號:浙ICP備18013128號-2