
    h1                         S r SSKrSSKrSSKrSSKrSSKrSSKJr  SSKJ	r	  SSK
r
\
R                  " \5      r " S S5      r " S S\5      r " S	 S
\5      r " S S5      rSS jrS r\S:X  a  \" 5         gg)uH   
价格爬虫模块
支持从京东、淘宝等平台获取产品价格
    N)quote)BeautifulSoupc                   >    \ rS rSrSrS
S jrS rSS jrS rS r	S	r
g)PriceScraper   u   价格爬虫基类Nc                     [         R                  " 5       U l        U R                  R                  R	                  SS05        Xl        U R                  5         g )Nz
User-AgentzsMozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36)requestsSessionsessionheadersupdateplatformload_cookies)selfr   s     &D:\demo\tech_portal\portal\scrapers.py__init__PriceScraper.__init__   sK    '')##  P%
 	 !    c                    U R                   (       a   SSKJn  UR                  S5      (       a  SSKJn  UR                  R                  U R                   SS9R                  S5      R                  5       nU(       ax  UR                  5       nUR                  5        H*  u  pVU R                  R                  R                  XV5        M,     [        R!                  5       Ul        UR%                  5         gggg! [&         a
  n SnAgSnAff = f)	u   从数据库加载Cookier   )appsportal)PlatformCookieT)r   	is_activez-updated_atN)r   django.appsr   is_installedportal.modelsr   objectsfilterorder_byfirstget_cookie_dictitemsr   cookiessettimezonenow	last_usedsave	Exception)r   r   r   
cookie_objcookie_dictkeyvaluees           r   r   PriceScraper.load_cookies   s    ==,$$X..<!/!7!7!>!>!%"& "? " h}-eeg 
 "&0&@&@&B*5*;*;*=JC LL0044S@ +> 08||~
,") " / &  s   C!C8 8
DDc                     [         e)u'   获取产品价格 - 需要子类实现)NotImplementedError)r   product_nameproduct_models      r   	get_pricePriceScraper.get_price5   s    !!r   c                     U(       d  g[         R                  " SS[        U5      5      n [        U5      $ ! [         a     gf = f)u$   清理价格字符串，提取数字        z[^\d.] )resubstrfloat
ValueError)r   	price_strprice_cleans      r   clean_pricePriceScraper.clean_price9   sB     ffYC	N;	%% 		s   
6 
AAc                 Z    [         R                  " [        R                  " SS5      5        g)u   随机延迟，避免被反爬      N)timesleeprandomuniform)r   s    r   delayPriceScraper.delayF   s    

6>>!Q'(r   )r   r   Nr8   )__name__
__module____qualname____firstlineno____doc__r   r   r4   r@   rI   __static_attributes__ r   r   r   r      s    2")r   r   c                   @   ^  \ rS rSrSrSU 4S jjrSS jrS rSrU =r	$ )		JDScraperK   u   京东价格爬虫c                    > [         TU ]  US9  SU l        U R                  R                  R                  SSSSSS.5        g )	Nr   zhttps://search.jd.com/SearchzJtext/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8z;zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2zgzip, deflatez
keep-alive1)AcceptzAccept-LanguagezAccept-Encoding
ConnectionzUpgrade-Insecure-Requests)superr   base_urlr   r   r   r   r   	__class__s     r   r   JDScraper.__init__N   sF    (+6##b\.&),%
 	r   c           
          U SU 3R                  5       nU R                   S[        U5       S3nU R                  R	                  USS9nUR                  5         SUR                  ;   d  SUR                  R                  5       ;   a*  [        R                  SU 35         U R                  5         g	[        UR                  S
5      nUR                  SSS9nU(       d  UR                  SSS9nU(       aI  US   nU R                  U5      n	U	S:  a-  [        R                  SU SU	 35        U	U R                  5         $ / SQn
U
 Hk  nUR!                  U5      nUSS  HN  nU R                  U5      n	U	S:  d  M  [        R                  SU SU SU	 35        U	s  s  U R                  5         $    Mm     [        R                  SU 35         U R                  5         g	! ["         a>  n[        R%                  SW S['        U5       35         SnAU R                  5         g	SnAff = f! U R                  5         f = f)u   从京东获取产品价格 z	?keyword=z
&enc=utf-8   )timeoutu   验证securityu   京东触发反爬虫验证: r7   html.parserdivz	gl-i-wrapclass_lizgl-itemr   u   京东获取价格成功:     - ￥)zspan.p-pricezstrong.J_price	div.pricezi.pricez[data-price]z.priceN   u   京东获取价格成功(): u   京东未找到价格: u   京东价格获取失败:  - )stripr]   r   r   getraise_for_statustexturllowerloggerwarningrI   r   find_allextract_price_from_elementinfoselectr)   errorr;   )r   r2   r3   search_keyword
search_urlresponsesoupproduct_itemsfirst_productpriceprice_selectorsselectorelementselementr.   s                  r   r4   JDScraper.get_priceZ   s    :	 ,~Q}o>DDFN !MM?)E.4I3J*UJ||''
B'?H%%' 8==(J(,,:L:L:N,N!>~>NOPZ JJLW !>D !MM%MDM  $d9 E -a 0 77F19KK"<^<LFSXRY Z[ 6 JJL1O ,;;x0'|G ;;GDEqy&?z^L\\bchbi$jk$ JJL  , , NN4^4DEF JJL	  	LL5n5ESQQRJJL		 JJLsC   B G  4A<G  7G  <#G  0G   
H(*$H#H+ #H((H+ +H=c                 x   UR                  S5      (       a  U R                  US   5      $ UR                  SS9nU R                  U5      nUS:  a  U$ UR                  / SQ[        R
                  " S[        R                  5      S9nU H-  nUR                  SS9nU R                  U5      nUS:  d  M+  Us  $    g)	u   从HTML元素中提取价格
data-priceTrp   r   )spanrg   strongir   rh   r7   )has_attrr@   get_textrx   r9   compileI)r   r   rs   r   price_elementsprice_element
price_texts          r   ry   $JDScraper.extract_price_from_element   s     L))##GL$9:: d+  &19L !))*HQSQ[Q[\dfhfjfjQk)l+M&//d/;J$$Z0Eqy	 , r   r]   rK   rL   )
rM   rN   rO   rP   rQ   r   r4   ry   rR   __classcell__r_   s   @r   rU   rU   K   s    
<| r   rU   c                   :   ^  \ rS rSrSrSU 4S jjrSS jrSrU =r$ )TaobaoScraper   u   淘宝价格爬虫c                 .   > [         TU ]  US9  SU l        g )NrX   zhttps://s.taobao.com/search)r\   r   r]   r^   s     r   r   TaobaoScraper.__init__   s    (+5r   c           
          U SU 3R                  5       nUSSSSSS.nU R                  R                  U R                  USS	9nUR	                  5         [        UR                  S
5      n/ SQnU Hw  nUR                  U5      n	U	 H]  n
U
R                  SS9nU R                  U5      nUS:  d  M+  [        R                  SU SU SU 35        Us  s  U R                  5         $    My     UR                  SS0S9n	U	 HL  n
U R                  U
S   5      nUS:  d  M  [        R                  SU SU 35        Us  U R                  5         $    UR                  S5      nU H  nUR                  (       d  M  SUR                  ;   d  M(   [        R                   " SUR                  5      nU(       a  ["        R$                  " UR'                  S5      5      nSU;   az  SUS   ;   ao  US   S   S   S   nU(       aX  US   nSU;   aK  U R                  US   5      nUS:  a/  [        R                  SU SU 35        Us  U R                  5         $ M  M  M  M  M  M     [        R-                  SU 35         U R                  5         g! ["        R(                  [*        4 a     GMD  f = f! [.         a>  n[        R1                  S W S![3        U5       35         S"nAU R                  5         gS"nAff = f! U R                  5         f = f)#u   从淘宝获取产品价格rb   r8   rC   zsearch_radio_all%3A1staobaoz_20181010utf8)qimgfilejsstats_clickinitiative_idie
   )paramsrd   rf   )zstrong.pricez
span.pricerl   zem.pricezb.pricez[class*="price"]z[class*="Price"]Tr   r   u   淘宝获取价格成功(rn   rk   r   )attrsu&   淘宝获取价格成功(data-price): scriptg_page_configzg_page_config\s*=\s*({.*?});modsitemlistdataauctions
view_priceu    淘宝获取价格成功(JSON): u   淘宝未找到价格: r7   u   淘宝价格获取失败: ro   N)rp   r   rq   r]   rr   r   rs   r{   r   r@   rv   rz   rI   rx   stringr9   searchjsonloadsgroupJSONDecodeErrorKeyErrorrw   r)   r|   r;   )r   r2   r3   r}   r   r   r   r   r   r   r   r   r   script_tagsr   
json_matchr   r"   
first_itemr.   s                       r   r4   TaobaoScraper.get_price   s   M	 ,~Q}o>DDFN $5!4F ||''fb'QH%%' !>DO ,!%X!6-G!(!1!1!1!=J ,,Z8Eqy&?z^L\\bchbi$jk$N JJLY  . , "]],1E]FN)(()>?19KK"HHXX^_d^e fg L> JJLG * --1K%===_%E!%'YY/NPVP]P]%^
%#'::j.>.>q.A#BD%~*V2L(,VZ(@(H(T#(16qJ'3z'A040@0@LAY0Z+019,2KK:Z[iZjjpqvpw8x,y38L JJL ,5 (B $) 3M~ & &( NN4^4DEF JJL !00(; ! !  	LL5n5ESQQRJJL		 JJLss   B,J* 2#J* &4J* J* 'J* 8J* B2J=J* &J* J'"J* &J''J* *
K24$K-K5 -K22K5 5Lr   rK   rL   )	rM   rN   rO   rP   rQ   r   r4   rR   r   r   s   @r   r   r      s    6O Or   r   c                   (    \ rS rSrSr\S 5       rSrg)PriceScraperFactoryi  u   价格爬虫工厂c                     [         [        S.nUR                  U R                  5       5      nU(       a  U" U S9$ [	        SU  35      e)u!   根据平台创建对应的爬虫)jdtaobaorX   u   不支持的平台: )rU   r   rq   ru   r=   )r   scrapersscraper_classs      r   create_scraper"PriceScraperFactory.create_scraper  sI     #

 !X^^%56 (333H:>??r   rS   N)rM   rN   rO   rP   rQ   staticmethodr   rR   rS   r   r   r   r     s    @ @r   r   c                     [         R                  U5      nUR                  X5      nUS::  aj  [        U 5      S-  [        U5      S-  -   n[	        SU[
        R                  " SS5      -   5      n[        R                  SU  SU S	U 35        [        U5      $ U$ ! [         a1  n[        R                  S
U  SU S[        U5       35         SnAgSnAff = f)u   
获取产品价格的便捷函数

Args:
    product_name: 产品名称
    product_model: 产品型号
    platform: 平台名称 (jd, taobao)

Returns:
    float: 产品价格，获取失败返回0.0
r   2      d   i   u   使用模拟价格: rb   rk   u)   价格获取失败，使用默认价格: ro   Ng     @@)r   r   r4   lenmaxrG   randintrv   rz   r<   r)   r|   r;   )r2   r3   r   scraper
real_price
base_pricesimulated_pricer.   s           r   get_product_pricer     s    %44X>&&|C
 ?\*R/#m2Dr2IIJ!#zFNN34L'LMOKK.|nAm_FSbRcde)) @aP]^abefgbhaijks   BB B 
C$'CCc            	          SS/n U  H?  u  pn[        SU SU SU 35        [        XU5      n[        SU 35        [        S5        MA     g)	u   测试爬虫功能)u   华为P50r   )u   小米12r   u   测试 z: rb   u
   结果: ¥z(----------------------------------------N)printr   )test_productsnamemodelr   r   s        r   test_scrapersr   ;  s_     	 "M
 "/XzD65'23!$x8
5'"#h	 "/r   __main__)r8   r   )rQ   r	   r9   r   rE   rG   urllib.parser   bs4r   logging	getLoggerrM   rv   r   rU   r   r   r   r   rS   r   r   <module>r      s   
  	      			8	$7) 7)ta aHVL Vr@ @$B zO r   