renhe_mt_search_5.py 200 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819
  1. import requests
  2. import base64
  3. import cv2
  4. import uiautomator2 as u2
  5. import time
  6. import subprocess
  7. import re
  8. import random
  9. import datetime
  10. import json
  11. from aip import AipOcr
  12. from apscheduler.schedulers.blocking import BlockingScheduler
  13. # from db_mysql import mysqlClient
  14. import threading
  15. from collections import deque
  16. import numpy as np
  17. import secrets
  18. import os
  19. # import pyperclip
  20. from config import Config
  21. from logger import setup_logger
  22. import logging
  23. # from database import MySQLClient
  24. # 配置日志
  25. # logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
  26. setup_logger("mt_spider") # 初始化日志
  27. class SpiderMonitor(threading.Thread):
  28. """全局弹窗监控线程(增强版)"""
  29. def __init__(self, spider_instance):
  30. super().__init__(daemon=True)
  31. self.spider = spider_instance
  32. self.running = True
  33. self.pausing = threading.Event() # 主线程同步事件
  34. self.last_verification_time = 0
  35. self.verification_count = 0
  36. self.MAX_VERIFICATION_RETRY = 10
  37. self.recent_clicks = deque(maxlen=10) # 防重复点击
  38. self.logger = logging.getLogger("SpiderMonitor")
  39. # 可配置化弹窗规则
  40. self.popup_rules = {
  41. "simple": [
  42. ('//*[@text="确定"]', "点击确定"),
  43. ('//*[@text="允许"]', "点击允许"),
  44. ('//*[@text="关闭"]', "点击关闭"),
  45. ('//*[@resource-id="com.sankuai.meituan:id/close"]', "关闭按钮"),
  46. ('//*[@resource-id="com.sankuai.meituan:id/address_center_location_close"]', "关闭按钮"),
  47. ('//*[@resource-id="com.sankuai.meituan:id/location_close"]', "关闭按钮"),
  48. ],
  49. "verification": [
  50. '//*[contains(@text, "验证")]',
  51. '//*[contains(@text, "滑块")]',
  52. '//*[contains(@text, "依次点击")]',
  53. '//*[contains(@text, "请点击")]',
  54. '//*[contains(@text, "拖动滑块刚")]', #这个需要拖动滑块至最右边,然后再截图
  55. '//*[contains(@text, "请输入图片中的内容")]',
  56. '//*[contains(@text, "用最短线连接")]',
  57. '//*[contains(@text, "请按语序依次点击")]',
  58. '//*[contains(@text, "请向右滑动滑块")]',
  59. '//*[contains(@text, "请拖动下方滑块完成拼图")]',
  60. '//*[contains(@resource-id, "captcha")]'
  61. ]
  62. }
  63. def run(self):
  64. while self.running:
  65. try:
  66. handled = self.check_and_handle_popup()
  67. time.sleep(2 if handled else 1)
  68. except Exception as e:
  69. self.logger.exception("监控线程异常: %s", e)
  70. time.sleep(3)
  71. def _is_recent_click(self, xpath):
  72. """防止重复点击同一个弹窗"""
  73. key = f"{xpath}_{int(time.time())}"
  74. if key in self.recent_clicks:
  75. return True
  76. self.recent_clicks.append(key)
  77. return False
  78. def check_and_handle_popup(self):
  79. d = self.spider.d
  80. # 1. 处理简单弹窗
  81. for xpath, desc in self.popup_rules["simple"]:
  82. if d.xpath(xpath).exists and not self._is_recent_click(xpath):
  83. self.logger.info("检测到弹窗: %s", desc)
  84. d.xpath(xpath).click()
  85. return True
  86. # 2. 处理验证码弹窗
  87. for xpath in self.popup_rules["verification"]:
  88. if d.xpath(xpath).exists:
  89. now = time.time()
  90. if now - self.last_verification_time < 30:
  91. return False # 30秒内不重复触发
  92. self.last_verification_time = now
  93. self.verification_count += 1
  94. self.logger.warning("验证码弹窗触发,等待人工处理...")
  95. if self.verification_count > self.MAX_VERIFICATION_RETRY:
  96. self.logger.error("验证码重试超限,终止任务")
  97. # self.spider.stop_all()
  98. return True
  99. self.pausing.set() # 通知主线程暂停
  100. # d.toast.show("需要人工处理验证码", 120)
  101. # 等待人工处理
  102. start = time.time()
  103. # while time.time() - start < 120*60:
  104. # if not d.xpath(xpath).exists:
  105. # self.logger.info("验证码已处理")
  106. # d.toast.show("验证完成", 2)
  107. # self.pausing.clear() # 放行主线程
  108. # return True
  109. # time.sleep(5)
  110. while True:
  111. if not d.xpath(xpath).exists:
  112. self.logger.info("验证码已处理")
  113. # d.toast.show("验证完成", 2)
  114. self.pausing.clear() # 放行主线程
  115. return True
  116. time.sleep(5)
  117. self.logger.warning("验证码超时,重启APP")
  118. self.spider.restart_app()
  119. return True
  120. # 3. 处理广告弹窗(点击右上角)
  121. if d.xpath('//*[contains(@text, "广告")]').exists:
  122. w, h = d.info['displayWidth'], d.info['displayHeight']
  123. d.click(w - 50, 50)
  124. self.logger.info("关闭广告弹窗")
  125. return True
  126. return False
  127. def stop(self):
  128. self.running = False
  129. def get_access_token():
  130. AppKey = "tRK2RhyItCSh6BzyT4CNVXQa"
  131. AppSrcret = "TDgKiPo94i2mOM1sDqOuDnlcK1bG66jh"
  132. token_url = 'https://aip.baidubce.com/oauth/2.0/token'
  133. url = f"{token_url}?grant_type=client_credentials&client_id={AppKey}&client_secret={AppSrcret}"
  134. payload = ""
  135. headers = {
  136. 'Content-Type': 'application/json',
  137. 'Accept': 'application/json'
  138. }
  139. response = requests.request("POST", url, headers=headers, data=payload)
  140. try:
  141. return response.json()['access_token']
  142. except:
  143. return None
  144. def get_mysql():
  145. """
  146. 建立并返回一个到数据库的连接对象
  147. """
  148. import pymysql
  149. return pymysql.connect(
  150. host = Config.DB_HOST, #"localhost", # 修改后的主机
  151. port = Config.DB_PORT, #3306, # 添加端口号
  152. user = Config.DB_USER, #'root', # 修改后的用户名
  153. password = Config.DB_PASSWORD, # 修改后的密码
  154. db = Config.DB_NAME, #"drug_data", # 修改后的数据库名
  155. charset='utf8mb4'
  156. )
  157. class MT:
  158. def __init__(self, key):
  159. # self.package_name = 'com.sankuai.meituan'
  160. self.package_name = Config.PACKAGE_NAME
  161. self.access_token = get_access_token()
  162. self.city2province = self.get_city_info()
  163. self.APP_ID = '116857964'
  164. self.API_KEY = '1gAzACJOAr7BeILKqkqPOETh'
  165. self.SECRET_KEY = 'ZNArANb9GwJYgLKg4EfYhukKBfPdl1n3'
  166. self.client = AipOcr(self.APP_ID, self.API_KEY, self.SECRET_KEY)
  167. # host = Config.DB_HOST #"localhost"
  168. # user = Config.DB_USER #"root"
  169. # password = Config.DB_PASSWORD #"dfwy2025"
  170. # database = Config.DB_NAME #"drug_data"
  171. # port = Config.DB_PORT#3306
  172. # print(f'数据库配置:host:{host},user:{user},password:{password},database:{database},port:{port}')
  173. self.table_name = Config.DB_RH_TABLE #"mt_drug_middle"
  174. self.shop_table_name = Config.DB_RH_SHOP_TABLE
  175. # print(f'数据库表名:table_name:{self.table_name},shop_table_name:{self.shop_table_name}')
  176. # self.mysql_client = mysqlClient(host, user, password, database, port)
  177. self.loggerMT = logging.getLogger()
  178. self.search_key = key # 参苓健脾胃颗粒 舒肝颗粒 清肺化痰丸 香砂平胃颗粒
  179. self.unrelated_data = 0 # 无关数据数量
  180. self.shop_data_num = 0 # 店铺数据数量
  181. def stop_app(self):
  182. self.d.app_stop(self.package_name)
  183. time.sleep(5)
  184. def start_app(self):
  185. self.d.app_start(self.package_name)
  186. time.sleep(5)
  187. def restart_app(self):
  188. """
  189. 重启app
  190. :return:
  191. """
  192. self.stop_app()
  193. self.start_app()
  194. @staticmethod
  195. def get_sleep_time():
  196. # return random.randint(5, 8)
  197. return random.randint(1, 3)
  198. @staticmethod
  199. def get_current_date():
  200. return datetime.datetime.now().strftime('%Y/%m/%d')
  201. @staticmethod
  202. def get_city_info():
  203. """
  204. 获取所有的省市数据
  205. :return:
  206. """
  207. file_path = '../kailin_city.json'
  208. with open(file_path, 'r', encoding='utf-8') as f:
  209. data = json.load(f)
  210. province = {province_one["id"]: province_one for province_one in data['province']}
  211. city2province = dict()
  212. city = data['city']
  213. for city_one in city:
  214. name = city_one['name']
  215. pid = city_one['pid']
  216. if len(str(pid)) > 2:
  217. pid = int(re.match('^\d{2}', str(pid)).group())
  218. city2province[name] = province[pid]['name']
  219. return city2province
  220. def get_shop_name(self):
  221. """
  222. 获取店铺名
  223. :return:
  224. """
  225. try:
  226. shop_name = self.d.xpath(
  227. '//android.widget.ScrollView/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[last()]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[3]/android.widget.FrameLayout[1]/android.widget.TextView').text
  228. print(f'获取到店铺名:{shop_name}')
  229. return shop_name
  230. except:
  231. try:
  232. shop_name = self.d.xpath(
  233. '//android.widget.ScrollView/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[last()-1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[3]/android.widget.FrameLayout[1]/android.widget.TextView').text
  234. print(f'获取到店铺名2:{shop_name}')
  235. return shop_name
  236. except Exception as e:
  237. #点击店铺曲获取店铺名称
  238. print("点击店铺进入后获取店铺名称")
  239. self.enter_shop()
  240. shop_xpath = '//*[@resource-id="com.sankuai.meituan:id/layout_header_view"]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]//android.widget.FrameLayout[2]/android.widget.FrameLayout[1]/android.widget.TextView'
  241. if self.d.xpath(shop_xpath).exists:
  242. shop_name = self.d.xpath(shop_xpath).text
  243. self.swipe_back(1)
  244. return shop_name
  245. else:
  246. print(f'获取店铺名出错:{e}')
  247. return None
  248. def get_qualification_number(self):
  249. """
  250. 获取资质编号
  251. :return:
  252. """
  253. try:
  254. qualification_number_str = self.d.xpath(
  255. '//*[@resource-id="com.sankuai.meituan:id/mil_container"]/android.webkit.WebView[1]/android.webkit.WebView[1]/android.view.View[1]/android.view.View[1]/android.widget.TextView[2]').text
  256. qualification_number = qualification_number_str.strip('资质编号:').strip()
  257. return qualification_number
  258. except:
  259. return None
  260. def get_shop_address(self):
  261. try:
  262. xpath = '//*[@resource-id="com.sankuai.meituan:id/wm_sc_drug_shop_content_mrn_container_id_2"]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.widget.ScrollView[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.widget.TextView'
  263. if self.d.xpath(xpath).exists:
  264. shop_address = self.d.xpath(xpath).text
  265. print(f'111-获取到店铺地址:{shop_address}')
  266. if '发货时间' in shop_address:
  267. print(f'店铺地址包含发货时间,再次获取店铺地址')
  268. xpath2 = '//*[@resource-id="com.sankuai.meituan:id/wm_sc_drug_shop_content_mrn_container_id_2"]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.widget.ScrollView[1]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.widget.TextView'
  269. if self.d.xpath(xpath2).exists:
  270. shop_address = self.d.xpath(xpath2).text
  271. print(f'222-获取到店铺地址:{shop_address}')
  272. else:
  273. print(f'222-xpath2获取店铺地址失败')
  274. else:
  275. shop_address = ''
  276. print(f'333-获取到店铺地址:{shop_address}')
  277. return shop_address
  278. except:
  279. print(f'获取店铺地址出错-get_shop_address')
  280. return None
  281. def enter_detail(self):
  282. self.d.xpath('//*[@resource-id="com.sankuai.meituan:id/recycler"]/android.widget.FrameLayout[1]').click()
  283. time.sleep(self.get_sleep_time())
  284. def save_to_database(self, data):
  285. print(f'保存数据到数据库:{data}')
  286. # 连接数据库
  287. conn = get_mysql()
  288. # 创建游标对象
  289. cur = conn.cursor()
  290. # add_sql = "insert into delete_friend_table(delete_user_name,delete_user_id,delete_content,delete_time) value(%s,%s,%s,%s)"
  291. add_sql = f"""
  292. INSERT INTO {self.table_name}
  293. (product, min_price, manufacture_date, expiry_date, shop, business_license_company, province, city, manufacturer, specification, approval_number, product_link, scrape_date, scrape_province, availability, credit_code, platform, search_key)
  294. VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
  295. """
  296. # cur.execute(add_sql, (data['product'], data['min_price'], data['manufacture_date'], data['expiry_date'], data['shop'], data['business_license_company'],data['province'], data['city'], data['manufacturer'], data['specification'], data['approval_number'], data['product_link'], self.get_current_date(), data['scrape_province'], data['availability'], data['credit_code'], data['platform']))
  297. cur.execute(add_sql, (data['product'], data['min_price'], data['manufacture_date'], data['expiry_date'], data['shop'], data['business_license_company'],data['province'], data['city'], data['manufacturer'], data['specification'], data['approval_number'], data['product_link'], data['scrape_date'], data['scrape_province'], data['availability'], data['credit_code'], data['platform'], data['search_key']))
  298. conn.commit() # 提交数据
  299. #self.mysql_client.insert(self.table_name, data)
  300. print(f"存入数据库成功")
  301. def save_shop_info_to_database(self, data):
  302. print(f'保存店铺数据到数据库:{data}')
  303. # 连接数据库
  304. conn = get_mysql()
  305. # 创建游标对象
  306. cur = conn.cursor()
  307. add_sql = f"""
  308. INSERT INTO {self.shop_table_name}
  309. (shop, contact_address, qualification_number, business_license_company, business_license_address, scrape_date, platform)
  310. VALUES (%s, %s, %s, %s, %s, %s, %s)
  311. """
  312. cur.execute(add_sql, (data['shop'], data['contact_address'], data['qualification_number'], data['business_license_company'], data['business_license_address'], data['scrape_date'], data['platform']))
  313. conn.commit() # 提交数据
  314. #self.mysql_client.insert(self.shop_table_name, data)
  315. print(f'存入店铺信息到数据库成功')
  316. def swipe_up(self):
  317. """
  318. 上滑
  319. :return:
  320. """
  321. screen_width = self.d.info['displayWidth']
  322. screen_height = self.d.info['displayHeight']
  323. duration_rate = random.uniform(0, 0.3)
  324. self.d.swipe(screen_width // 2, screen_height - 100, screen_width // 2, 100, duration=duration_rate)
  325. no = random.uniform(0, 1)
  326. if no > 0.85:
  327. # 有的时候卡着 再稍微往上滑一点点
  328. self.d.swipe_ext("up", 0.1)
  329. time.sleep(self.get_sleep_time())
  330. def swipe_back(self, no):
  331. """
  332. 返回
  333. :param no: 回退次数
  334. :return:
  335. """
  336. for idx in range(no):
  337. self.d.press('back')
  338. time.sleep(self.get_sleep_time())
  339. def drug_price(self):
  340. """
  341. 获取药品价格
  342. :return:
  343. """
  344. try:
  345. price_str = self.d.xpath('//*[starts-with(@text,"¥")]').text
  346. price = float(re.search('[\d\.]+', price_str).group())
  347. print(f'获取到价格:{price}')
  348. return price
  349. except Exception as e:
  350. print(f'提取价格出错-->{e}')
  351. return None
  352. def restart_uiautomator_services(self, device_id):
  353. """
  354. 重启atx的uiautomator 服务
  355. :param device_id:
  356. :return:
  357. """
  358. stop_uiautomator_services = f'adb -s {device_id} shell /data/local/tmp/atx-agent server -d --stop'
  359. start_uiautomator_services = f'adb -s {device_id} shell /data/local/tmp/atx-agent server -d'
  360. # result = subprocess.run(stop_uiautomator_services, capture_output=True, text=True, shell=True)
  361. # print(result.stdout)
  362. subprocess.run(stop_uiautomator_services, capture_output=True, text=True, shell=True)
  363. time.sleep(self.get_sleep_time())
  364. subprocess.run(start_uiautomator_services, capture_output=True, text=True, shell=True)
  365. time.sleep(self.get_sleep_time())
  366. def connect_devices(self, device_id):
  367. """
  368. 连接设备
  369. :return:
  370. """
  371. try:
  372. self.d = u2.connect_usb(device_id)
  373. # 设置隐形等待时间
  374. # self.d.implicitly_wait(5)
  375. self.restart_uiautomator_services(device_id)
  376. print(f'连接到设备:{device_id}')
  377. except Exception as e:
  378. print(f'{device_id} 连接错误: {e}')
  379. raise Exception(e)
  380. def get_ocr_res(self, img):
  381. try:
  382. #img地址
  383. print(f'开始识别图片:{img}')
  384. request_url = "https://aip.baidubce.com/rest/2.0/ocr/v1/business_license"
  385. # 二进制方式打开图片文件
  386. f = open(img, 'rb')
  387. img = base64.b64encode(f.read())
  388. params = {"image": img}
  389. # access_token = get_access_token()
  390. request_url = request_url + "?access_token=" + self.access_token
  391. headers = {'content-type': 'application/x-www-form-urlencoded'}
  392. response = requests.post(request_url, data=params, headers=headers)
  393. if response:
  394. res = response.json()
  395. new_dic = dict()
  396. for ite in res['words_result'].keys():
  397. new_dic[ite] = res['words_result'][ite]['words']
  398. print('资质数据信息', new_dic)
  399. return new_dic
  400. else:
  401. return None
  402. except:
  403. return None
  404. def remove_watermark(self, img_path):
  405. """
  406. 图片去水印(将水印部分变成白色背景)并将数据转化为二进制数据
  407. :param img_path: 图片路径
  408. :return: 二进制图片数据
  409. """
  410. img = cv2.imdecode(np.fromfile(img_path, dtype=np.uint8), -1)
  411. endswith = os.path.splitext(img_path)[1]
  412. new = np.clip(1.4057577998008846 * img - 38.33089999653017, 0, 255).astype(np.uint8)
  413. _, img_binary = cv2.imencode(endswith, new)
  414. return img_binary
  415. def get_ocr_res_image(self, img):
  416. try:
  417. image = self.remove_watermark(img)
  418. # image_file = open(img,'wb')
  419. # image_file.write(image)
  420. # res_image = self.client.basicAccurate(image) # 高精度
  421. res_image = self.client.basicGeneral(image)
  422. # print(f'百度api返回结果:{res_image}')
  423. # print(res_image.get('words_result', ''))
  424. # new_dic = dict()
  425. data = res_image.get('words_result', '')
  426. print(f'百度api返回结果:{data}')
  427. # full_text = ';'.join(item['words'] for item in data)
  428. # address = ''
  429. # for item in data:
  430. # if '企业注册号' in item['words']:
  431. # print('come in 111')
  432. # reg_number = item['words'].split(':', 1)[1].strip()
  433. # elif '企业名称' in item['words']:
  434. # print('come in 222')
  435. # company_name = item['words'].split(':', 1)[1].strip()
  436. # elif '所:' in item['words']:
  437. # print('come in 333')
  438. # address = item['words'].split(':', 1)[1].strip()
  439. # # 输出结果
  440. # print("企业注册号:", reg_number)
  441. # print("企业名称:", company_name)
  442. # print("住所:", address)
  443. return data
  444. except:
  445. return None
  446. def screenshot_the_business_license(self, qualification_number):
  447. screenshot_path = 'screenshot1.png'
  448. self.d.screenshot(screenshot_path)
  449. img = cv2.imread(screenshot_path)
  450. # 指定裁剪区域 (left, top, right, bottom)
  451. left = 0
  452. top = 480
  453. right = 720
  454. bottom = 1420
  455. cropped_img = img[top:bottom, left:right]
  456. if qualification_number:
  457. cropped_screenshot_path = 'D:\\work\\dfwy_spider\\drug_data\\mt\\screenshot\\' + qualification_number + '.png'
  458. else:
  459. cropped_screenshot_path = 'cropped_screenshot.png'
  460. cv2.imwrite(cropped_screenshot_path, cropped_img)
  461. return cropped_screenshot_path
  462. def screenshot_instruction(self):
  463. # 获取当前时间
  464. current_time = datetime.datetime.now()
  465. # 格式化为时分秒
  466. time_str = current_time.strftime("%H-%M-%S")
  467. # 生成随机的 8 位字符串
  468. random_str = secrets.token_hex(4) # 生成 4 个字节的随机字符串,转换为 8 位十六进制字符串
  469. print(time_str)
  470. screenshot_path = 'instructionscreenshot1-' + time_str + '-' + random_str + '.png'
  471. self.d.screenshot(screenshot_path)
  472. return screenshot_path
  473. #获取商品title
  474. def get_title(self):
  475. # try:
  476. # title = self.d.xpath(
  477. # '//android.widget.ScrollView/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[3]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.widget.FrameLayout[1]/android.widget.TextView').text
  478. # except:
  479. # title = self.d.xpath(
  480. # '//android.widget.ScrollView/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[3]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.widget.TextView').text
  481. # title = self.d.xpath('//*[contains(@text, "舒肝颗粒")]').text
  482. def _inner():
  483. temp_search_key = self.search_key
  484. if '仁和' in self.search_key:
  485. if self.search_key == '仁和可立克复方氨酚烷胺胶囊12粒':
  486. temp_search_key = self.search_key.replace("仁和可立克", "")
  487. temp_search_key = temp_search_key.replace("12粒", "")
  488. elif self.search_key == '仁和咽炎片(薄膜衣片)':
  489. temp_search_key = self.search_key.replace("仁和", "")
  490. temp_search_key = temp_search_key.replace("(薄膜衣片)", "")
  491. elif self.search_key == '仁和中方消炎镇痛膏':
  492. temp_search_key = self.search_key.replace("仁和中方", "")
  493. elif self.search_key == '仁和藿香正气合剂10ml*6':
  494. temp_search_key = self.search_key.replace("仁和", "")
  495. temp_search_key = temp_search_key.replace("10ml*6", "")
  496. elif self.search_key == '仁和可立克磷酸奥司他韦胶囊':
  497. temp_search_key = self.search_key.replace("仁和可立克", "")
  498. elif self.search_key == '仁和可立克感冒软胶囊':
  499. temp_search_key = self.search_key.replace("仁和可立克", "")
  500. else:
  501. temp_search_key = self.search_key.replace("仁和", "")
  502. else:
  503. if self.search_key == '伊康美宝甲硝唑氯己定洗剂':
  504. temp_search_key = self.search_key.replace("伊康美宝", "")
  505. elif self.search_key == '闪亮萘敏维滴眼液':
  506. temp_search_key = self.search_key.replace("闪亮", "")
  507. elif self.search_key == '闪亮复方门冬维甘滴眼液':
  508. temp_search_key = self.search_key.replace("闪亮", "")
  509. elif self.search_key == '米阿卡小儿止咳糖浆':
  510. temp_search_key = self.search_key.replace("米阿卡", "")
  511. elif self.search_key == '达舒克硝酸益康唑喷雾剂':
  512. temp_search_key = self.search_key.replace("达舒克", "")
  513. elif self.search_key == '闪亮盐酸奥洛他定滴眼液':
  514. temp_search_key = self.search_key.replace("闪亮", "")
  515. elif self.search_key == '闪亮左氧氟沙星滴眼液':
  516. temp_search_key = self.search_key.replace("闪亮", "")
  517. elif self.search_key == '妇炎洁植物本草抑菌洗液380ml':
  518. temp_search_key = self.search_key.replace("妇炎洁", "")
  519. temp_search_key = temp_search_key.replace("380ml", "")
  520. elif self.search_key == '妇炎洁洁阴康洗液':
  521. temp_search_key = self.search_key.replace("妇炎洁", "")
  522. elif self.search_key == '妇炎洁医用护理垫245*70':
  523. temp_search_key = self.search_key.replace("妇炎洁", "")
  524. temp_search_key = temp_search_key.replace("245*70", "")
  525. elif self.search_key == '妇炎洁克霉唑阴道片':
  526. temp_search_key = self.search_key.replace("妇炎洁", "")
  527. elif self.search_key == '优卡丹葡萄糖酸钙锌口服溶液':
  528. temp_search_key = self.search_key.replace("优卡丹", "")
  529. elif self.search_key == '优卡丹小儿氨酚烷胺颗粒':
  530. temp_search_key = self.search_key.replace("优卡丹", "")
  531. elif self.search_key == '克快好强力枇杷露':
  532. temp_search_key = self.search_key.replace("克快好", "")
  533. elif self.search_key == '君扬他达拉非片':
  534. temp_search_key = self.search_key.replace("君扬", "")
  535. elif self.search_key == '米阿卡头孢克肟颗粒':
  536. temp_search_key = self.search_key.replace("米阿卡", "")
  537. elif self.search_key == '克快好治咳枇杷合剂':
  538. temp_search_key = self.search_key.replace("克快好", "")
  539. elif self.search_key == '优卡丹三合钙咀嚼片':
  540. temp_search_key = self.search_key.replace("优卡丹", "")
  541. elif self.search_key == '必艾得吲哚美辛巴布膏':
  542. temp_search_key = self.search_key.replace("必艾得", "")
  543. elif self.search_key == '宁新宝葡萄糖酸钙片':
  544. temp_search_key = self.search_key.replace("宁新宝", "")
  545. elif self.search_key == '闪亮玻璃酸钠滴眼液':
  546. temp_search_key = self.search_key.replace("闪亮", "")
  547. elif self.search_key == '闪亮地夸磷索钠滴眼液':
  548. temp_search_key = self.search_key.replace("闪亮", "")
  549. elif self.search_key == '闪亮复方尿维氨滴眼液':
  550. temp_search_key = self.search_key.replace("闪亮", "")
  551. elif self.search_key == '闪亮盐酸莫西沙星滴眼液':
  552. temp_search_key = self.search_key.replace("闪亮", "")
  553. print(f'获取商品title时的搜索关键字:{temp_search_key}')
  554. # title = self.d.xpath(f'//*[contains(@text, "{self.search_key}")]').text
  555. #初始化
  556. drugs_name = ''
  557. specifications = ''
  558. title = ''
  559. #循环的获取title为了有时间来处理人机验证
  560. for m in range(1, 6000) :
  561. if self.d.xpath(f'//*[contains(@text, "{temp_search_key}")]').exists:
  562. title = self.safe_exec(
  563. lambda: self.d.xpath(f'//*[contains(@text, "{temp_search_key}")]').text
  564. )
  565. print(f"第{m}次获取title成功")
  566. break
  567. else:
  568. time.sleep(3)
  569. # return drugs_name, specifications
  570. # drugs_name = ''
  571. # specifications = ''
  572. # try:
  573. # title_xpath = '//*[@resource-id="com.sankuai.meituan:id/container"]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[3]/android.widget.FrameLayout[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.widget.ScrollView[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[3]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.widget.FrameLayout[1]/android.widget.TextView'
  574. # title_xpath_2 = '//*[@resource-id="com.sankuai.meituan:id/container"]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[3]/android.widget.FrameLayout[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.widget.ScrollView[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[3]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.widget.FrameLayout[1]/android.widget.TextView'
  575. # if self.d.xpath(title_xpath).exists:
  576. # title = self.d.xpath(title_xpath).text
  577. # print(f"title_xpath获取的title={title}")
  578. # if temp_search_key not in title:
  579. # return drugs_name, specifications
  580. # elif self.d.xpath(title_xpath_2).exists:
  581. # title = self.d.xpath(title_xpath_2).text
  582. # print(f"title_xpath_2获取的title={title}")
  583. # if temp_search_key not in title:
  584. # return drugs_name, specifications
  585. # else:
  586. # print('title_xpath不存在,请确认')
  587. # return drugs_name, specifications
  588. # # title = self.d.xpath(f'//*[contains(@text, "{temp_search_key}")]').text
  589. # except Exception as e:
  590. # print(f"发生异常: {e}")
  591. # return drugs_name, specifications
  592. #奇怪:有的时候title取出来的记过第一位会多一个0
  593. # title = self.safe_exec(self.d.xpath(f'//*[contains(@text, "{self.search_key}")]').text)
  594. # title = self.d.xpath('//*[@resource-id="com.sankuai.meituan:id/com.sankuai.meituan:id/container"]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[3]/android.widget.FrameLayout[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.widget.ScrollView[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[3]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.widget.FrameLayout[1]/android.widget.TextView').text
  595. title = title[1:] if title.startswith('0') else title
  596. print(f'获取到药品标题:{title}')
  597. # 从里面匹配出药品名和规格
  598. # drugs_name
  599. # specifications
  600. # match = re.search(r'([^\d]+)([\d\D]+)', title)
  601. if self.search_key == '999赐多康大豆':
  602. return title, '1罐'
  603. if self.search_key == "999感冒清热颗粒" :
  604. match = re.search(r'(\[[^\]]+\])(.+?)(\d+.*)', title)
  605. else:
  606. match = re.match(r'(\[[^\]]+\])(.*?)\s*((?:\d+\S*|\(.+))$', title)
  607. if match:
  608. #drugs_name = match.group(1).strip() + match.group(2).strip()
  609. drugs_name = title
  610. specifications = match.group(3).strip()
  611. print("药品名:", drugs_name)
  612. print("规格:", specifications)
  613. # print('完整药名:', drugs_name + specifications)
  614. return drugs_name, specifications
  615. else:
  616. if title == '999抗病毒口服液10ml*12' or title == '999抗病毒口服液':
  617. drugs_name = title
  618. specifications = '10ml*12支/盒'
  619. return drugs_name, specifications
  620. elif title == '999抗病毒口服液10ml*10':
  621. drugs_name = title
  622. specifications = '10ml*10支/盒'
  623. return drugs_name, specifications
  624. elif title == '999小柴胡颗粒':
  625. drugs_name = title
  626. specifications = '10g*9袋/盒'
  627. return drugs_name, specifications
  628. elif title == '999养胃舒颗粒':
  629. drugs_name = title
  630. specifications = '10g*6袋/盒'
  631. return drugs_name, specifications
  632. elif title == '三九胃泰胶囊':
  633. drugs_name = title
  634. specifications = '0.5g*24粒/盒'
  635. return drugs_name, specifications
  636. elif title == '999补脾益肠丸':
  637. drugs_name = title
  638. specifications = '6g*15袋/盒'
  639. return drugs_name, specifications
  640. elif title == '999复方感冒灵颗粒':
  641. drugs_name = title
  642. specifications = '14g*9袋/盒'
  643. return drugs_name, specifications
  644. else:
  645. print("没有匹配到预期格式")
  646. drugs_name = title
  647. specifications = ''
  648. return drugs_name, specifications
  649. # 用 safe_exec 包装内部逻辑,确保验证码阻塞
  650. return self.safe_exec(_inner)
  651. def enter_shop(self):
  652. """
  653. 进店,方便提取资质环境
  654. :return:
  655. """
  656. # self.d.xpath('//*[@text="进店"]').click()
  657. self.d.xpath('//*[@text="店铺"]').click()
  658. time.sleep(self.get_sleep_time())
  659. def enter_shoper(self):
  660. """
  661. 进入商家
  662. :return:
  663. """
  664. is_shoper_exists = 0
  665. for i in range(10):
  666. if self.d.xpath('//*[@text="商家"]').exists:
  667. print(f'第{i}次商家存在')
  668. is_shoper_exists = 1
  669. break
  670. else:
  671. print(f'第{i}次商家不存在')
  672. time.sleep(self.get_sleep_time())
  673. if is_shoper_exists == 1:
  674. self.d.xpath('//*[@text="商家"]').click()
  675. time.sleep(self.get_sleep_time())
  676. return True
  677. else:
  678. return False
  679. #点击查看商家资质
  680. def scan_shoper_license(self):
  681. exist_shoper = 0
  682. for i in range(10):
  683. if self.d.xpath('//*[@text="查看商家资质"]').exists:
  684. print(f'第{i}次查看商家资质存在')
  685. exist_shoper = 1
  686. break
  687. else:
  688. print(f'第{i}次查看商家资质不存在')
  689. time.sleep(self.get_sleep_time())
  690. if exist_shoper == 1:
  691. self.d.xpath('//*[@text="查看商家资质"]').click()
  692. time.sleep(self.get_sleep_time())
  693. else:
  694. self.swipe_back(1)
  695. #验证商品的信息是否在数据库中已存在
  696. def data_is_exists(self, data):
  697. """
  698. 检查指定数据是否已存在于数据库表中(仅检查存在性)
  699. 参数:
  700. data: 包含查询条件的字典,键为列名,值为条件值
  701. 返回:
  702. True: 数据存在
  703. False: 数据不存在
  704. None: 检查过程中出错
  705. """
  706. # dup_data = {'product': product, 'min_price': min_price, 'shop': shop, 'scrape_date': scrape_date,
  707. # 'platform': '美团'}
  708. # 1. 验证必要字段
  709. required_keys = ['product', 'min_price', 'shop', 'scrape_date', 'platform']
  710. if not all(key in data for key in required_keys):
  711. missing = [key for key in required_keys if key not in data]
  712. logging.error(f"缺少必要字段: {', '.join(missing)}")
  713. return None
  714. try:
  715. # 连接数据库
  716. conn = get_mysql()
  717. # 创建游标对象
  718. cur = conn.cursor()
  719. # query_sql = f"SELECT * FROM {self.table_name} WHERE product = '{data['product']}' AND min_price = '{data['min_price']}' AND shop = '{data['shop']}' AND scrape_date = '{data['scrape_date']}' AND platform = '{data['platform']}'"
  720. # cur.execute(query_sql)
  721. query_sql = """
  722. SELECT * FROM {}
  723. WHERE product = %s
  724. AND min_price = %s
  725. AND shop = %s
  726. AND scrape_date = %s
  727. AND platform = %s
  728. """.format(self.table_name)
  729. cur.execute(query_sql, (
  730. data['product'],
  731. data['min_price'],
  732. data['shop'],
  733. data['scrape_date'],
  734. data['platform']
  735. ))
  736. result = cur.fetchone()
  737. return bool(result) # 如果存在返回True,否则False
  738. except Exception as e:
  739. print(f"MySQL 错误: {str(e)}")
  740. #验证店铺信息是否在数据库中已存在
  741. def shop_is_exists_database(self, shop):
  742. try:
  743. # 连接数据库
  744. conn = get_mysql()
  745. # 创建游标对象
  746. cur = conn.cursor()
  747. query_sql = """
  748. SELECT * FROM {}
  749. WHERE shop = %s
  750. """.format(self.shop_table_name)
  751. cur.execute(query_sql, (
  752. shop
  753. ))
  754. result = cur.fetchone()
  755. return bool(result) # 如果存在返回True,否则False
  756. except Exception as e:
  757. print(f"MySQL 错误: {str(e)}")
  758. def wait_if_verifying(self, monitor, timeout=120):
  759. """验证码处理期间阻塞主线程"""
  760. start = time.time()
  761. while monitor.pausing.is_set() and time.time() - start < timeout:
  762. time.sleep(1)
  763. # def safe_xpath(self, xpath, timeout=10):
  764. # """线程安全 xpath 查找"""
  765. # self.wait_if_verifying(self.monitor)
  766. # return self.d.xpath(xpath).wait(timeout=timeout)
  767. def wait_for_ready(self, monitor, timeout=86400):
  768. """进入每一页前都先等验证码"""
  769. start = time.time()
  770. while monitor.pausing.is_set() and time.time() - start < timeout:
  771. time.sleep(1)
  772. # 额外保险:如果验证码突然在这一秒才弹,再主动扫一次
  773. monitor.check_and_handle_popup()
  774. def safe_list(self, xpath, monitor):
  775. """线程安全地拿商品列表"""
  776. self.wait_for_ready(monitor)
  777. return self.d.xpath(xpath).all()
  778. def safe_exec(self, func, *args, **kwargs):
  779. """
  780. 万能安全壳:执行 func 前检查验证码,
  781. 若监控线程已置位 pausing,则一直阻塞直到放行。
  782. """
  783. while self.monitor.pausing.is_set():
  784. time.sleep(1)
  785. # 执行真正逻辑
  786. return func(*args, **kwargs)
  787. def get_next_data(self, data, target):
  788. for i, item in enumerate(data):
  789. if item['words'] == target:
  790. if i + 1 < len(data):
  791. return data[i + 1]['words']
  792. return None
  793. def delete_instruction_screenshot(self, screenshot_path):
  794. # 删除截图文件
  795. try:
  796. os.remove(screenshot_path)
  797. print(f"截图文件已删除:{screenshot_path}")
  798. except FileNotFoundError:
  799. print(f"文件未找到,无法删除:{screenshot_path}")
  800. except Exception as e:
  801. print(f"删除文件时出错:{e}")
  802. '''
  803. def get_instructions_data(self):
  804. """
  805. 确定有说明书之后,提取所有的说明书数据
  806. :return:
  807. """
  808. self.d.xpath('//*[@text="说明"]').click()
  809. # time.sleep(random.randint(3, 5))
  810. time.sleep(0.5)
  811. self.d.xpath('//*[@text="查看详细说明"]').click()
  812. # time.sleep(random.randint(3, 5))
  813. time.sleep(0.5)
  814. self.d.xpath('//*[@text="加载更多"]').click_exists()
  815. loop_page = 5
  816. # new_list = list()
  817. new_list = []
  818. for i in range(loop_page):
  819. self.d.xpath('//*[@text="加载更多"]').click_exists()
  820. time.sleep(0.2)
  821. if i == 0:
  822. self.d.swipe(200, 1000, 200, 300, 0.4)
  823. else:
  824. self.d.swipe(200, 1000, 200, 62)
  825. time.sleep(0.2)
  826. if self.d.xpath('//*[@text="加载更多"]').exists:
  827. self.d.xpath('//*[@text="加载更多"]').click()
  828. time.sleep(0.2)
  829. all_tt = self.d.xpath(
  830. '//*[@resource-id="com.sankuai.meituan:id/container"]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[3]/android.widget.FrameLayout[1]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[3]/android.widget.ScrollView[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup').all()
  831. for idx in range(1, len(all_tt) + 1):
  832. all_tt1 = self.d.xpath(
  833. f'//*[@resource-id="com.sankuai.meituan:id/container"]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[3]/android.widget.FrameLayout[1]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[3]/android.widget.ScrollView[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[{idx}]//android.widget.TextView').all()
  834. # print(f'当前说明书列表数据:{all_tt1}')
  835. for tt in all_tt1:
  836. if tt.text and tt.text != '展开全文':
  837. new_list.append(tt.text)
  838. if i == 0:
  839. height = 938
  840. else:
  841. drug_box = self.d.xpath(
  842. '//*[@resource-id="com.sankuai.meituan:id/container"]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[3]/android.widget.FrameLayout[1]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[3]/android.widget.ScrollView[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]').info
  843. bounds = drug_box['bounds']
  844. height = bounds['bottom'] - bounds['top']
  845. if height < 938:
  846. # print('说明书翻页到底部')
  847. break
  848. # 展开全文
  849. new_list = [item for item in new_list if item != '展开全文']
  850. print(f'当前说明书列表数据:{new_list}')
  851. # expiry_date_index = next(idx for idx, i in enumerate(new_list) if i == '有效期')
  852. # manufacturer_index = next(idx for idx, i in enumerate(new_list) if i == '生产单位')
  853. # approval_number_index = next(idx for idx, i in enumerate(new_list) if i == '批准文号')
  854. # res_data = {
  855. # "有效期": new_list[expiry_date_index + 1],
  856. # "生产单位": new_list[manufacturer_index + 1],
  857. # "批准文号": new_list[approval_number_index + 1]
  858. # }
  859. res_data = {
  860. "有效期": (new_list[new_list.index("有效期") + 1]) if "有效期" in new_list and new_list.index("有效期") + 1 < len(new_list) else "",
  861. "生产单位": (new_list[new_list.index("生产单位") + 1]) if "生产单位" in new_list and new_list.index("生产单位") + 1 < len(new_list) else "",
  862. "批准文号": (new_list[new_list.index("批准文号") + 1]) if "批准文号" in new_list and new_list.index("批准文号") + 1 < len(new_list) else ""
  863. }
  864. print(f'当前说明书字典数据:{res_data}')
  865. return res_data
  866. '''
  867. '''
  868. def get_instructions_data(self):
  869. """
  870. 确定有说明书之后,提取所有的说明书数据
  871. :return:
  872. """
  873. self.d.xpath('//*[@text="说明"]').click()
  874. # time.sleep(random.randint(3, 5))
  875. time.sleep(0.5)
  876. self.d.xpath('//*[@text="查看详细说明"]').click()
  877. # time.sleep(random.randint(3, 5))
  878. time.sleep(0.5)
  879. # 1) 先向上滑动一次,触发“加载更多”出现
  880. self.d.swipe(200, 1000, 200, 300, 0.4)
  881. time.sleep(0.3)
  882. # 2) 再进入“出现就点”的循环
  883. while self.d.xpath('//*[@text="加载更多"]').click_exists(timeout=1):
  884. time.sleep(0.2)
  885. self.d.swipe(200, 1000, 200, 300, 0.4)
  886. # self.d.swipe(200, 1000, 200, 62)
  887. time.sleep(0.2)
  888. # 一次性获取所有文本
  889. texts = [
  890. node.text.strip()
  891. # for node in self.d.xpath('//android.widget.TextView').all()
  892. for node in self.d.xpath('//*[@resource-id="com.sankuai.meituan:id/container"]//android.widget.TextView').all()
  893. if node.text and node.text.strip() and node.text != '加载更多'
  894. ]
  895. print(f'当前说明书列表数据:{texts}')
  896. # 提取关键字段
  897. def safe_get(key):
  898. # try:
  899. # idx = texts.index(key)
  900. # return texts[idx + 1] if idx + 1 < len(texts) else ""
  901. # except ValueError:
  902. # return ""
  903. try:
  904. idx = next(i for i, text in enumerate(texts) if text == key)
  905. return texts[idx + 1] if idx + 1 < len(texts) else ""
  906. except StopIteration:
  907. return ""
  908. res_data = {
  909. "有效期": safe_get("有效期"),
  910. "生产单位": safe_get("生产单位"),
  911. "批准文号": safe_get("批准文号")
  912. }
  913. print(f'当前说明书字典数据:{res_data}')
  914. return res_data
  915. '''
  916. '''
  917. def get_instructions_data(self):
  918. """
  919. 说明书键值对采集:连续两个 TextView 为一对,精确提取
  920. """
  921. # 1. 进入说明书
  922. self.d(text="说明").click()
  923. time.sleep(0.5)
  924. self.d(text="查看详细说明").click()
  925. time.sleep(0.5)
  926. # self.d(text="加载更多").click_exists(timeout=0.5)
  927. # 2. 找到说明书最外层 ScrollView(页面主体)
  928. scroll_view = self.d(resourceId="com.sankuai.meituan:id/container") .child(className="android.widget.ScrollView")
  929. count = scroll_view.count
  930. print(f"找到的 ScrollView 数量: {count}")
  931. if not scroll_view.exists:
  932. return {"有效期": "", "生产单位": "", "批准文号": ""}
  933. # 3. 在 ScrollView 内再定位真正包含键值对的容器
  934. # 绝大多数美团说明书页面对应的是 ScrollView > ViewGroup > 若干 TextView
  935. kv_container = scroll_view.child(className="android.view.ViewGroup")
  936. if not kv_container.exists:
  937. kv_container = scroll_view # 降级:直接对 ScrollView 取子孙 TextView
  938. # 4. 滑动到底并收集所有 TextView(保留顺序)
  939. all_texts = []
  940. max_swipe = 5
  941. last_length = 0
  942. for _ in range(max_swipe):
  943. texts = kv_container.child(className="android.widget.TextView")
  944. #获取texts中的文本
  945. print(f'当前说明书列表数据:{texts}')
  946. current_texts = []
  947. self.loggerMT.info(f'说明书111')
  948. for tv in texts:
  949. try:
  950. txt = tv.get_text().strip()
  951. # txt = tv.info['text'].strip()
  952. except Exception:
  953. continue
  954. if txt and txt != "展开全文":
  955. current_texts.append(txt)
  956. self.loggerMT.info(f'说明书222')
  957. print(f'当前说明书列表数据:{current_texts}')
  958. # 去重
  959. if current_texts:
  960. current_texts = [t for t in current_texts if t not in all_texts]
  961. all_texts.extend(current_texts)
  962. # 判断是否到底
  963. # if not scroll_view.info.get("scrollable"):
  964. # break
  965. # 判断是否到底
  966. if len(all_texts) == last_length:
  967. break
  968. last_length = len(all_texts)
  969. # self.d.swipe_ext("up", scale=0.7)
  970. #向上滑动一次
  971. self.d.swipe(200, 1000, 200, 300, 0.2)
  972. time.sleep(0.2)
  973. if self.d.xpath('//*[@text="加载更多"]').exists:
  974. self.d.xpath('//*[@text="加载更多"]').click()
  975. # 5. 成对解析
  976. res_data = {"有效期": "", "生产单位": "", "批准文号": ""}
  977. for i in range(len(all_texts) - 1):
  978. key = all_texts[i]
  979. val = all_texts[i + 1]
  980. if key in res_data:
  981. res_data[key] = val
  982. print(f'说明书文本共 {len(all_texts)} 条,提取结果: {res_data}')
  983. # time.sleep(1000000)
  984. return res_data
  985. '''
  986. def get_instructions_data(self):
  987. """
  988. 确定有说明书之后,提取所有的说明书数据
  989. :return:
  990. """
  991. self.d.xpath('//*[@text="说明"]').click()
  992. # time.sleep(random.randint(3, 5))
  993. time.sleep(0.5)
  994. if self.d.xpath('//*[@text="查看详细说明"]').exists:
  995. self.d.xpath('//*[@text="查看详细说明"]').click()
  996. else:
  997. for i in range(8):
  998. if self.d.xpath('//*[@text="查看全部"]').exists:
  999. print('开始点击查看全部')
  1000. break
  1001. self.d.swipe_ext('down', 0.3)
  1002. time.sleep(1)
  1003. if self.d.xpath('//*[@text="查看全部"]').exists:
  1004. print('开始点击查看全部2')
  1005. break
  1006. if self.d.xpath('//*[@text="查看全部"]').exists:
  1007. self.d.xpath('//*[@text="查看全部"]').click()
  1008. else:
  1009. res_data = {
  1010. "有效期": '',
  1011. "生产单位": '',
  1012. "批准文号": ''
  1013. }
  1014. self.loggerMT.info('获取到的说明书信息为空。')
  1015. return res_data
  1016. # time.sleep(random.randint(3, 5))
  1017. time.sleep(0.5)
  1018. # self.d.xpath('//*[@text="加载更多"]').click_exists()
  1019. # loop_page = 5
  1020. # new_list = list()
  1021. # new_list = []
  1022. for ii in range(8):
  1023. if self.d.xpath('//*[@text="加载更多"]').exists:
  1024. self.d.xpath('//*[@text="加载更多"]').click()
  1025. time.sleep(0.2)
  1026. break
  1027. else:
  1028. self.d.swipe(200, 1000, 200, 300, 0.3)
  1029. # self.d.swipe_ext("up", scale=0.3)
  1030. for iii in range(10):
  1031. if self.d.xpath('//*[@text="生产单位"]').exists and self.d.xpath('//*[@text="批准文号"]').exists:
  1032. break
  1033. else:
  1034. self.d.swipe(200, 1300, 200, 300, 0.3)
  1035. # self.d.swipe_ext("up", scale=0.3)
  1036. instruction_path = self.screenshot_instruction()
  1037. print(f"instruction_path= {instruction_path}")
  1038. time.sleep(2)
  1039. ocr_res = self.get_ocr_res_image(instruction_path)
  1040. # print(f'ocr_res:{ocr_res}')
  1041. if ocr_res:
  1042. # 获取有效期的下一个数据
  1043. validity = self.get_next_data(ocr_res, '有效期')
  1044. # 获取批准文号的下一个数据
  1045. approval_number = self.get_next_data(ocr_res, '批准文号')
  1046. # 获取生产单位的下一个数据
  1047. manufacturer = self.get_next_data(ocr_res, '生产单位')
  1048. else:
  1049. validity = ''
  1050. approval_number = ''
  1051. manufacturer = ''
  1052. # print("有效期:", validity)
  1053. # print("批准文号:", approval_number)
  1054. # print("生产单位:", manufacturer)
  1055. res_data = {
  1056. "有效期": validity,
  1057. "生产单位": manufacturer,
  1058. "批准文号": approval_number
  1059. }
  1060. print(f"res_data={res_data}")
  1061. time.sleep(1)
  1062. self.delete_instruction_screenshot(instruction_path)
  1063. return res_data
  1064. def has_instructions(self):
  1065. """
  1066. 是否有说明书
  1067. :return:
  1068. """
  1069. # 没有说明书的无法采集具体数据
  1070. time.sleep(self.get_sleep_time())
  1071. is_has_instructions = False
  1072. for i in range(8):
  1073. if self.d.xpath('//*[@text="说明"]').exists:
  1074. print(f"第{i}次有说明书1")
  1075. is_has_instructions = True
  1076. break
  1077. self.d.swipe_ext('down', 0.3)
  1078. time.sleep(1)
  1079. # detail_info = self.d.xpath(
  1080. # '//android.widget.ScrollView/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[6]').info
  1081. # bounds = detail_info['bounds']
  1082. # height = bounds['bottom'] - bounds['top']
  1083. # if self.d.xpath('//*[@text="进店"]').exists and height > 100:
  1084. if self.d.xpath('//*[@text="说明"]').exists:
  1085. is_has_instructions = True
  1086. print(f"第{i}次有说明书2")
  1087. break
  1088. # is_has_instructions = self.d.xpath('//*[@text="说明"]').exists
  1089. return is_has_instructions
  1090. def has_shop(self):
  1091. """
  1092. 是否有进店按钮
  1093. :return:
  1094. """
  1095. # self.d.swipe_ext('up', 0.1)
  1096. time.sleep(self.get_sleep_time())
  1097. is_has_enter_shop = self.d.xpath('//*[@text="进店"]').exists
  1098. return is_has_enter_shop
  1099. #获取商品对应的店铺信息
  1100. def get_license_info_ex(self):
  1101. # self.enter_shop()
  1102. self.safe_exec(self.enter_shop)
  1103. # self.enter_shoper()
  1104. result = self.safe_exec(self.enter_shoper)
  1105. if result == False:
  1106. license_info_data = {'contact_address': '', 'qualification_number': '', 'business_license_company': '', 'business_license_address': ''}
  1107. return license_info_data
  1108. for i in range(10):
  1109. if self.d.xpath('//*[@text="查看商家资质"]').exists:
  1110. print(f"第{i}次有商家资质")
  1111. break
  1112. else:
  1113. print(f"第{i}次没有商家资质")
  1114. time.sleep(self.get_sleep_time())
  1115. #获取地址
  1116. # contact_address = self.get_shop_address()
  1117. contact_address = self.safe_exec(self.get_shop_address)
  1118. # time.sleep(50000)
  1119. ###
  1120. # self.scan_shoper_license()
  1121. self.safe_exec(self.scan_shoper_license)
  1122. # 获取资质编码
  1123. # qualification_number = self.get_qualification_number()
  1124. qualification_number = self.safe_exec(self.get_qualification_number)
  1125. #qualification_number 不为None继续下一步
  1126. if qualification_number:
  1127. #营业执照公司名称
  1128. business_license_company = ''
  1129. #营业执照地址
  1130. business_license_address = ''
  1131. self.d.click(0.603, 0.27)
  1132. time.sleep(self.get_sleep_time())
  1133. cropped_screenshot_path = self.screenshot_the_business_license(qualification_number)
  1134. print(f'cropped_screenshot_path:{cropped_screenshot_path}')
  1135. # if qualification_number:
  1136. # cropped_screenshot_path = 'D:\\work\\dfwy_spider\\drug_data\\mt\\screenshot\\' + qualification_number + '.png'
  1137. # else:
  1138. # cropped_screenshot_path = 'cropped_screenshot.png'
  1139. # ocr_res = self.get_ocr_res('cropped_screenshot.png')
  1140. ocr_res = self.get_ocr_res(cropped_screenshot_path)
  1141. print(f'ocr_res:{ocr_res}')
  1142. #获取ocr_res 中的地址、单位名称
  1143. if ocr_res:
  1144. if '单位名称' in ocr_res.keys():
  1145. business_license_company = ocr_res['单位名称']
  1146. if '地址' in ocr_res.keys():
  1147. business_license_address = ocr_res['地址']
  1148. license_info_data = {'contact_address': contact_address, 'qualification_number': qualification_number, 'business_license_company': business_license_company, 'business_license_address': business_license_address}
  1149. else:
  1150. license_info_data = {'contact_address': contact_address, 'qualification_number': '', 'business_license_company': '', 'business_license_address': ''}
  1151. return license_info_data
  1152. """暂不用该功能
  1153. def get_license_info(self):
  1154. self.enter_shop()
  1155. self.enter_shoper()
  1156. self.scan_shoper_license()
  1157. # 获取资质编码
  1158. qualification_number = self.get_qualification_number()
  1159. if qualification_number:
  1160. table_license_info = self.get_table_license_info(qualification_number)
  1161. if table_license_info:
  1162. return {
  1163. '单位名称': table_license_info[0],
  1164. '地址': table_license_info[1],
  1165. '社会信用代码': table_license_info[2]
  1166. }
  1167. else:
  1168. # operate_no = random.randint(0, 1)
  1169. self.d.click(0.603, 0.27)
  1170. # if operate_no == 0:
  1171. # self.d.xpath('//*[@text="营业执照"]').click()
  1172. # else:
  1173. # self.d.click(0.603, 0.27)
  1174. time.sleep(self.get_sleep_time())
  1175. self.screenshot_the_business_license()
  1176. ocr_res = self.get_ocr_res('cropped_screenshot.png')
  1177. return ocr_res
  1178. # operate_no = random.randint(0, 1)
  1179. self.d.click(0.603, 0.27)
  1180. # if operate_no == 0:
  1181. # self.d.xpath('//*[@text="营业执照"]').click()
  1182. # else:
  1183. # self.d.click(0.603, 0.27)
  1184. time.sleep(self.get_sleep_time())
  1185. self.screenshot_the_business_license()
  1186. ocr_res = self.get_ocr_res('cropped_screenshot.png')
  1187. return ocr_res
  1188. """
  1189. def distinct_target(self):
  1190. result = False
  1191. position_xpath = '//*[@resource-id="com.sankuai.meituan:id/container"]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[3]/android.widget.FrameLayout[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[3]'
  1192. position_xpath2 = '//*[@resource-id="com.sankuai.meituan:id/container"]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[2]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[3]/android.widget.FrameLayout[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[3]'
  1193. is_position = self.d.xpath(position_xpath).exists
  1194. is_position2 = self.d.xpath(position_xpath2).exists
  1195. xpath = '//*[@resource-id="com.sankuai.meituan:id/container"]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[3]/android.widget.FrameLayout[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.widget.ScrollView[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.support.v7.widget.RecyclerView[1]/android.widget.FrameLayout[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.widget.HorizontalScrollView[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[last()]'
  1196. xpath2 = '//*[@resource-id="com.sankuai.meituan:id/container"]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[3]/android.widget.FrameLayout[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.widget.ScrollView[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.support.v7.widget.RecyclerView[1]/android.widget.FrameLayout[2]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.widget.HorizontalScrollView[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[last()]'
  1197. xpath3 = '//*[@resource-id="com.sankuai.meituan:id/container"]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[2]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[3]/android.widget.FrameLayout[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.support.v7.widget.RecyclerView[1]/android.widget.FrameLayout[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.widget.HorizontalScrollView[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[last()]'
  1198. xpath4 = '//*[@resource-id="com.sankuai.meituan:id/container"]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[2]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[3]/android.widget.FrameLayout[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.support.v7.widget.RecyclerView[1]/android.widget.FrameLayout[2]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.widget.HorizontalScrollView[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[last()]'
  1199. is_position5 = self.d.xpath(xpath).exists
  1200. is_position6 = self.d.xpath(xpath2).exists
  1201. is_position7 = self.d.xpath(xpath3).exists
  1202. is_position8 = self.d.xpath(xpath4).exists
  1203. # print(f"is_position = {is_position}")
  1204. # print(f"is_position2 = {is_position2}")
  1205. if result == False:
  1206. print("---检测没有回到列表页---")
  1207. else:
  1208. print("---检测回到了列表页---")
  1209. if is_position or is_position2 or is_position5 or is_position6 or is_position7 or is_position8:
  1210. result = True
  1211. return result
  1212. # return is_position
  1213. def enter_target_page(self):
  1214. self.d.xpath('//*[@content-desc="看病买药"]').click()
  1215. time.sleep(self.get_sleep_time())
  1216. self.d.xpath('//*[@resource-id="com.sankuai.meituan:id/vf_search_carousel_text"]').click()
  1217. time.sleep(self.get_sleep_time())
  1218. self.d.xpath('//*[@resource-id="com.sankuai.meituan:id/container"]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[3]/android.widget.FrameLayout[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[1]').click()
  1219. time.sleep(self.get_sleep_time())
  1220. self.d.send_keys(self.search_key, clear=True)
  1221. time.sleep(self.get_sleep_time())
  1222. self.d.xpath('//*[@text="搜索"]').click()
  1223. time.sleep(self.get_sleep_time())
  1224. # content_frame = self.d.xpath('//*[@resource-id="com.sankuai.meituan:id/container"]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[2]').exists
  1225. # print(content_frame)
  1226. # position_xpath1 = '//*[@resource-id="com.sankuai.meituan:id/container"]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[3]/android.widget.FrameLayout[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[3]'
  1227. # position_xpath2 = '//*[@resource-id="com.sankuai.meituan:id/container"]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[2]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[3]/android.widget.FrameLayout[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[3]'
  1228. # if self.d.xpath(position_xpath1).exists:
  1229. # print("position_xpath1 exist")
  1230. # elif self.d.xpath(position_xpath2).exists:
  1231. # print("position_xpath2 exist")
  1232. # else:
  1233. # print("position_xpath not exist")
  1234. # time.sleep(10000)
  1235. #增加点击快递送
  1236. self.click_express_send()
  1237. time.sleep(self.get_sleep_time())
  1238. def click_express_send(self):
  1239. # xpath= '//*[@resource-id="com.sankuai.meituan:id/container"]//android.widget.HorizontalScrollView[last()]'
  1240. slide_xpath = '//*[@resource-id="com.sankuai.meituan:id/container"]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[3]/android.widget.FrameLayout[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.widget.ScrollView[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.support.v7.widget.RecyclerView[1]/android.widget.FrameLayout[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.widget.HorizontalScrollView[1]'
  1241. slide_xpath2= '//*[@resource-id="com.sankuai.meituan:id/container"]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[3]/android.widget.FrameLayout[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.widget.ScrollView[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.support.v7.widget.RecyclerView[1]/android.widget.FrameLayout[2]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.widget.HorizontalScrollView[1]'
  1242. slide_xpath3= '//*[@resource-id="com.sankuai.meituan:id/container"]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[2]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[3]/android.widget.FrameLayout[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.support.v7.widget.RecyclerView[1]/android.widget.FrameLayout[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.widget.HorizontalScrollView[1]'
  1243. slide_xpath4= '//*[@resource-id="com.sankuai.meituan:id/container"]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[2]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[3]/android.widget.FrameLayout[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.support.v7.widget.RecyclerView[1]/android.widget.FrameLayout[2]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.widget.HorizontalScrollView[1]'
  1244. '''
  1245. for i in range (1,3):
  1246. if self.d.xpath(slide_xpath).exists:
  1247. bounds = self.d.xpath(slide_xpath).info['bounds']
  1248. top = bounds['top']
  1249. bottom = bounds['bottom']
  1250. print(f'top={top}')
  1251. print(f'bottom={bottom}')
  1252. y = (top + bottom) // 2
  1253. print(f'y={y}')
  1254. self.loggerMT.info('开始滑动1')
  1255. self.d.swipe(500, y, 100, y, 0.5)
  1256. time.sleep(self.get_sleep_time())
  1257. break
  1258. elif self.d.xpath(slide_xpath2).exists:
  1259. bounds = self.d.xpath(slide_xpath2).info['bounds']
  1260. top = bounds['top']
  1261. bottom = bounds['bottom']
  1262. print(f'top={top}')
  1263. print(f'bottom={bottom}')
  1264. y = (top + bottom) // 2
  1265. print(f'y={y}')
  1266. self.loggerMT.info('开始滑动2')
  1267. self.d.swipe(500, y, 100, y, 0.5)
  1268. time.sleep(self.get_sleep_time())
  1269. break
  1270. elif self.d.xpath(slide_xpath3).exists:
  1271. bounds = self.d.xpath(slide_xpath3).info['bounds']
  1272. top = bounds['top']
  1273. bottom = bounds['bottom']
  1274. print(f'top={top}')
  1275. print(f'bottom={bottom}')
  1276. y = (top + bottom) // 2
  1277. print(f'y={y}')
  1278. self.loggerMT.info('开始滑动3')
  1279. self.d.swipe(500, y, 100, y, 0.5)
  1280. time.sleep(self.get_sleep_time())
  1281. break
  1282. elif self.d.xpath(slide_xpath4).exists:
  1283. bounds = self.d.xpath(slide_xpath4).info['bounds']
  1284. top = bounds['top']
  1285. bottom = bounds['bottom']
  1286. print(f'top={top}')
  1287. print(f'bottom={bottom}')
  1288. y = (top + bottom) // 2
  1289. print(f'y={y}')
  1290. self.loggerMT.info('开始滑动4')
  1291. self.d.swipe(500, y, 100, y, 0.5)
  1292. time.sleep(self.get_sleep_time())
  1293. break
  1294. '''
  1295. position = get_position() #快递送
  1296. max_retry = 5 # 最多尝试次数
  1297. for idx in range(1, max_retry + 1):
  1298. # xpath= '//*[@resource-id="com.sankuai.meituan:id/container"]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[3]/android.widget.FrameLayout[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.widget.ScrollView[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.support.v7.widget.RecyclerView[1]/android.widget.FrameLayout[2]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.widget.HorizontalScrollView[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[last()-1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]'
  1299. xpath= '//*[@resource-id="com.sankuai.meituan:id/container"]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[3]/android.widget.FrameLayout[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.widget.ScrollView[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.support.v7.widget.RecyclerView[1]/android.widget.FrameLayout[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.widget.HorizontalScrollView[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]'
  1300. xpath2= '//*[@resource-id="com.sankuai.meituan:id/container"]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[3]/android.widget.FrameLayout[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.widget.ScrollView[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.support.v7.widget.RecyclerView[1]/android.widget.FrameLayout[2]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.widget.HorizontalScrollView[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]'
  1301. xpath3= '//*[@resource-id="com.sankuai.meituan:id/container"]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[2]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[3]/android.widget.FrameLayout[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.support.v7.widget.RecyclerView[1]/android.widget.FrameLayout[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.widget.HorizontalScrollView[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]'
  1302. xpath4 = '//*[@resource-id="com.sankuai.meituan:id/container"]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[2]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[3]/android.widget.FrameLayout[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.support.v7.widget.RecyclerView[1]/android.widget.FrameLayout[2]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.widget.HorizontalScrollView[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]'
  1303. # print(f"xpath:{xpath}")
  1304. # scroll_view = self.d(resourceId="com.sankuai.meituan:id/container") .child(className="android.widget.HorizontalScrollView")
  1305. if self.d.xpath(xpath).exists:
  1306. self.d.xpath(xpath).click()
  1307. # time.sleep(self.get_sleep_time())
  1308. print(f"第{idx}次点击xpath快递送成功")
  1309. time.sleep(self.get_sleep_time())
  1310. break
  1311. elif self.d.xpath(xpath2).exists:
  1312. self.d.xpath(xpath2).click()
  1313. # time.sleep(self.get_sleep_time())
  1314. print(f"第{idx}次点击xpath2快递送成功")
  1315. time.sleep(self.get_sleep_time())
  1316. break
  1317. elif self.d.xpath(xpath3).exists:
  1318. self.d.xpath(xpath3).click()
  1319. # time.sleep(self.get_sleep_time())
  1320. print(f"第{idx}次点击xpath3快递送成功")
  1321. time.sleep(self.get_sleep_time())
  1322. break
  1323. elif self.d.xpath(xpath4).exists:
  1324. self.d.xpath(xpath4).click()
  1325. # time.sleep(self.get_sleep_time())
  1326. print(f"第{idx}次点击xpath4快递送成功")
  1327. time.sleep(self.get_sleep_time())
  1328. break
  1329. else:
  1330. print(f"第{idx}次点击xpath或xpath2或xpath3快递送都失败")
  1331. time.sleep(self.get_sleep_time())
  1332. # xpath2= '//*[@resource-id="com.sankuai.meituan:id/container"]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[3]/android.widget.FrameLayout[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.widget.ScrollView[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.support.v7.widget.RecyclerView[1]/android.widget.FrameLayout[2]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.widget.HorizontalScrollView[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[last()]'
  1333. # if self.d.xpath(xpath2).exists:
  1334. # self.d.xpath(xpath2).click()
  1335. # print(f"第{idx}次点击xpath2快递送成功")
  1336. # time.sleep(self.get_sleep_time())
  1337. # break
  1338. """暂不用该功能
  1339. def get_table_license_info(self, qualification_number):
  1340. try:
  1341. sql = f'select business_license_company,city,credit_code from mt_drug where credit_code = "{qualification_number}"'
  1342. self.mysql_client.cur.execute(sql)
  1343. res = self.mysql_client.cur.fetchone()
  1344. return res
  1345. except:
  1346. return None
  1347. """
  1348. # def get_clipboard(self):
  1349. # """通过ADB获取Android手机剪贴板内容"""
  1350. # try:
  1351. # result = subprocess.run(
  1352. # ["adb", "shell", "am", "broadcast", "-a", "clipper.get"],
  1353. # capture_output=True,
  1354. # text=True,
  1355. # timeout=5
  1356. # )
  1357. # print(f"获取剪贴板结果: {result.stdout}")
  1358. # # 解析返回信息中的剪贴板内容
  1359. # for line in result.stdout.splitlines():
  1360. # if "data=" in line:
  1361. # return line.split("data=")[1].strip()
  1362. # return ""
  1363. # except Exception as e:
  1364. # print("获取剪贴板失败:", e)
  1365. # return ""
  1366. # def get_clipboard(self):
  1367. # """读取 Android 剪贴板(系统自带命令)"""
  1368. # try:
  1369. # text = subprocess.check_output(
  1370. # ["adb", "shell", "cmd", "clipboard", "get"],
  1371. # text=True, timeout=5, stderr=subprocess.STDOUT
  1372. # ).strip()
  1373. # print(f"获取剪贴板结果: {text}")
  1374. # return text if text else ""
  1375. # except Exception as e:
  1376. # print("获取剪贴板失败:", e)
  1377. # return ""
  1378. def get_clipboard(self):
  1379. time.sleep(1)
  1380. self.loggerMT.info(f"Clipboard content:{self.d.clipboard}") # 打印调试信息
  1381. clipboard_content = self.d.clipboard
  1382. if clipboard_content is None:
  1383. return ''
  1384. return clipboard_content.strip()
  1385. # return self.d.clipboard.strip()
  1386. def clear_clipboard(self):
  1387. self.d.set_clipboard("", "text/plain")
  1388. # def clear_clipboard(self):
  1389. # """清空手机剪贴板:写入空字符串(subprocess 版)"""
  1390. # try:
  1391. # subprocess.run(
  1392. # ["adb", "shell", "am", "broadcast", "-a", "clipper.set", "-e", "text", " "],
  1393. # check=True,
  1394. # capture_output=True,
  1395. # text=True,
  1396. # timeout=5
  1397. # )
  1398. # except subprocess.CalledProcessError as e:
  1399. # print("ADB 清空失败:", e.stderr)
  1400. # def clear_clipboard():
  1401. # """清空手机剪贴板:写入空字符串"""
  1402. # try:
  1403. # adb_shell(["shell", "am", "broadcast", "-a", "clipper.set", "-e", "text", ""])
  1404. # except subprocess.CalledProcessError as e:
  1405. # print("ADB 清空失败:", e.output)
  1406. #获取一个商品的数据、商品对应的店铺的数据
  1407. def get_product_link(self):
  1408. product_link = ''
  1409. # 两种可能的“···”按钮
  1410. dots_xpaths = [
  1411. '//*[@resource-id="com.sankuai.meituan:id/container"]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[3]/android.widget.FrameLayout[1]/android.view.ViewGroup[3]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.widget.ImageView[1]',
  1412. '//*[@resource-id="com.sankuai.meituan:id/container"]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[3]/android.widget.FrameLayout[1]/android.view.ViewGroup[3]/android.view.ViewGroup[2]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.widget.ImageView[1]',
  1413. '//*[@resource-id="com.sankuai.meituan:id/container"]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[3]/android.widget.FrameLayout[1]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.widget.ImageView[1]'
  1414. ]
  1415. max_retry = 5 # 最多尝试次数
  1416. for idx in range(1, max_retry + 1):
  1417. if product_link: # 已经拿到则退出
  1418. break
  1419. for xp in dots_xpaths:
  1420. if self.d.xpath(xp).exists:
  1421. print(f'{idx}-进入分享点点点')
  1422. self.loggerMT.info(f'{idx}-进入分享点点点')
  1423. # #先清空剪贴板的内容
  1424. # self.clear_clipboard()
  1425. # print("清空剪贴板内容成功。")
  1426. self.d.xpath(xp).click()
  1427. time.sleep(0.2)
  1428. self.d.xpath('//*[@text="分享商品"]').click_exists()
  1429. time.sleep(0.2)
  1430. link_xpath = '//*[@text="复制链接"]'
  1431. if self.d.xpath(link_xpath).exists:
  1432. self.d.xpath(link_xpath).click()
  1433. time.sleep(1)
  1434. product_link = self.get_clipboard()
  1435. time.sleep(0.5)
  1436. print(f'{idx}-商品链接:{product_link}')
  1437. self.loggerMT.info(f'{idx}-商品链接:{product_link}')
  1438. break # 找到并执行后跳出内层循环
  1439. else:
  1440. print(f'{idx}-商品链接:{product_link}')
  1441. self.loggerMT.info(f'{idx}-商品链接:{product_link}')
  1442. product_link = ''
  1443. # self.d.xpath('//*[@text="复制链接"]').click_exists()
  1444. # time.sleep(1)
  1445. # product_link = self.get_clipboard()
  1446. # time.sleep(0.5)
  1447. # print(f'{idx}-商品链接:{product_link}')
  1448. # self.loggerMT.info(f'{idx}-商品链接:{product_link}')
  1449. # break # 找到并执行后跳出内层循环
  1450. if not product_link and idx < max_retry:
  1451. time.sleep(0.5) # 最后一次不需要再等待
  1452. return product_link
  1453. def integrate_data(self):
  1454. #测试说明书详情:
  1455. # instructions_info = self.safe_exec(self.get_instructions_data)
  1456. # time.sleep(1000000)
  1457. #测试店铺信息
  1458. # license_info = self.safe_exec(self.get_license_info_ex)
  1459. # time.sleep(1000000)
  1460. #测试定位地址
  1461. #获取链接开始
  1462. #self.d.xpath('//*[@resource-id="com.sankuai.meituan:id/com.sankuai.meituan:id/container"]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[3]/android.widget.FrameLayout[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.widget.ScrollView[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[3]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.widget.FrameLayout[1]/android.widget.TextView').text
  1463. #1、点击页面的... 先判断元素是否存在
  1464. '''
  1465. if self.d.xpath('//*[@resource-id="com.sankuai.meituan:id/container"]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[3]/android.widget.FrameLayout[1]/android.view.ViewGroup[3]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.widget.ImageView[1]').exists:
  1466. print('1-进入分享点点点111')
  1467. self.loggerMT.info('1-进入分享点点点111')
  1468. self.d.xpath('//*[@resource-id="com.sankuai.meituan:id/container"]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[3]/android.widget.FrameLayout[1]/android.view.ViewGroup[3]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.widget.ImageView[1]').click()
  1469. #点击分享商品
  1470. # if self.d.xpath('//*[@resource-id="com.sankuai.meituan:id/container"]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[3]/android.widget.FrameLayout[1]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[2]/android.view.ViewGroup[3]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.widget.ImageView[1]').exists:
  1471. time.sleep(0.2)
  1472. self.d.xpath('//*[@text="分享商品"]').click_exists()
  1473. time.sleep(0.2)
  1474. self.d.xpath('//*[@text="复制链接"]').click_exists()
  1475. time.sleep(1)
  1476. #获取剪切板的数据
  1477. product_link = self.get_clipboard()
  1478. time.sleep(0.5)
  1479. print(f'1-商品链接:{product_link}')
  1480. self.loggerMT.info(f'1-商品链接:{product_link}')
  1481. #清空剪切板
  1482. # self.clear_clipboard()
  1483. # if self.d.xpath('//*[@text="加载更多"]').click_exists():
  1484. # self.d.xpath('//*[@resource-id="com.sankuai.meituan:id/container"]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[3]/android.widget.FrameLayout[1]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[2]/android.view.ViewGroup[3]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.widget.ImageView[1]').click()
  1485. # if self.d.xpath('//android.support.v7.widget.RecyclerView/android.view.ViewGroup[3]/android.widget.ImageView[1]').exists:
  1486. # self.d.xpath('//android.support.v7.widget.RecyclerView/android.view.ViewGroup[3]/android.widget.ImageView[1]').click()
  1487. # #获取剪切板的数据
  1488. # product_link = self.get_clipboard()
  1489. # time.sleep(0.5)
  1490. # print(f'商品链接:{product_link}')
  1491. # #清空剪切板
  1492. # self.clear_clipboard()
  1493. # else:
  1494. # print('未找到分享按钮111')
  1495. elif self.d.xpath('//*[@resource-id="com.sankuai.meituan:id/container"]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[3]/android.widget.FrameLayout[1]/android.view.ViewGroup[3]/android.view.ViewGroup[2]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.widget.ImageView[1]').exists:
  1496. print('1-进入分享点点点222')
  1497. self.loggerMT.info('1-进入分享点点点222')
  1498. self.d.xpath('//*[@resource-id="com.sankuai.meituan:id/container"]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[3]/android.widget.FrameLayout[1]/android.view.ViewGroup[3]/android.view.ViewGroup[2]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.widget.ImageView[1]').click()
  1499. time.sleep(0.2)
  1500. self.d.xpath('//*[@text="分享商品"]').click_exists()
  1501. time.sleep(0.2)
  1502. self.d.xpath('//*[@text="复制链接"]').click_exists()
  1503. time.sleep(1)
  1504. #获取剪切板的数据
  1505. product_link = self.get_clipboard()
  1506. time.sleep(0.5)
  1507. print(f'1-商品链接:{product_link}')
  1508. self.loggerMT.info(f'1-商品链接:{product_link}')
  1509. #如果为获取到product_link 则等待0.5秒再获取
  1510. if not product_link:
  1511. time.sleep(0.5)
  1512. if self.d.xpath('//*[@resource-id="com.sankuai.meituan:id/container"]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[3]/android.widget.FrameLayout[1]/android.view.ViewGroup[3]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.widget.ImageView[1]').exists:
  1513. print('2-进入分享点点点111')
  1514. self.loggerMT.info('2-进入分享点点点111')
  1515. self.d.xpath('//*[@resource-id="com.sankuai.meituan:id/container"]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[3]/android.widget.FrameLayout[1]/android.view.ViewGroup[3]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.widget.ImageView[1]').click()
  1516. #点击分享商品
  1517. # if self.d.xpath('//*[@resource-id="com.sankuai.meituan:id/container"]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[3]/android.widget.FrameLayout[1]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[2]/android.view.ViewGroup[3]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.widget.ImageView[1]').exists:
  1518. time.sleep(0.2)
  1519. self.d.xpath('//*[@text="分享商品"]').click_exists()
  1520. time.sleep(0.2)
  1521. self.d.xpath('//*[@text="复制链接"]').click_exists()
  1522. time.sleep(1)
  1523. #获取剪切板的数据
  1524. product_link = self.get_clipboard()
  1525. time.sleep(0.5)
  1526. print(f'2-商品链接:{product_link}')
  1527. self.loggerMT.info(f'2-商品链接:{product_link}')
  1528. elif self.d.xpath('//*[@resource-id="com.sankuai.meituan:id/container"]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[3]/android.widget.FrameLayout[1]/android.view.ViewGroup[3]/android.view.ViewGroup[2]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.widget.ImageView[1]').exists:
  1529. print('2-进入分享点点点222')
  1530. self.loggerMT.info('2-进入分享点点点222')
  1531. self.d.xpath('//*[@resource-id="com.sankuai.meituan:id/container"]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[3]/android.widget.FrameLayout[1]/android.view.ViewGroup[3]/android.view.ViewGroup[2]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.widget.ImageView[1]').click()
  1532. time.sleep(0.2)
  1533. self.d.xpath('//*[@text="分享商品"]').click_exists()
  1534. time.sleep(0.2)
  1535. self.d.xpath('//*[@text="复制链接"]').click_exists()
  1536. time.sleep(1)
  1537. #获取剪切板的数据
  1538. product_link = self.get_clipboard()
  1539. time.sleep(0.5)
  1540. print(f'2-商品链接:{product_link}')
  1541. self.loggerMT.info(f'2-商品链接:{product_link}')
  1542. #如果为获取到product_link 则等待0.5秒再获取
  1543. if not product_link:
  1544. time.sleep(0.5)
  1545. if self.d.xpath('//*[@resource-id="com.sankuai.meituan:id/container"]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[3]/android.widget.FrameLayout[1]/android.view.ViewGroup[3]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.widget.ImageView[1]').exists:
  1546. print('3-进入分享点点点111')
  1547. self.loggerMT.info('3-进入分享点点点111')
  1548. self.d.xpath('//*[@resource-id="com.sankuai.meituan:id/container"]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[3]/android.widget.FrameLayout[1]/android.view.ViewGroup[3]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.widget.ImageView[1]').click()
  1549. #点击分享商品
  1550. # if self.d.xpath('//*[@resource-id="com.sankuai.meituan:id/container"]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[3]/android.widget.FrameLayout[1]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[2]/android.view.ViewGroup[3]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.widget.ImageView[1]').exists:
  1551. time.sleep(0.2)
  1552. self.d.xpath('//*[@text="分享商品"]').click_exists()
  1553. time.sleep(0.2)
  1554. self.d.xpath('//*[@text="复制链接"]').click_exists()
  1555. time.sleep(1)
  1556. #获取剪切板的数据
  1557. product_link = self.get_clipboard()
  1558. time.sleep(0.5)
  1559. print(f'3-商品链接:{product_link}')
  1560. self.loggerMT.info(f'3-商品链接:{product_link}')
  1561. elif self.d.xpath('//*[@resource-id="com.sankuai.meituan:id/container"]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[3]/android.widget.FrameLayout[1]/android.view.ViewGroup[3]/android.view.ViewGroup[2]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.widget.ImageView[1]').exists:
  1562. print('3-进入分享点点点222')
  1563. self.loggerMT.info('3-进入分享点点点222')
  1564. self.d.xpath('//*[@resource-id="com.sankuai.meituan:id/container"]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[3]/android.widget.FrameLayout[1]/android.view.ViewGroup[3]/android.view.ViewGroup[2]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.widget.ImageView[1]').click()
  1565. time.sleep(0.2)
  1566. self.d.xpath('//*[@text="分享商品"]').click_exists()
  1567. time.sleep(0.2)
  1568. self.d.xpath('//*[@text="复制链接"]').click_exists()
  1569. time.sleep(1)
  1570. #获取剪切板的数据
  1571. product_link = self.get_clipboard()
  1572. time.sleep(0.5)
  1573. print(f'3-商品链接:{product_link}')
  1574. self.loggerMT.info(f'3-商品链接:{product_link}')
  1575. '''
  1576. #获取链接结束
  1577. """
  1578. 整合数据
  1579. :return:
  1580. """
  1581. # title_info = self.get_title() # 药品,规格
  1582. # title_info = self.safe_exec(self.get_title) # 药品,规格
  1583. product, specifications = self.safe_exec(self.get_title) # 药品,规格
  1584. if product:
  1585. # product, specifications = title_info
  1586. if '仁和' in self.search_key:
  1587. if self.search_key == '仁和可立克复方氨酚烷胺胶囊12粒':
  1588. temp_search_key = self.search_key.replace("仁和可立克", "")
  1589. temp_search_key = temp_search_key.replace("12粒", "")
  1590. elif self.search_key == '仁和咽炎片(薄膜衣片)':
  1591. temp_search_key = self.search_key.replace("仁和", "")
  1592. temp_search_key = temp_search_key.replace("(薄膜衣片)", "")
  1593. elif self.search_key == '仁和中方消炎镇痛膏':
  1594. temp_search_key = self.search_key.replace("仁和中方", "")
  1595. elif self.search_key == '仁和藿香正气合剂10ml*6':
  1596. temp_search_key = self.search_key.replace("仁和", "")
  1597. temp_search_key = temp_search_key.replace("10ml*6", "")
  1598. elif self.search_key == '仁和可立克磷酸奥司他韦胶囊':
  1599. temp_search_key = self.search_key.replace("仁和可立克", "")
  1600. elif self.search_key == '仁和可立克感冒软胶囊':
  1601. temp_search_key = self.search_key.replace("仁和可立克", "")
  1602. else:
  1603. temp_search_key = self.search_key.replace("仁和", "")
  1604. if '仁和' not in product or temp_search_key not in product:
  1605. self.swipe_back(1)
  1606. self.unrelated_data += 1
  1607. return
  1608. else:
  1609. if self.search_key == '伊康美宝甲硝唑氯己定洗剂':
  1610. temp_search_key = self.search_key.replace("伊康美宝", "")
  1611. if '伊康美宝' not in product or temp_search_key not in product:
  1612. self.swipe_back(1)
  1613. self.unrelated_data += 1
  1614. return
  1615. elif self.search_key == '闪亮萘敏维滴眼液':
  1616. temp_search_key = self.search_key.replace("闪亮", "")
  1617. if '闪亮' not in product or temp_search_key not in product:
  1618. self.swipe_back(1)
  1619. self.unrelated_data += 1
  1620. return
  1621. elif self.search_key == '闪亮复方门冬维甘滴眼液':
  1622. temp_search_key = self.search_key.replace("闪亮", "")
  1623. if '闪亮' not in product or temp_search_key not in product:
  1624. self.swipe_back(1)
  1625. self.unrelated_data += 1
  1626. return
  1627. elif self.search_key == '米阿卡小儿止咳糖浆':
  1628. temp_search_key = self.search_key.replace("米阿卡", "")
  1629. if '米阿卡' not in product or temp_search_key not in product:
  1630. self.swipe_back(1)
  1631. self.unrelated_data += 1
  1632. return
  1633. elif self.search_key == '达舒克硝酸益康唑喷雾剂':
  1634. temp_search_key = self.search_key.replace("达舒克", "")
  1635. if '达舒克' not in product or temp_search_key not in product:
  1636. self.swipe_back(1)
  1637. self.unrelated_data += 1
  1638. return
  1639. elif self.search_key == '闪亮盐酸奥洛他定滴眼液':
  1640. temp_search_key = self.search_key.replace("闪亮", "")
  1641. if '闪亮' not in product or temp_search_key not in product:
  1642. self.swipe_back(1)
  1643. self.unrelated_data += 1
  1644. return
  1645. elif self.search_key == '闪亮左氧氟沙星滴眼液':
  1646. temp_search_key = self.search_key.replace("闪亮", "")
  1647. if '闪亮' not in product or temp_search_key not in product:
  1648. self.swipe_back(1)
  1649. self.unrelated_data += 1
  1650. return
  1651. elif self.search_key == '妇炎洁植物本草抑菌洗液380ml':
  1652. temp_search_key = self.search_key.replace("妇炎洁", "")
  1653. temp_search_key = temp_search_key.replace("380ml", "")
  1654. if '妇炎洁' not in product or temp_search_key not in product:
  1655. self.swipe_back(1)
  1656. self.unrelated_data += 1
  1657. return
  1658. elif '380ml' not in product:
  1659. self.swipe_back(1)
  1660. self.unrelated_data += 1
  1661. return
  1662. elif self.search_key == '妇炎洁洁阴康洗液':
  1663. temp_search_key = self.search_key.replace("妇炎洁", "")
  1664. if '妇炎洁' not in product or temp_search_key not in product:
  1665. self.swipe_back(1)
  1666. self.unrelated_data += 1
  1667. return
  1668. elif self.search_key == '妇炎洁医用护理垫245*70':
  1669. temp_search_key = self.search_key.replace("妇炎洁", "")
  1670. temp_search_key = temp_search_key.replace("245*70", "")
  1671. if '妇炎洁' not in product or temp_search_key not in product:
  1672. self.swipe_back(1)
  1673. self.unrelated_data += 1
  1674. return
  1675. elif '245*70' not in product:
  1676. self.swipe_back(1)
  1677. self.unrelated_data += 1
  1678. return
  1679. elif self.search_key == '妇炎洁克霉唑阴道片':
  1680. temp_search_key = self.search_key.replace("妇炎洁", "")
  1681. if '妇炎洁' not in product or temp_search_key not in product:
  1682. self.swipe_back(1)
  1683. self.unrelated_data += 1
  1684. return
  1685. elif self.search_key == '优卡丹葡萄糖酸钙锌口服溶液':
  1686. temp_search_key = self.search_key.replace("优卡丹", "")
  1687. if '优卡丹' not in product or temp_search_key not in product:
  1688. self.swipe_back(1)
  1689. self.unrelated_data += 1
  1690. return
  1691. elif self.search_key == '优卡丹小儿氨酚烷胺颗粒':
  1692. temp_search_key = self.search_key.replace("优卡丹", "")
  1693. if '优卡丹' not in product or temp_search_key not in product:
  1694. self.swipe_back(1)
  1695. self.unrelated_data += 1
  1696. return
  1697. elif self.search_key == '克快好强力枇杷露':
  1698. temp_search_key = self.search_key.replace("克快好", "")
  1699. if '克快好' not in product or temp_search_key not in product:
  1700. self.swipe_back(1)
  1701. self.unrelated_data += 1
  1702. return
  1703. elif self.search_key == '君扬他达拉非片':
  1704. temp_search_key = self.search_key.replace("君扬", "")
  1705. if '君扬' not in product or temp_search_key not in product:
  1706. self.swipe_back(1)
  1707. self.unrelated_data += 1
  1708. return
  1709. elif self.search_key == '米阿卡头孢克肟颗粒':
  1710. temp_search_key = self.search_key.replace("米阿卡", "")
  1711. if '米阿卡' not in product or temp_search_key not in product:
  1712. self.swipe_back(1)
  1713. self.unrelated_data += 1
  1714. return
  1715. elif self.search_key == '克快好治咳枇杷合剂':
  1716. temp_search_key = self.search_key.replace("克快好", "")
  1717. if '克快好' not in product or temp_search_key not in product:
  1718. self.swipe_back(1)
  1719. self.unrelated_data += 1
  1720. return
  1721. elif self.search_key == '优卡丹三合钙咀嚼片':
  1722. temp_search_key = self.search_key.replace("优卡丹", "")
  1723. if '优卡丹' not in product or temp_search_key not in product:
  1724. self.swipe_back(1)
  1725. self.unrelated_data += 1
  1726. return
  1727. elif self.search_key == '必艾得吲哚美辛巴布膏':
  1728. temp_search_key = self.search_key.replace("必艾得", "")
  1729. if '必艾得' not in product or temp_search_key not in product:
  1730. self.swipe_back(1)
  1731. self.unrelated_data += 1
  1732. return
  1733. elif self.search_key == '宁新宝葡萄糖酸钙片':
  1734. temp_search_key = self.search_key.replace("宁新宝", "")
  1735. if '宁新宝' not in product or temp_search_key not in product:
  1736. self.swipe_back(1)
  1737. self.unrelated_data += 1
  1738. return
  1739. elif self.search_key == '闪亮玻璃酸钠滴眼液':
  1740. temp_search_key = self.search_key.replace("闪亮", "")
  1741. if '闪亮' not in product or temp_search_key not in product:
  1742. self.swipe_back(1)
  1743. self.unrelated_data += 1
  1744. return
  1745. elif self.search_key == '闪亮地夸磷索钠滴眼液':
  1746. temp_search_key = self.search_key.replace("闪亮", "")
  1747. if '闪亮' not in product or temp_search_key not in product:
  1748. self.swipe_back(1)
  1749. self.unrelated_data += 1
  1750. return
  1751. elif self.search_key == '闪亮复方尿维氨滴眼液':
  1752. temp_search_key = self.search_key.replace("闪亮", "")
  1753. if '闪亮' not in product or temp_search_key not in product:
  1754. self.swipe_back(1)
  1755. self.unrelated_data += 1
  1756. return
  1757. elif self.search_key == '闪亮盐酸莫西沙星滴眼液':
  1758. temp_search_key = self.search_key.replace("闪亮", "")
  1759. if '闪亮' not in product or temp_search_key not in product:
  1760. self.swipe_back(1)
  1761. self.unrelated_data += 1
  1762. return
  1763. else:
  1764. if self.search_key not in product.replace(' ', ''):
  1765. self.swipe_back(1)
  1766. self.unrelated_data += 1
  1767. return
  1768. else:
  1769. self.swipe_back(1)
  1770. return
  1771. min_price = self.drug_price() # 最低价格
  1772. # 商品链接
  1773. # product_link = self.get_product_link()
  1774. product_link = ''
  1775. #判断是否有自营的文本,有的话不需要获取店铺的信息
  1776. if self.d.xpath('//*[@text="自营"]').exists:
  1777. shop = "美团自营大药房(快递电商)"
  1778. # 爬取日期
  1779. scrape_date = self.get_current_date()
  1780. # scrape_date = "2025-07-18"
  1781. dup_data = {'product': product, 'min_price': min_price, 'shop': shop, 'scrape_date': scrape_date,
  1782. 'platform': '美团'}
  1783. print(f'当前数据:{dup_data}')
  1784. if self.data_is_exists(dup_data):
  1785. print('存在相同数据不入库')
  1786. self.swipe_back(1)
  1787. return
  1788. else:
  1789. for i in range(8):
  1790. if self.d.xpath('//*[@text="进店"]').exists:
  1791. print('开始获取店铺名1')
  1792. break
  1793. self.d.swipe_ext('up', 0.3)
  1794. time.sleep(1)
  1795. # detail_info = self.d.xpath(
  1796. # '//android.widget.ScrollView/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[6]').info
  1797. # bounds = detail_info['bounds']
  1798. # height = bounds['bottom'] - bounds['top']
  1799. # if self.d.xpath('//*[@text="进店"]').exists and height > 100:
  1800. if self.d.xpath('//*[@text="进店"]').exists:
  1801. print('开始获取店铺名2')
  1802. break
  1803. shop = self.get_shop_name()
  1804. # 爬取日期
  1805. scrape_date = self.get_current_date()
  1806. # scrape_date = "2025-07-18"
  1807. dup_data = {'product': product, 'min_price': min_price, 'shop': shop, 'scrape_date': scrape_date,
  1808. 'platform': '美团'}
  1809. print(f'当前数据:{dup_data}')
  1810. #获取店铺信息开始
  1811. #暂时不获取店铺信息 start
  1812. '''
  1813. is_has_enter_shop = self.has_shop()
  1814. #需要判断shop是否已经在数据库中存在,如果存在,则不再进入店铺,直接进入下一个商品
  1815. shop_is_exists = self.shop_is_exists_database(shop)
  1816. #存在进店 并且店铺的名称不包含美团官方的字样
  1817. print(f"已采集{self.shop_data_num}家店铺数据")
  1818. if is_has_enter_shop and '美团官方' not in shop and '美团自营' not in shop and not shop_is_exists and self.shop_data_num < 500:
  1819. # license_info = self.get_license_info_ex()
  1820. license_info = self.safe_exec(self.get_license_info_ex)
  1821. contact_address = license_info['contact_address']
  1822. qualification_number = license_info['qualification_number']
  1823. business_license_company = license_info['business_license_company']
  1824. business_license_address = license_info['business_license_address']
  1825. save_shop_data = {
  1826. 'shop': shop,
  1827. 'contact_address': contact_address,
  1828. 'qualification_number': qualification_number,
  1829. 'scrape_date': scrape_date,
  1830. 'business_license_company':business_license_company,
  1831. 'business_license_address':business_license_address,
  1832. 'platform': '美团'
  1833. }
  1834. self.save_shop_info_to_database(save_shop_data)
  1835. self.shop_data_num += 1 # 店铺数据数量+1
  1836. self.swipe_back(2)
  1837. else:
  1838. print('不采集店铺信息')
  1839. #获取店铺信息结束
  1840. '''
  1841. #暂时不获取店铺信息 end
  1842. if self.data_is_exists(dup_data):
  1843. print('存在相同数据不入库')
  1844. self.swipe_back(1)
  1845. return
  1846. if not shop:
  1847. print('未获取到店铺名:开始回退')
  1848. self.swipe_back(1)
  1849. return
  1850. if not shop or '自营' in shop:
  1851. self.swipe_back(1)
  1852. return
  1853. time.sleep(self.get_sleep_time())
  1854. # 生产日期为空
  1855. manufacture_date = ''
  1856. # 执政信息
  1857. # if is_has_enter_shop:
  1858. # license_info = self.get_license_info()
  1859. # business_license_company = license_info["单位名称"]
  1860. # credit_code = license_info['社会信用代码']
  1861. # city_str = license_info['地址']
  1862. # # 先把省份啥的替换掉
  1863. # city_sub_str = re.sub(r'[u4e00-\u9fa5]+省', '', city_str)
  1864. # try:
  1865. # city = re.search(r'[\u4e00-\u9fa5]+?(市|区|县)', city_sub_str).group(0)
  1866. # except:
  1867. # city = city_sub_str
  1868. # try:
  1869. # province = self.city2province[city]
  1870. # except:
  1871. # province = ''
  1872. # self.swipe_back(2)
  1873. # else:
  1874. # business_license_company = ''
  1875. # credit_code = ''
  1876. # city = ''
  1877. # province = ''
  1878. business_license_company = ''
  1879. credit_code = ''
  1880. city = ''
  1881. province = ''
  1882. expiry_date = ''
  1883. manufacturer = ''
  1884. approval_number = ''
  1885. #暂时不获取说明书信息 start
  1886. medicine_info = {
  1887. '仁和盐酸氨溴索口服溶液': {
  1888. 'expiry_date': '24个月',
  1889. 'manufacturer': '山东益康药业股份有限公司',
  1890. 'approval_number': '国药准字H20065840'
  1891. },
  1892. '仁和蒲公英颗粒': {
  1893. 'expiry_date': '24个月',
  1894. 'manufacturer': '江西心诚药业有限公司',
  1895. 'approval_number': '国药准字Z200055430'
  1896. },
  1897. '仁和红霉素软膏': {
  1898. 'expiry_date': '24个月',
  1899. 'manufacturer': '江西德成制药有限公司',
  1900. 'approval_number': '国药准字H36020018'
  1901. },
  1902. '仁和可立克复方氨酚烷胺胶囊12粒': {
  1903. 'expiry_date': '30个月',
  1904. 'manufacturer': '江西铜鼓仁和制药有限公司',
  1905. 'approval_number': '国药准字H20068169'
  1906. },
  1907. '仁和盐酸羟甲唑啉喷雾剂': {
  1908. 'expiry_date': '24个月',
  1909. 'manufacturer': '南京海鲸药业有限公司',
  1910. 'approval_number': '国药准字H20057401'
  1911. },
  1912. '仁和咽炎片(薄膜衣片)': {
  1913. 'expiry_date': '24个月',
  1914. 'manufacturer': '石家庄东方药业股份有限公司',
  1915. 'approval_number': '国药准字Z20093479'
  1916. },
  1917. '仁和曲安奈德益康唑乳膏': {
  1918. 'expiry_date': '36个月',
  1919. 'manufacturer': '福建太平洋制药有限公司',
  1920. 'approval_number': '国药准字H20064180'
  1921. },
  1922. '仁和头孢克洛干混悬剂': {
  1923. 'expiry_date': '24个月',
  1924. 'manufacturer': '山东益康药业股份有限公司',
  1925. 'approval_number': '国药准字H20084417'
  1926. },
  1927. '伊康美宝甲硝唑氯己定洗剂': {
  1928. 'expiry_date': '24个月',
  1929. 'manufacturer': '江西药都仁和制药有限公司',
  1930. 'approval_number': '国药准字H20043498'
  1931. },
  1932. '仁和布洛芬缓释胶囊': {
  1933. 'expiry_date': '36个月',
  1934. 'manufacturer': '福建太平洋制药有限公司',
  1935. 'approval_number': '国药准字H20093691'
  1936. },
  1937. '闪亮萘敏维滴眼液': {
  1938. 'expiry_date': '24个月',
  1939. 'manufacturer': '江西闪亮制药有限公司',
  1940. 'approval_number': '国药准字H20064223'
  1941. },
  1942. '闪亮复方门冬维甘滴眼液': {
  1943. 'expiry_date': '24个月',
  1944. 'manufacturer': '江西闪亮制药有限公司',
  1945. 'approval_number': '国药准字H20083254‌'
  1946. },
  1947. '米阿卡小儿止咳糖浆': {
  1948. 'expiry_date': '24个月',
  1949. 'manufacturer': '江西远东药业股份有限公司',
  1950. 'approval_number': '国药准字Z36020251'
  1951. },
  1952. '仁和人工牛黄甲硝唑胶囊': {
  1953. 'expiry_date': '24个月',
  1954. 'manufacturer': '江西药都仁和制药有限公司',
  1955. 'approval_number': '国药准字H36022263'
  1956. },
  1957. '仁和盐酸左氧氟沙星胶囊': {
  1958. 'expiry_date': '24个月',
  1959. 'manufacturer': '海南海神同洲制药有限公司',
  1960. 'approval_number': '国药准字H20103012'
  1961. },
  1962. '仁和苯磺酸氨氯地平片': {
  1963. 'expiry_date': '36个月',
  1964. 'manufacturer': '江西制药有限责任公司',
  1965. 'approval_number': '国药准字H20083949'
  1966. },
  1967. '仁和阿昔洛韦乳膏': {
  1968. 'expiry_date': '24个月',
  1969. 'manufacturer': '江西吉安三力制药有限公司',
  1970. 'approval_number': '国药准字H20063386'
  1971. },
  1972. '仁和阿莫西林胶囊': {
  1973. 'expiry_date': '36个月',
  1974. 'manufacturer': '安徽安科恒益药业有限公司‌',
  1975. 'approval_number': '国药准字H34023532‌'
  1976. },
  1977. '仁和小柴胡颗粒': {
  1978. 'expiry_date': '24个月',
  1979. 'manufacturer': '江西铜鼓仁和制药有限公司',
  1980. 'approval_number': '国药准字Z20054063'
  1981. },
  1982. '仁和中方消炎镇痛膏': {
  1983. 'expiry_date': '24个月',
  1984. 'manufacturer': '江西吉安三力制药有限公司',
  1985. 'approval_number': '国药准字Z36021368'
  1986. },
  1987. '仁和头孢克肟片': {
  1988. 'expiry_date': '24个月',
  1989. 'manufacturer': '湖南方盛制药股份有限公司',
  1990. 'approval_number': '国药准字H20093161'
  1991. },
  1992. '仁和头孢克洛分散片': {
  1993. 'expiry_date': '24个月',
  1994. 'manufacturer': '安徽安科恒益药业有限公司',
  1995. 'approval_number': '国药准字H20041126'
  1996. },
  1997. '仁和诺氟沙星胶囊': {
  1998. 'expiry_date': '12月',
  1999. 'manufacturer': '江西药都仁和制药有限公司',
  2000. 'approval_number': '国药准字H36021062'
  2001. },
  2002. '仁和川贝清肺糖浆': {
  2003. 'expiry_date': '24个月',
  2004. 'manufacturer': '江西铜鼓仁和制药有限公司',
  2005. 'approval_number': '国药准字Z36021507'
  2006. },
  2007. '达舒克硝酸益康唑喷雾剂': {
  2008. 'expiry_date': '36个月',
  2009. 'manufacturer': '广东同德药业有限公司',
  2010. 'approval_number': '国药准字H44025251'
  2011. },
  2012. '仁和清火胶囊': {
  2013. 'expiry_date': '24个月',
  2014. 'manufacturer': '江西药都仁和制药有限公司',
  2015. 'approval_number': '国药准字Z20080476'
  2016. },
  2017. '仁和双氯芬酸钠缓释片': {
  2018. 'expiry_date': '36个月',
  2019. 'manufacturer': '湖南华纳大药厂股份有限公司',
  2020. 'approval_number': '国药准字H20067776'
  2021. },
  2022. '仁和氨咖黄敏胶囊': {
  2023. 'expiry_date': '24个月',
  2024. 'manufacturer': '安徽安科恒益药业有限公司',
  2025. 'approval_number': '国药准字H34023208'
  2026. },
  2027. '仁和四季感冒胶囊': {
  2028. 'expiry_date': '24个月',
  2029. 'manufacturer': '广东佳泰药业股份有限公司',
  2030. 'approval_number': '国药准字Z‌20168001'
  2031. },
  2032. '仁和肺宁颗粒': {
  2033. 'expiry_date': '24个月',
  2034. 'manufacturer': '吉林益民堂制药有限公司',
  2035. 'approval_number': '国药准字Z22023003'
  2036. },
  2037. '仁和银黄颗粒': {
  2038. 'expiry_date': '36个月',
  2039. 'manufacturer': '河南诺美药业有限公司',
  2040. 'approval_number': '国药准字Z20044588'
  2041. },
  2042. '仁和蒲地蓝消炎片': {
  2043. 'expiry_date': '24个月',
  2044. 'manufacturer': '湖南方盛制药股份有限公司',
  2045. 'approval_number': '国药准字Z20043422'
  2046. },
  2047. '仁和复方鲜竹沥液': {
  2048. 'expiry_date': '24个月',
  2049. 'manufacturer': '江西远东药业股份有限公司',
  2050. 'approval_number': '国药准字Z20153065'
  2051. },
  2052. '仁和益气养血口服液': {
  2053. 'expiry_date': '36个月',
  2054. 'manufacturer': '通化汇金堂药业股份有限公司',
  2055. 'approval_number': '国药准字Z20055044'
  2056. },
  2057. '仁和氧氟沙星滴耳液': {
  2058. 'expiry_date': '24个月',
  2059. 'manufacturer': '武汉诺安药业有限公司',
  2060. 'approval_number': '国药准字H20083321'
  2061. },
  2062. '仁和蒙脱石散': {
  2063. 'expiry_date': '24个月',
  2064. 'manufacturer': '湖南方盛制药股份有限公司',
  2065. 'approval_number': '国药准字H20094210'
  2066. },
  2067. '仁和奥美拉唑肠溶胶囊': {
  2068. 'expiry_date': '30个月',
  2069. 'manufacturer': '河北山姆士药业有限公司',
  2070. 'approval_number': '国药准字H20093291'
  2071. },
  2072. '仁和氯雷他定片': {
  2073. 'expiry_date': '30个月',
  2074. 'manufacturer': '海南海神同洲制药有限公司',
  2075. 'approval_number': '国药准字H20040797'
  2076. },
  2077. '闪亮盐酸奥洛他定滴眼液': {
  2078. 'expiry_date': '24个月',
  2079. 'manufacturer': '江苏广承药业有限公司',
  2080. 'approval_number': '国药准字H20183349'
  2081. },
  2082. '闪亮左氧氟沙星滴眼液': {
  2083. 'expiry_date': '24个月',
  2084. 'manufacturer': '中山万汉制药有限公司',
  2085. 'approval_number': '国药准字H20203122‌'
  2086. },
  2087. '妇炎洁植物本草抑菌洗液380ml': {
  2088. 'expiry_date': '24个月',
  2089. 'manufacturer': '江西康美医药保健品有限公司',
  2090. 'approval_number': '赣卫消证字(2010)第0003号‌'
  2091. },
  2092. '妇炎洁洁阴康洗液': {
  2093. 'expiry_date': '24个月',
  2094. 'manufacturer': '江西药都仁和制药有限公司',
  2095. 'approval_number': '国药准字Z20103066'
  2096. },
  2097. '妇炎洁医用护理垫245*70': {
  2098. 'expiry_date': '36个月',
  2099. 'manufacturer': '美丽岛(福建)生活用品有限公司',
  2100. 'approval_number': '闽泉械备20180016号'
  2101. },
  2102. '妇炎洁克霉唑阴道片': {
  2103. 'expiry_date': '36个月',
  2104. 'manufacturer': '湖南华纳大药厂股份有限公司',
  2105. 'approval_number': '国药准字H20043250'
  2106. },
  2107. '仁和益母草颗粒': {
  2108. 'expiry_date': '24个月',
  2109. 'manufacturer': '广西圣特药业有限公司',
  2110. 'approval_number': '国药准字Z45020484'
  2111. },
  2112. '仁和红霉素眼膏': {
  2113. 'expiry_date': '24个月',
  2114. 'manufacturer': '福建省三明天泰制药有限公司',
  2115. 'approval_number': '国药准字H20003077'
  2116. },
  2117. '仁和炉甘石洗剂': {
  2118. 'expiry_date': '24个月',
  2119. 'manufacturer': '江苏华神药业有限公司',
  2120. 'approval_number': '国药准字H20053895'
  2121. },
  2122. '优卡丹葡萄糖酸钙锌口服溶液': {
  2123. 'expiry_date': '24个月',
  2124. 'manufacturer': '石家庄科仁医药科技有限公司',
  2125. 'approval_number': '国药准字H20193310'
  2126. },
  2127. '优卡丹小儿氨酚烷胺颗粒': {
  2128. 'expiry_date': '2024-12-31',
  2129. 'manufacturer': '江西铜鼓仁和制药有限公司',
  2130. 'approval_number': '国药准字H20068170'
  2131. },
  2132. '仁和湿毒清片': {
  2133. 'expiry_date': '24个月',
  2134. 'manufacturer': '江西药都仁和制药有限公司',
  2135. 'approval_number': '国药准字Z20050472'
  2136. },
  2137. '仁和阿达帕林凝胶': {
  2138. 'expiry_date': '24个月',
  2139. 'manufacturer': '江苏福邦药业有限公司',
  2140. 'approval_number': '国药准字H20113373'
  2141. },
  2142. '仁和盐酸二甲双胍缓释片': {
  2143. 'expiry_date': '24个月',
  2144. 'manufacturer': '河北山姆士药业有限公司',
  2145. 'approval_number': '国药准字H20123024'
  2146. },
  2147. '仁和替米沙坦胶囊': {
  2148. 'expiry_date': '24个月',
  2149. 'manufacturer': '江西杏林白马药业股份有限公司',
  2150. 'approval_number': '国药准字H20070134'
  2151. },
  2152. '仁和格列齐特缓释片': {
  2153. 'expiry_date': '12个月',
  2154. 'manufacturer': '江西制药有限责任公司',
  2155. 'approval_number': '国药准字H20065489‌'
  2156. },
  2157. '仁和双氯芬酸钠气雾剂': {
  2158. 'expiry_date': '24个月',
  2159. 'manufacturer': '广东同德药业有限公司',
  2160. 'approval_number': '国药准字H20056346'
  2161. },
  2162. '仁和硝苯地平缓释片': {
  2163. 'expiry_date': '24个月',
  2164. 'manufacturer': '烟台鲁银药业有限公司',
  2165. 'approval_number': '国药准字H20073908'
  2166. },
  2167. '仁和痔速宁片': {
  2168. 'expiry_date': '24个月',
  2169. 'manufacturer': '江西药都仁和制药有限公司',
  2170. 'approval_number': '国药准字Z20073162'
  2171. },
  2172. '仁和氧氟沙星滴眼液': {
  2173. 'expiry_date': '24个月',
  2174. 'manufacturer': '江西闪亮制药有限公司',
  2175. 'approval_number': '国药准字H20067760'
  2176. },
  2177. '克快好强力枇杷露': {
  2178. 'expiry_date': '24个月',
  2179. 'manufacturer': '江西药都樟树制药有限公司',
  2180. 'approval_number': '国药准字Z36021750'
  2181. },
  2182. '仁和盐酸左西替利嗪胶囊': {
  2183. 'expiry_date': '18个月',
  2184. 'manufacturer': '湖南九典制药股份有限公司',
  2185. 'approval_number': '国药准字H20060183'
  2186. },
  2187. '仁和甲钴胺胶囊': {
  2188. 'expiry_date': '24个月',
  2189. 'manufacturer': '山东鲁抗医药集团赛特有限责任公司',
  2190. 'approval_number': '国药准字H20051424'
  2191. },
  2192. '仁和多潘立酮片': {
  2193. 'expiry_date': '36个月',
  2194. 'manufacturer': '山西宝泰药业有限责任公司',
  2195. 'approval_number': '国药准字H20010245'
  2196. },
  2197. '仁和兰索拉唑肠溶片': {
  2198. 'expiry_date': '24个月',
  2199. 'manufacturer': '湖南华纳大药厂股份有限公司',
  2200. 'approval_number': '国药准字H20084414'
  2201. },
  2202. '仁和复方银翘氨敏胶囊': {
  2203. 'expiry_date': '24个月',
  2204. 'manufacturer': '江西新赣江药业股份有限公司',
  2205. 'approval_number': '国药准字H36022108'
  2206. },
  2207. '君扬他达拉非片': {
  2208. 'expiry_date': '24个月',
  2209. 'manufacturer': '江西药都仁和制药有限公司',
  2210. 'approval_number': '国药准字H20233233‌'
  2211. },
  2212. '仁和盐酸达泊西汀片': {
  2213. 'expiry_date': '24个月',
  2214. 'manufacturer': '厦门力卓药业有限公司',
  2215. 'approval_number': '国药准字H20213156'
  2216. },
  2217. '仁和藿香正气合剂10ml*6': {
  2218. 'expiry_date': '24个月',
  2219. 'manufacturer': '广西邦琪药业集团有限公司',
  2220. 'approval_number': '国药准字Z45022009'
  2221. },
  2222. '仁和阿昔洛韦片': {
  2223. 'expiry_date': '24个月',
  2224. 'manufacturer': '康普药业股份有限公司',
  2225. 'approval_number': '国药准字H43020286'
  2226. },
  2227. '仁和糠酸莫米松乳膏': {
  2228. 'expiry_date': '24个月',
  2229. 'manufacturer': '武汉诺安药业有限公司',
  2230. 'approval_number': '国药准字H20173401'
  2231. },
  2232. '米阿卡头孢克肟颗粒': {
  2233. 'expiry_date': '24个月',
  2234. 'manufacturer': '康普药业股份有限公司',
  2235. 'approval_number': '国药准字H20068130‌'
  2236. },
  2237. '克快好治咳枇杷合剂': {
  2238. 'expiry_date': '24个月',
  2239. 'manufacturer': '江西省芙蓉堂药业股份有限公司',
  2240. 'approval_number': '国药准字Z20027452'
  2241. },
  2242. '仁和雪梨膏': {
  2243. 'expiry_date': '24个月',
  2244. 'manufacturer': '武汉太福制药有限公司',
  2245. 'approval_number': '国药准字Z42021449'
  2246. },
  2247. '仁和西青果颗粒': {
  2248. 'expiry_date': '18个月',
  2249. 'manufacturer': '广西壮族自治区药物研究所有限公司',
  2250. 'approval_number': '国药准字Z45022149'
  2251. },
  2252. '仁和氨酚烷胺那敏胶囊': {
  2253. 'expiry_date': '24个月',
  2254. 'manufacturer': '大同市利群药业有限责任公司',
  2255. 'approval_number': '国药准字H14022808'
  2256. },
  2257. '仁和美洛昔康片': {
  2258. 'expiry_date': '24个月',
  2259. 'manufacturer': '宁波大红鹰药业股份有限公司',
  2260. 'approval_number': '国药准字H20031131'
  2261. }
  2262. }
  2263. if self.search_key in medicine_info:
  2264. info = medicine_info[self.search_key]
  2265. expiry_date = info['expiry_date']
  2266. manufacturer = info['manufacturer']
  2267. approval_number = info['approval_number']
  2268. else:
  2269. # 如果药品不在字典中,使用默认值
  2270. expiry_date = ''
  2271. manufacturer = ''
  2272. approval_number = ''
  2273. #是否存在说明书
  2274. # is_has_instructions = self.has_instructions()
  2275. # '仁和盐酸氨溴索口服溶液',
  2276. # '仁和蒲公英颗粒',
  2277. # '仁和红霉素软膏',
  2278. # '仁和可立克复方氨酚烷胺胶囊12粒',
  2279. # '仁和盐酸羟甲唑啉喷雾剂',
  2280. # '仁和咽炎片',
  2281. # '仁和曲安奈德益康唑乳膏',
  2282. # '仁和头孢克洛干混悬剂',
  2283. # '伊康美宝甲硝唑氯己定洗剂',
  2284. # '仁和布洛芬缓释胶囊'
  2285. #有的药品没有说明书,直接默认
  2286. # if self.search_key == '仁和盐酸氨溴索口服溶液':
  2287. # expiry_date = '24个月'
  2288. # manufacturer = '山东益康药业股份有限公司'
  2289. # approval_number = '国药准字H20065840'
  2290. # elif self.search_key == '仁和蒲公英颗粒':
  2291. # expiry_date = '24个月'
  2292. # manufacturer = '江西心诚药业有限公司'
  2293. # approval_number = '国药准字Z200055430'
  2294. # elif self.search_key == '仁和红霉素软膏':
  2295. # expiry_date = '24个月'
  2296. # manufacturer = '江西德成制药有限公司'
  2297. # approval_number = '国药准字H36020018'
  2298. # elif self.search_key == '仁和可立克复方氨酚烷胺胶囊12粒':
  2299. # expiry_date = '30个月'
  2300. # manufacturer = '江西铜鼓仁和制药有限公司'
  2301. # approval_number = '国药准字H20068169'
  2302. # elif self.search_key == '仁和盐酸羟甲唑啉喷雾剂':
  2303. # expiry_date = '24个月'
  2304. # manufacturer = '南京海鲸药业有限公司'
  2305. # approval_number = '国药准字H20057401'
  2306. # elif self.search_key == '仁和咽炎片(薄膜衣片)':
  2307. # expiry_date = '24个月'
  2308. # manufacturer = '石家庄东方药业股份有限公司'
  2309. # approval_number = '国药准字Z20093479'
  2310. # elif self.search_key == '仁和曲安奈德益康唑乳膏':
  2311. # expiry_date = '36个月'
  2312. # manufacturer = '福建太平洋制药有限公司'
  2313. # approval_number = '国药准字H20064180'
  2314. # elif self.search_key == '仁和头孢克洛干混悬剂':
  2315. # expiry_date = '24个月'
  2316. # manufacturer = '山东益康药业股份有限公司'
  2317. # approval_number = '国药准字H20084417'
  2318. # elif self.search_key == '伊康美宝甲硝唑氯己定洗剂':
  2319. # expiry_date = '24个月'
  2320. # manufacturer = '江西药都仁和制药有限公司'
  2321. # approval_number = '国药准字H20043498'
  2322. # elif self.search_key == '仁和布洛芬缓释胶囊':
  2323. # expiry_date = '36个月'
  2324. # manufacturer = '福建太平洋制药有限公司'
  2325. # approval_number = '国药准字H20093691'
  2326. # elif self.search_key == '闪亮萘敏维滴眼液':
  2327. # expiry_date = '24个月'
  2328. # manufacturer = '江西闪亮制药有限公司'
  2329. # approval_number = '国药准字H20064223'
  2330. # elif self.search_key == '闪亮复方门冬维甘滴眼液':
  2331. # expiry_date = '24个月'
  2332. # manufacturer = '江西闪亮制药有限公司'
  2333. # approval_number = '国药准字H20083254‌'
  2334. # elif self.search_key == '米阿卡小儿止咳糖浆':
  2335. # expiry_date = '24个月'
  2336. # manufacturer = '江西远东药业股份有限公司'
  2337. # approval_number = '国药准字Z36020251'
  2338. # elif self.search_key == '仁和人工牛黄甲硝唑胶囊':
  2339. # expiry_date = '24个月'
  2340. # manufacturer = '江西药都仁和制药有限公司'
  2341. # approval_number = '国药准字H36022263'
  2342. # elif self.search_key == '仁和盐酸左氧氟沙星胶囊':
  2343. # expiry_date = '24个月'
  2344. # manufacturer = '海南海神同洲制药有限公司'
  2345. # approval_number = '国药准字H20103012'
  2346. # elif self.search_key == '仁和苯磺酸氨氯地平片':
  2347. # expiry_date = '36个月'
  2348. # manufacturer = '江西制药有限责任公司'
  2349. # approval_number = '国药准字H20083949'
  2350. # elif self.search_key == '仁和阿昔洛韦乳膏':
  2351. # expiry_date = '24个月'
  2352. # manufacturer = '江西吉安三力制药有限公司'
  2353. # approval_number = '国药准字H20063386'
  2354. # else:
  2355. # is_has_instructions = self.safe_exec(self.has_instructions)
  2356. # # 说明书等信息
  2357. # if is_has_instructions:
  2358. # print('开始获取说明书信息')
  2359. # # instructions_info = self.get_instructions_data()
  2360. # instructions_info = self.safe_exec(self.get_instructions_data)
  2361. # if instructions_info['有效期'] is not None:
  2362. # expiry_date = instructions_info['有效期'].strip('。')
  2363. # if instructions_info['生产单位'] is not None:
  2364. # manufacturer = instructions_info['生产单位'].strip('。')
  2365. # if instructions_info['批准文号'] is not None:
  2366. # approval_number = instructions_info['批准文号'].strip('。')
  2367. # else:
  2368. # # 没有说明书不入库
  2369. # print('没有获取到说明书信息')
  2370. # self.swipe_back(1)
  2371. # return
  2372. #暂时不获取说明书信息 end
  2373. self.unrelated_data = 0
  2374. # 爬取省份
  2375. scrape_province = '广东' # 这里先默认广东
  2376. # 是否有货
  2377. availability = ''
  2378. save_data = {
  2379. 'product': product,
  2380. 'min_price': min_price,
  2381. 'manufacture_date': manufacture_date,
  2382. 'expiry_date': expiry_date,
  2383. 'shop': shop,
  2384. 'business_license_company': business_license_company,
  2385. 'province': province,
  2386. 'city': city,
  2387. 'manufacturer': manufacturer,
  2388. 'specification': specifications,
  2389. 'approval_number': approval_number,
  2390. 'product_link': product_link,
  2391. 'scrape_date': scrape_date,
  2392. 'scrape_province': scrape_province,
  2393. 'availability': availability,
  2394. 'credit_code': credit_code,
  2395. 'platform': '美团',
  2396. 'search_key': self.search_key,
  2397. }
  2398. self.save_to_database(save_data)
  2399. # time.sleep(100000)
  2400. time.sleep(self.get_sleep_time())
  2401. if self.distinct_target():
  2402. print('已到达搜索列表页')
  2403. else:
  2404. for i in range(1):
  2405. print('在详情页')
  2406. self.swipe_back(1)
  2407. time.sleep(self.get_sleep_time())
  2408. # 最外部有个定位按钮
  2409. if self.distinct_target():
  2410. break
  2411. #主函数
  2412. def main(self, device_id, retry_count=0):
  2413. MAX_RETRY = 3 # 最大重试次数
  2414. spider_no = 0
  2415. self.connect_devices(device_id)
  2416. time.sleep(self.get_sleep_time())
  2417. # self.d.toast.show("测试toast", 20)
  2418. # 启动全局弹窗监控
  2419. self.monitor = SpiderMonitor(self)
  2420. self.monitor.start()
  2421. try:
  2422. # 重新开启美团应用
  2423. self.restart_app()
  2424. # 搜索关键字
  2425. # self.enter_target_page()
  2426. self.safe_exec(self.enter_target_page)
  2427. # print('开始滑动')
  2428. # self.d.drag(300, 1400, 300, 400, 1)
  2429. # time.sleep(100000)
  2430. for idx in range(300):
  2431. print(f'第{idx + 1}页')
  2432. if spider_no > 30:
  2433. time.sleep(60)
  2434. spider_no = 0
  2435. print('目前无关数据量: ', self.unrelated_data)
  2436. # 检查是否需要暂停(验证码过多)
  2437. if self.monitor.verification_count >= self.monitor.MAX_VERIFICATION_RETRY:
  2438. print("频繁遇到验证码,暂停程序")
  2439. # self.d.toast("请处理验证码后点击继续", 30)
  2440. # 等待用户点击屏幕继续
  2441. self.d.click(0, 0) # 无效点击,等待用户操作
  2442. self.monitor.verification_count = 0
  2443. if self.unrelated_data > 10:
  2444. # # 连续超过5个不达标的数据则停止采集
  2445. self.loggerMT.info('连续10个不达标的数据则停止该品规数据的采集')
  2446. return
  2447. # 线程安全获取商品列表
  2448. # drug_lis = self.d.xpath('//android.support.v7.widget.RecyclerView/android.widget.FrameLayout').all()
  2449. # drug_lis = self.safe_list('//android.support.v7.widget.RecyclerView/android.widget.FrameLayout', self.monitor)
  2450. while True:
  2451. if self.d.xpath('//android.support.v7.widget.RecyclerView/android.widget.FrameLayout').exists:
  2452. break
  2453. time.sleep(1)
  2454. drug_lis = self.safe_exec(self.d.xpath('//android.support.v7.widget.RecyclerView/android.widget.FrameLayout').all)
  2455. lis_len = len(drug_lis)
  2456. print(f'当前页面共有{lis_len}个商品')
  2457. for idxx,drug_one in enumerate(drug_lis,start = 1):
  2458. bounds = drug_one.info['bounds']
  2459. top = bounds['top']
  2460. bottom = bounds['bottom']
  2461. # height = bottom - top
  2462. print(f'当前商品bottom:{bottom}')
  2463. print(f'当前商品top:{top}')
  2464. # if 304 <= top and bottom <= 1475: # 默认高度241的才行
  2465. if 304 <= top and bottom <= 1475: # 默认高度241的才行 1559
  2466. # print('目标-->', drug_one.info)
  2467. # drug_one.click()
  2468. #获取当前元素中的属性来判断是否要点击进入采集
  2469. print(f"这页的第几个商品:{idxx}")
  2470. product_title = ''
  2471. price = ''
  2472. shop_name = ''
  2473. #商品名称的xpath
  2474. product_tittle_xpath = f'//android.support.v7.widget.RecyclerView/android.widget.FrameLayout[{idxx}]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.widget.FrameLayout[1]/android.widget.TextView'
  2475. product_tittle_xpath2 = f'//android.support.v7.widget.RecyclerView/android.widget.FrameLayout[{idxx}]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.widget.FrameLayout[1]/android.widget.TextView'
  2476. if self.d.xpath(product_tittle_xpath).exists:
  2477. product_title = self.d.xpath(product_tittle_xpath).text
  2478. product_title = product_title[1:] if product_title.startswith('0') else product_title
  2479. print(f"product_tittle_xpath列表当前商品名称:{product_title}")
  2480. elif self.d.xpath(product_tittle_xpath2).exists:
  2481. product_title = self.d.xpath(product_tittle_xpath2).text
  2482. product_title = product_title[1:] if product_title.startswith('0') else product_title
  2483. print(f"product_tittle_xpath2列表当前商品名称:{product_title}")
  2484. else:
  2485. print(f"列表当前商品名称不存在")
  2486. #优化流程,只有product_title 不为空的时候才判断当前名称是否符合标准
  2487. if product_title:
  2488. if '仁和' in self.search_key:
  2489. if self.search_key == '仁和可立克复方氨酚烷胺胶囊12粒':
  2490. temp_search_key = self.search_key.replace("仁和可立克", "")
  2491. temp_search_key = temp_search_key.replace("12粒", "")
  2492. elif self.search_key == '仁和咽炎片(薄膜衣片)':
  2493. temp_search_key = self.search_key.replace("仁和", "")
  2494. temp_search_key = temp_search_key.replace("(薄膜衣片)", "")
  2495. elif self.search_key == '仁和中方消炎镇痛膏':
  2496. temp_search_key = self.search_key.replace("仁和中方", "")
  2497. elif self.search_key == '仁和藿香正气合剂10ml*6':
  2498. temp_search_key = self.search_key.replace("仁和", "")
  2499. temp_search_key = temp_search_key.replace("10ml*6", "")
  2500. elif self.search_key == '仁和可立克磷酸奥司他韦胶囊':
  2501. temp_search_key = self.search_key.replace("仁和可立克", "")
  2502. elif self.search_key == '仁和可立克感冒软胶囊':
  2503. temp_search_key = self.search_key.replace("仁和可立克", "")
  2504. else:
  2505. temp_search_key = self.search_key.replace("仁和", "")
  2506. else:
  2507. if self.search_key == '伊康美宝甲硝唑氯己定洗剂':
  2508. temp_search_key = self.search_key.replace("伊康美宝", "")
  2509. elif self.search_key == '闪亮萘敏维滴眼液':
  2510. temp_search_key = self.search_key.replace("闪亮", "")
  2511. elif self.search_key == '闪亮复方门冬维甘滴眼液':
  2512. temp_search_key = self.search_key.replace("闪亮", "")
  2513. elif self.search_key == '米阿卡小儿止咳糖浆':
  2514. temp_search_key = self.search_key.replace("米阿卡", "")
  2515. elif self.search_key == '达舒克硝酸益康唑喷雾剂':
  2516. temp_search_key = self.search_key.replace("达舒克", "")
  2517. elif self.search_key == '闪亮盐酸奥洛他定滴眼液':
  2518. temp_search_key = self.search_key.replace("闪亮", "")
  2519. elif self.search_key == '闪亮左氧氟沙星滴眼液':
  2520. temp_search_key = self.search_key.replace("闪亮", "")
  2521. elif self.search_key == '妇炎洁植物本草抑菌洗液380ml':
  2522. temp_search_key = self.search_key.replace("妇炎洁", "")
  2523. temp_search_key = temp_search_key.replace("380ml", "")
  2524. elif self.search_key == '妇炎洁洁阴康洗液':
  2525. temp_search_key = self.search_key.replace("妇炎洁", "")
  2526. elif self.search_key == '妇炎洁医用护理垫245*70':
  2527. temp_search_key = self.search_key.replace("妇炎洁", "")
  2528. temp_search_key = temp_search_key.replace("245*70", "")
  2529. elif self.search_key == '妇炎洁克霉唑阴道片':
  2530. temp_search_key = self.search_key.replace("妇炎洁", "")
  2531. elif self.search_key == '优卡丹葡萄糖酸钙锌口服溶液':
  2532. temp_search_key = self.search_key.replace("优卡丹", "")
  2533. elif self.search_key == '优卡丹小儿氨酚烷胺颗粒':
  2534. temp_search_key = self.search_key.replace("优卡丹", "")
  2535. elif self.search_key == '克快好强力枇杷露':
  2536. temp_search_key = self.search_key.replace("克快好", "")
  2537. elif self.search_key == '君扬他达拉非片':
  2538. temp_search_key = self.search_key.replace("君扬", "")
  2539. elif self.search_key == '米阿卡头孢克肟颗粒':
  2540. temp_search_key = self.search_key.replace("米阿卡", "")
  2541. elif self.search_key == '克快好治咳枇杷合剂':
  2542. temp_search_key = self.search_key.replace("克快好", "")
  2543. elif self.search_key == '优卡丹三合钙咀嚼片':
  2544. temp_search_key = self.search_key.replace("优卡丹", "")
  2545. elif self.search_key == '必艾得吲哚美辛巴布膏':
  2546. temp_search_key = self.search_key.replace("必艾得", "")
  2547. elif self.search_key == '宁新宝葡萄糖酸钙片':
  2548. temp_search_key = self.search_key.replace("宁新宝", "")
  2549. elif self.search_key == '闪亮玻璃酸钠滴眼液':
  2550. temp_search_key = self.search_key.replace("闪亮", "")
  2551. elif self.search_key == '闪亮地夸磷索钠滴眼液':
  2552. temp_search_key = self.search_key.replace("闪亮", "")
  2553. elif self.search_key == '闪亮复方尿维氨滴眼液':
  2554. temp_search_key = self.search_key.replace("闪亮", "")
  2555. elif self.search_key == '闪亮盐酸莫西沙星滴眼液':
  2556. temp_search_key = self.search_key.replace("闪亮", "")
  2557. if self.search_key == '伊康美宝甲硝唑氯己定洗剂':
  2558. if '伊康美宝' not in product_title or temp_search_key not in product_title :
  2559. print(f"当前商品名称:{product_title} 不包含关键字:{temp_search_key}")
  2560. self.unrelated_data += 1
  2561. continue
  2562. elif self.search_key == '仁和可立克复方氨酚烷胺胶囊12粒':
  2563. if '仁和' not in product_title or temp_search_key not in product_title :
  2564. print(f"当前商品名称:{product_title} 不包含关键字:{temp_search_key}")
  2565. self.unrelated_data += 1
  2566. continue
  2567. elif '12' not in product_title:
  2568. print(f"当前商品名称:{product_title} 不包含12品规")
  2569. self.unrelated_data += 1
  2570. continue
  2571. elif self.search_key == '仁和咽炎片(薄膜衣片)':
  2572. if '仁和' not in product_title or temp_search_key not in product_title :
  2573. print(f"当前商品名称:{product_title} 不包含关键字:{temp_search_key}")
  2574. self.unrelated_data += 1
  2575. continue
  2576. elif '0.25g*15片*3板' not in product_title:
  2577. print(f"当前商品名称:{product_title} 不包含0.25g*15片*3板品规")
  2578. self.unrelated_data += 1
  2579. continue
  2580. elif self.search_key == '闪亮萘敏维滴眼液':
  2581. if '闪亮' not in product_title or temp_search_key not in product_title :
  2582. print(f"当前商品名称:{product_title} 不包含关键字:{temp_search_key}")
  2583. self.unrelated_data += 1
  2584. continue
  2585. elif self.search_key == '闪亮复方门冬维甘滴眼液':
  2586. if '闪亮' not in product_title or temp_search_key not in product_title :
  2587. print(f"当前商品名称:{product_title} 不包含关键字:{temp_search_key}")
  2588. self.unrelated_data += 1
  2589. continue
  2590. elif self.search_key == '米阿卡小儿止咳糖浆':
  2591. if '米阿卡' not in product_title or temp_search_key not in product_title :
  2592. print(f"当前商品名称:{product_title} 不包含关键字:{temp_search_key}")
  2593. self.unrelated_data += 1
  2594. continue
  2595. elif self.search_key == '仁和中方消炎镇痛膏':
  2596. if '仁和中方' not in product_title or temp_search_key not in product_title :
  2597. print(f"当前商品名称:{product_title} 不包含关键字:{temp_search_key}")
  2598. self.unrelated_data += 1
  2599. continue
  2600. elif self.search_key == '达舒克硝酸益康唑喷雾剂':
  2601. if '达舒克' not in product_title or temp_search_key not in product_title :
  2602. print(f"当前商品名称:{product_title} 不包含关键字:{temp_search_key}")
  2603. self.unrelated_data += 1
  2604. continue
  2605. elif self.search_key == '闪亮盐酸奥洛他定滴眼液':
  2606. if '闪亮' not in product_title or temp_search_key not in product_title :
  2607. print(f"当前商品名称:{product_title} 不包含关键字:{temp_search_key}")
  2608. self.unrelated_data += 1
  2609. continue
  2610. elif self.search_key == '闪亮左氧氟沙星滴眼液':
  2611. if '闪亮' not in product_title or temp_search_key not in product_title :
  2612. print(f"当前商品名称:{product_title} 不包含关键字:{temp_search_key}")
  2613. self.unrelated_data += 1
  2614. continue
  2615. elif self.search_key == '妇炎洁植物本草抑菌洗液380ml':
  2616. if '妇炎洁' not in product_title or temp_search_key not in product_title :
  2617. print(f"当前商品名称:{product_title} 不包含关键字:{temp_search_key}")
  2618. self.unrelated_data += 1
  2619. continue
  2620. elif '380ml' not in product_title:
  2621. print(f"当前商品名称:{product_title} 不包含380ml品规")
  2622. self.unrelated_data += 1
  2623. continue
  2624. elif self.search_key == '妇炎洁洁阴康洗液':
  2625. if '妇炎洁' not in product_title or temp_search_key not in product_title :
  2626. print(f"当前商品名称:{product_title} 不包含关键字:{temp_search_key}")
  2627. self.unrelated_data += 1
  2628. continue
  2629. elif self.search_key == '妇炎洁医用护理垫245*70':
  2630. if '妇炎洁' not in product_title or temp_search_key not in product_title :
  2631. print(f"当前商品名称:{product_title} 不包含关键字:{temp_search_key}")
  2632. self.unrelated_data += 1
  2633. continue
  2634. elif '245*70' not in product_title:
  2635. print(f"当前商品名称:{product_title} 不包含245*70品规")
  2636. self.unrelated_data += 1
  2637. continue
  2638. elif self.search_key == '妇炎洁克霉唑阴道片':
  2639. if '妇炎洁' not in product_title or temp_search_key not in product_title :
  2640. print(f"当前商品名称:{product_title} 不包含关键字:{temp_search_key}")
  2641. self.unrelated_data += 1
  2642. continue
  2643. elif self.search_key == '优卡丹葡萄糖酸钙锌口服溶液':
  2644. if '优卡丹' not in product_title or temp_search_key not in product_title :
  2645. print(f"当前商品名称:{product_title} 不包含关键字:{temp_search_key}")
  2646. self.unrelated_data += 1
  2647. continue
  2648. elif self.search_key == '优卡丹小儿氨酚烷胺颗粒':
  2649. if '优卡丹' not in product_title or temp_search_key not in product_title :
  2650. print(f"当前商品名称:{product_title} 不包含关键字:{temp_search_key}")
  2651. self.unrelated_data += 1
  2652. continue
  2653. elif self.search_key == '克快好强力枇杷露':
  2654. if '克快好' not in product_title or temp_search_key not in product_title :
  2655. print(f"当前商品名称:{product_title} 不包含关键字:{temp_search_key}")
  2656. self.unrelated_data += 1
  2657. continue
  2658. elif self.search_key == '君扬他达拉非片':
  2659. if '君扬' not in product_title or temp_search_key not in product_title :
  2660. print(f"当前商品名称:{product_title} 不包含关键字:{temp_search_key}")
  2661. self.unrelated_data += 1
  2662. continue
  2663. elif self.search_key == '仁和藿香正气合剂10ml*6':
  2664. if '仁和' not in product_title or temp_search_key not in product_title :
  2665. print(f"当前商品名称:{product_title} 不包含关键字:{temp_search_key}")
  2666. self.unrelated_data += 1
  2667. continue
  2668. elif '10ml*6' not in product_title:
  2669. print(f"当前商品名称:{product_title} 不包含10ml*6品规")
  2670. self.unrelated_data += 1
  2671. continue
  2672. elif self.search_key == '米阿卡头孢克肟颗粒':
  2673. if '米阿卡' not in product_title or temp_search_key not in product_title :
  2674. print(f"当前商品名称:{product_title} 不包含关键字:{temp_search_key}")
  2675. self.unrelated_data += 1
  2676. continue
  2677. elif self.search_key == '克快好治咳枇杷合剂':
  2678. if '克快好' not in product_title or temp_search_key not in product_title :
  2679. print(f"当前商品名称:{product_title} 不包含关键字:{temp_search_key}")
  2680. self.unrelated_data += 1
  2681. continue
  2682. elif self.search_key == '仁和可立克磷酸奥司他韦胶囊':
  2683. if '仁和可立克' not in product_title or temp_search_key not in product_title :
  2684. print(f"当前商品名称:{product_title} 不包含关键字:{temp_search_key}")
  2685. self.unrelated_data += 1
  2686. continue
  2687. elif self.search_key == '仁和可立克感冒软胶囊':
  2688. if '仁和可立克' not in product_title or temp_search_key not in product_title :
  2689. print(f"当前商品名称:{product_title} 不包含关键字:{temp_search_key}")
  2690. self.unrelated_data += 1
  2691. continue
  2692. elif self.search_key == '优卡丹三合钙咀嚼片':
  2693. if '优卡丹' not in product_title or temp_search_key not in product_title :
  2694. print(f"当前商品名称:{product_title} 不包含关键字:{temp_search_key}")
  2695. self.unrelated_data += 1
  2696. continue
  2697. elif self.search_key == '必艾得吲哚美辛巴布膏':
  2698. if '必艾得' not in product_title or temp_search_key not in product_title :
  2699. print(f"当前商品名称:{product_title} 不包含关键字:{temp_search_key}")
  2700. self.unrelated_data += 1
  2701. continue
  2702. elif self.search_key == '宁新宝葡萄糖酸钙片':
  2703. if '宁新宝' not in product_title or temp_search_key not in product_title :
  2704. print(f"当前商品名称:{product_title} 不包含关键字:{temp_search_key}")
  2705. self.unrelated_data += 1
  2706. continue
  2707. elif self.search_key == '闪亮玻璃酸钠滴眼液':
  2708. if '闪亮' not in product_title or temp_search_key not in product_title :
  2709. print(f"当前商品名称:{product_title} 不包含关键字:{temp_search_key}")
  2710. self.unrelated_data += 1
  2711. continue
  2712. elif self.search_key == '闪亮地夸磷索钠滴眼液':
  2713. if '闪亮' not in product_title or temp_search_key not in product_title :
  2714. print(f"当前商品名称:{product_title} 不包含关键字:{temp_search_key}")
  2715. self.unrelated_data += 1
  2716. continue
  2717. elif self.search_key == '闪亮复方尿维氨滴眼液':
  2718. if '闪亮' not in product_title or temp_search_key not in product_title :
  2719. print(f"当前商品名称:{product_title} 不包含关键字:{temp_search_key}")
  2720. self.unrelated_data += 1
  2721. continue
  2722. elif self.search_key == '闪亮盐酸莫西沙星滴眼液':
  2723. if '闪亮' not in product_title or temp_search_key not in product_title :
  2724. print(f"当前商品名称:{product_title} 不包含关键字:{temp_search_key}")
  2725. self.unrelated_data += 1
  2726. continue
  2727. else:
  2728. if '仁和' not in product_title or temp_search_key not in product_title :
  2729. print(f"当前商品名称:{product_title} 不包含关键字:{temp_search_key}")
  2730. self.unrelated_data += 1
  2731. continue
  2732. #价格
  2733. price_xpath = f'//android.support.v7.widget.RecyclerView/android.widget.FrameLayout[{idxx}]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.widget.FrameLayout[1]/android.widget.TextView'
  2734. price_xpath3 = f'//android.support.v7.widget.RecyclerView/android.widget.FrameLayout[{idxx}]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.widget.FrameLayout[1]/android.widget.TextView'
  2735. price_xpath1 = f'//android.support.v7.widget.RecyclerView/android.widget.FrameLayout[{idxx}]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.widget.FrameLayout[1]/android.widget.TextView'
  2736. if self.d.xpath(price_xpath).exists:
  2737. price_str = self.d.xpath(price_xpath).text
  2738. print(f"price_xpath列表当前商品价格:{price_str}")
  2739. if price_str:
  2740. price = float(re.search('[\d\.]+', price_str).group())
  2741. elif self.d.xpath(price_xpath3).exists:
  2742. price_str = self.d.xpath(price_xpath3).text
  2743. print(f"price_xpath3列表当前商品价格:{price_str}")
  2744. if price_str:
  2745. price = float(re.search('[\d\.]+', price_str).group())
  2746. elif self.d.xpath(price_xpath1).exists:
  2747. price_str = self.d.xpath(price_xpath1).text
  2748. print(f"price_xpath1列表当前商品价格:{price_str}")
  2749. if price_str:
  2750. price = float(re.search('[\d\.]+', price_str).group())
  2751. else:
  2752. price_xpath2 = f'//android.support.v7.widget.RecyclerView/android.widget.FrameLayout[{idxx}]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.widget.FrameLayout[1]/android.widget.TextView'
  2753. if self.d.xpath(price_xpath2).exists:
  2754. price_str = self.d.xpath(price_xpath2).text
  2755. print(f"price_xpath2列表当前商品价格:{price_str}")
  2756. if price_str:
  2757. price = float(re.search('[\d\.]+', price_str).group())
  2758. else:
  2759. print(f"列表当前商品价格不存在")
  2760. # price_str = self.d.xpath(f'//android.support.v7.widget.RecyclerView/android.widget.FrameLayout[{idxx}]//*[starts-with(@text,"¥")]').text
  2761. print(f'列表获取到价格:{price}')
  2762. #店铺名称的xpath
  2763. shop_name_xpath = f'//android.support.v7.widget.RecyclerView/android.widget.FrameLayout[{idxx}]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[2]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.widget.FrameLayout[last()]/android.widget.TextView[1]'
  2764. shop_name_xpath2 = f'//android.support.v7.widget.RecyclerView/android.widget.FrameLayout[{idxx}]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[2]/android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.widget.FrameLayout[last()]/android.widget.TextView[1]'
  2765. if self.d.xpath(shop_name_xpath).exists:
  2766. shop_name = self.d.xpath(shop_name_xpath).text
  2767. print(f"shop_name_xpath列表当前商品店铺名称:{shop_name}")
  2768. elif self.d.xpath(shop_name_xpath2).exists:
  2769. shop_name = self.d.xpath(shop_name_xpath2).text
  2770. print(f"shop_name_xpath2列表当前商品店铺名称:{shop_name}")
  2771. else:
  2772. print(f"列表当前商品店铺名称不存在")
  2773. #如果商品的名称、价格和生产厂家都不存在则直接下一条数据。 跳过一些不是商品的数据。
  2774. if product_title == '' and price == '' and shop_name == '':
  2775. continue
  2776. scrape_date = self.get_current_date()
  2777. if product_title and price and shop_name:
  2778. #判断数据表中是否存在
  2779. dup_data = {'product': product_title, 'min_price': price, 'shop': shop_name, 'scrape_date': scrape_date,'platform': '美团'}
  2780. if self.data_is_exists(dup_data):
  2781. print('列表存在相同数据不入库')
  2782. continue
  2783. # match = re.match(r'(\[[^\]]+\])(.*?)\s*((?:\d+\S*|\(.+))$', product_title)
  2784. # if match:
  2785. # specifications = match.group(3).strip()
  2786. # else:
  2787. # specifications = ''
  2788. # save_data = {
  2789. # 'product': product_title,
  2790. # 'min_price': price,
  2791. # 'manufacture_date': '',
  2792. # 'expiry_date': '',
  2793. # 'shop': shop_name,
  2794. # 'business_license_company': '',
  2795. # 'province': '',
  2796. # 'city': '',
  2797. # 'manufacturer': '',
  2798. # 'specification': specifications,
  2799. # 'approval_number': '',
  2800. # 'product_link': '',
  2801. # 'scrape_date': scrape_date,
  2802. # 'scrape_province': scrape_province,
  2803. # 'availability': '',
  2804. # 'credit_code': '',
  2805. # 'platform': '美团',
  2806. # 'search_key': self.search_key,
  2807. # }
  2808. # self.save_to_database(save_data)
  2809. # time.sleep(self.get_sleep_time())
  2810. self.safe_exec(drug_one.click)
  2811. print('点击目标药品完毕')
  2812. time.sleep(2)
  2813. # 采集药品信息
  2814. try:
  2815. # self.integrate_data()
  2816. self.safe_exec(self.integrate_data)
  2817. # 检测下是否回退到列表页
  2818. if self.distinct_target():
  2819. print('回退到列表页', True)
  2820. else:
  2821. if self.d.xpath('//*[@text="搜索"]').exists:
  2822. print("检测到搜索按钮,重新开始采集流程")
  2823. if retry_count < MAX_RETRY:
  2824. # 停止当前监控线程
  2825. self.monitor.stop()
  2826. self.monitor.join()
  2827. # 递归重启采集
  2828. return self.main(device_id, retry_count+1)
  2829. else:
  2830. print("超过最大重试次数,终止程序")
  2831. return
  2832. else:
  2833. print("无法恢复页面,终止采集")
  2834. return
  2835. # print('回退到列表页失败,终止采集')
  2836. # return
  2837. time.sleep(self.get_sleep_time())
  2838. spider_no += 1
  2839. except Exception as e:
  2840. print(f'采集药品详情数据出错:{e}')
  2841. #增加阻塞的方法:
  2842. if not self.distinct_target():
  2843. for i in range(1):
  2844. self.swipe_back(1)
  2845. # 最外部有个定位按钮
  2846. if self.distinct_target():
  2847. break
  2848. if i == 0 and not self.distinct_target():
  2849. print('页面出错,退出采集')
  2850. return
  2851. else:
  2852. continue
  2853. if self.d.xpath('//*[@text="已经到底啦"]').exists:
  2854. print('已经到达列表页最底部')
  2855. return
  2856. search_list = self.d.xpath('//android.support.v7.widget.RecyclerView').info
  2857. bounds = search_list['bounds']
  2858. #print('搜索列表高度', 1400 + bounds['top'] - bounds['bottom'])
  2859. # self.d.swipe(200, 1400, 200, 1400 + bounds['top'] - bounds['bottom'])
  2860. # 计算滑动距离
  2861. scroll_distance = bounds['bottom'] - bounds['top'] # 正数
  2862. start_y = 1600
  2863. end_y = start_y - scroll_distance # 向上滑动,y 坐标减小
  2864. # 确保 end_y 不小于 0
  2865. end_y = max(end_y, 304) # 留出一点边距,避免滑出屏幕
  2866. # print('滑动起点 y:', start_y, '终点 y:', end_y)
  2867. # self.d.swipe(200, start_y, 200, end_y, 0.4)
  2868. print('开始滑动')
  2869. self.d.drag(300, 1400, 300, 400, 1)
  2870. # self.safe_exec(self.d.drag, 300, 1400, 300, 400, 1)
  2871. print('滑动结束')
  2872. #print('搜索列表高度', 1400 + bounds['top'] - bounds['bottom'])
  2873. # self.d.swipe(200, 1400, 200, 1400 + bounds['top'] - bounds['bottom'])
  2874. # self.d.swipe(200, 1400, 200, 1400 + bounds['top'] - bounds['bottom'], 0.4)
  2875. time.sleep(self.get_sleep_time())
  2876. finally:
  2877. # 确保监控线程被停止
  2878. self.monitor.stop()
  2879. self.monitor.join()
  2880. def unitest(self):
  2881. """
  2882. 单元测试
  2883. :return:
  2884. """
  2885. save_data = {
  2886. 'product':"[昆中药]舒肝颗粒(低糖型)",
  2887. 'min_price': 14.0,
  2888. 'manufacture_date': '',
  2889. 'expiry_date': '36个月',
  2890. 'shop': '美团自营大药房(快递电商)',
  2891. 'business_license_company': '',
  2892. 'province': '',
  2893. 'city': '',
  2894. 'manufacturer': '昆明中药厂有限公司',
  2895. 'specification': '3g*16袋/盒',
  2896. 'approval_number': '国药准字Z53021161',
  2897. 'product_link': '',
  2898. 'scrape_date': '2025/07/09',
  2899. 'scrape_province': '广东',
  2900. 'availability': '',
  2901. 'credit_code': '',
  2902. 'platform': '美团'
  2903. }
  2904. self.save_to_database(save_data)
  2905. time.sleep(100000)
  2906. pass
  2907. def main():
  2908. keys_list = [
  2909. # '三九胃泰颗粒',
  2910. # '999小柴胡颗粒',
  2911. # '999强力枇杷露',
  2912. # '[999]感冒清热颗粒',
  2913. # '999抗病毒口服液',
  2914. # '999皮炎平',
  2915. # '999盐酸特比萘芬乳膏',
  2916. # '999盐酸特比萘芬',
  2917. # '999藿香正气合剂',
  2918. # '999必无忧盐酸特比萘芬乳膏',
  2919. # '999复方感冒灵颗粒',
  2920. # '999糠酸莫米松凝胶',
  2921. # '999铝碳酸镁咀嚼片',
  2922. # '999阿奇霉素片',
  2923. # '999选平硝酸咪康唑乳膏',
  2924. # 按需继续添加,
  2925. #暂时不需要
  2926. # '999必无忧盐酸特比萘芬喷雾剂30'
  2927. # '999冰连清咽'
  2928. # '999复方金银花颗粒10g'
  2929. # '999复方苦参肠炎康片12片'
  2930. # '999强力枇杷露16袋'
  2931. # '999三蛇胆川贝膏138'
  2932. # '999维生素ec颗粒'
  2933. # '三九胃泰养胃舒颗粒8袋'
  2934. # '999止泻利颗粒15g*8'
  2935. # '999阿奇霉素片'
  2936. # '999可调式生理性海水鼻腔喷雾50'
  2937. # '999小儿止咳糖浆120' #不低于19.8
  2938. # '999小儿止咳糖浆225' #禁止挂网
  2939. # '999小儿感冒颗粒6g*10' #不低于24.9
  2940. # '999小儿感冒颗粒6g*24' #禁止挂网
  2941. # '999小儿氨酚黄那敏颗粒6g*10袋' #不低于15.8
  2942. # '999小儿氨酚黄那敏颗粒6g*20袋' #禁止挂网
  2943. # '999小儿咽扁颗粒8g*10袋' #仅限999官旗店
  2944. #2025-08-01最新 其中 藿香正气合剂两种规格 10支和6支 抗病毒口服液 12支和18支 蒲地蓝 24片 36片和44片 枇杷露225ml 小柴胡颗粒9袋和15袋 养胃舒 6袋 复方感冒灵颗粒15袋,
  2945. #曲安奈德益康唑乳膏 30g 葡萄糖酸锌口服溶液 12支 18支 24支和30支,
  2946. # 1、999止泻利颗粒15g*8 没有数据 2、999维生素ec颗粒 没有数据 3、999三蛇胆川贝膏138 没有数据 4、999强力枇杷露16袋 没有数据 5、999冰连清咽 没有数据
  2947. # '999藿香正气合剂',
  2948. # '999糠酸莫米松凝胶15',
  2949. # '999抗病毒口服液'
  2950. # '999抗病毒口服液10ml*10'
  2951. # '999抗病毒口服液10ml*12',
  2952. # '999蒲地蓝消炎片',
  2953. # '999强力枇杷露225ml',
  2954. # '999小柴胡颗粒',
  2955. # '999养胃舒颗粒',
  2956. # '999复方感冒灵颗粒',
  2957. # '999黄芪精',
  2958. # '999皮炎平曲安奈德益康唑乳膏30',
  2959. # '999葡萄糖酸锌口服溶液',
  2960. # '今维多赐多康牌蛋白粉',
  2961. # '佳美舒阿奇霉素肠溶胶囊4'
  2962. # '999必无忧盐酸特比萘芬乳膏15g'
  2963. # '999复方板蓝根颗粒15g*15袋/盒'
  2964. # '999速复康布洛芬缓释胶囊'
  2965. # '999维生素C咀嚼片'
  2966. # '999精氨酸布洛芬颗粒'
  2967. # '999强力枇杷露120ml'
  2968. #OTC
  2969. # '999强力枇杷露150ml'
  2970. # '999糠酸莫米松乳膏10g支'
  2971. # '999选平硝酸咪康唑乳膏20g'
  2972. # '999感冒清热颗粒(无糖)6g'
  2973. # '999银菊清咽颗粒' #只有一条数据
  2974. # '999补脾益肠丸'
  2975. # '999壮骨关节丸6g*20'
  2976. # '999壮骨关节胶囊'
  2977. # '999正天丸6g*15'
  2978. # '999正天胶囊'
  2979. # '三九胃泰胶囊'
  2980. # '三九胃泰颗粒20g*10'
  2981. # '三九胃泰颗粒(无糖)2.5g*6' # 没有数据
  2982. #10.31 new add
  2983. # '999感冒灵颗粒' #不低于15.5
  2984. # '999皮炎平复方醋酸地塞米松乳膏20' #不低于12.5
  2985. # '三九胃泰颗粒20g*6袋' #不低于13.5
  2986. # '顺峰康王酮康他索乳膏' #包含10g和20g两个规格 10g 不低于7.5 20g 不低于12.5
  2987. # '999糠酸莫米松凝胶10' #不低于26.9
  2988. # '999板蓝根颗粒10g*20' #不低于26.9
  2989. # '999复方氨酚烷胺胶囊12粒' #不低于17.9
  2990. # '999复方氨酚烷胺胶囊10粒' #禁止挂网
  2991. # '999复方氨酚烷胺胶囊6粒' #禁止挂网
  2992. # '999复方氨酚烷胺胶囊'
  2993. # '999咽炎片0.26g*12片*2板' #不低于13.5
  2994. # '999感冒灵胶囊' #仅限999官旗店
  2995. # '999荆防颗粒' #美团没有数据 #禁止挂网
  2996. # '999小儿感冒宁颗粒2.5g*10袋' #禁止挂网
  2997. # '999磷酸奥司他韦胶囊75mg*10' #仅限999官旗店
  2998. # '史达功右美沙芬愈创甘油醚糖浆120' #仅限999官旗店
  2999. # '999感冒清热颗粒12g*18'
  3000. # 仁和 O2O
  3001. # '仁和盐酸氨溴索口服溶液',
  3002. # '仁和蒲公英颗粒',
  3003. # '仁和红霉素软膏',
  3004. # '仁和可立克复方氨酚烷胺胶囊12粒',
  3005. # '仁和盐酸羟甲唑啉喷雾剂',
  3006. # '仁和咽炎片(薄膜衣片)',
  3007. # '仁和曲安奈德益康唑乳膏',
  3008. # '仁和头孢克洛干混悬剂',
  3009. # '伊康美宝甲硝唑氯己定洗剂',
  3010. # '仁和布洛芬缓释胶囊',
  3011. # '闪亮萘敏维滴眼液',
  3012. # '闪亮复方门冬维甘滴眼液',
  3013. # '米阿卡小儿止咳糖浆',
  3014. # '仁和人工牛黄甲硝唑胶囊',
  3015. # '仁和盐酸左氧氟沙星胶囊',
  3016. # '仁和苯磺酸氨氯地平片',
  3017. # '仁和阿昔洛韦乳膏',
  3018. # '仁和阿莫西林胶囊',
  3019. # '仁和小柴胡颗粒',
  3020. # '仁和中方消炎镇痛膏', ##特殊处理
  3021. # '仁和头孢克肟片',
  3022. # '仁和头孢克洛分散片',
  3023. # '仁和诺氟沙星胶囊',
  3024. # '仁和川贝清肺糖浆',
  3025. # '达舒克硝酸益康唑喷雾剂',
  3026. # '仁和清火胶囊',
  3027. # '仁和双氯芬酸钠缓释片',
  3028. # '仁和氨咖黄敏胶囊',
  3029. # '仁和四季感冒胶囊',
  3030. # '仁和肺宁颗粒',
  3031. # '仁和银黄颗粒',
  3032. # '仁和蒲地蓝消炎片',
  3033. # '仁和复方鲜竹沥液',
  3034. # '仁和益气养血口服液',
  3035. # '仁和氧氟沙星滴耳液',
  3036. # '仁和蒙脱石散',
  3037. # '仁和奥美拉唑肠溶胶囊',
  3038. # '仁和氯雷他定片',
  3039. # '闪亮盐酸奥洛他定滴眼液',
  3040. # '闪亮左氧氟沙星滴眼液',
  3041. # '妇炎洁植物本草抑菌洗液380ml',
  3042. # '妇炎洁洁阴康洗液',
  3043. # '妇炎洁医用护理垫245*70',
  3044. # '妇炎洁克霉唑阴道片',
  3045. # '仁和益母草颗粒',
  3046. # '仁和红霉素眼膏',
  3047. # '仁和炉甘石洗剂',
  3048. # '优卡丹葡萄糖酸钙锌口服溶液',
  3049. # '优卡丹小儿氨酚烷胺颗粒',
  3050. # '仁和湿毒清片',
  3051. # '仁和阿达帕林凝胶',
  3052. # '仁和盐酸二甲双胍缓释片',
  3053. # '仁和替米沙坦胶囊',
  3054. # '仁和格列齐特缓释片',
  3055. # '仁和双氯芬酸钠气雾剂',
  3056. # '仁和硝苯地平缓释片',
  3057. # '仁和痔速宁片',
  3058. # '仁和氧氟沙星滴眼液',
  3059. # '仁和盐酸左西替利嗪胶囊',
  3060. # '克快好强力枇杷露',
  3061. # '仁和甲钴胺胶囊',
  3062. # '仁和多潘立酮片',
  3063. # '仁和兰索拉唑肠溶片',
  3064. # '仁和复方银翘氨敏胶囊',
  3065. # '君扬他达拉非片',
  3066. # '仁和盐酸达泊西汀片',
  3067. # '仁和藿香正气合剂10ml*6',
  3068. # '仁和阿昔洛韦片',
  3069. # '仁和糠酸莫米松乳膏',
  3070. # '米阿卡头孢克肟颗粒',
  3071. # '克快好治咳枇杷合剂',
  3072. # '仁和雪梨膏',
  3073. # '仁和西青果颗粒',
  3074. # '仁和氨酚烷胺那敏胶囊',
  3075. # '仁和美洛昔康片',
  3076. #20260126
  3077. #20260126
  3078. # '仁和可立克磷酸奥司他韦胶囊',
  3079. # '仁和二至丸',
  3080. # '仁和杞菊地黄口服液',
  3081. # '仁和可立克感冒软胶囊',
  3082. # # '优卡丹三合钙咀嚼片',
  3083. # '仁和三合钙咀嚼片',
  3084. # '仁和愈风宁心片',
  3085. # '仁和碳酸钙D3咀嚼片',
  3086. # '仁和罗红霉素分散片',
  3087. # # '必艾得吲哚美辛巴布膏',
  3088. # '仁和血塞通分散片',
  3089. # '仁和胶体果胶铋胶囊',
  3090. # '仁和足光散',
  3091. # '仁和阿莫西林克拉维酸钾颗粒',
  3092. # # '宁新宝葡萄糖酸钙片',
  3093. # '仁和脑心舒口服液',
  3094. # '仁和前列安通胶囊',
  3095. # '仁和小儿七星茶颗粒',
  3096. # '仁和至灵胶囊',
  3097. # '仁和肾骨片',
  3098. # '仁和盐酸班布特罗胶囊',
  3099. # '仁和妇炎康分散片',
  3100. # '仁和益心酮分散片',
  3101. # '仁和莲芝消炎片',
  3102. # '仁和生发丸',
  3103. # '仁和胆舒软胶囊',
  3104. # '仁和咳喘舒片',
  3105. # '仁和苹果酸氯波必利片',
  3106. # '仁和六味补血胶囊',
  3107. # '仁和复方黄连素片',
  3108. # '仁和复方桔梗止咳片',
  3109. # '仁和孟鲁司特钠颗粒',
  3110. # '仁和吲达帕胺缓释片',
  3111. # '仁和依托红霉素颗粒',
  3112. # '仁和硝酸咪康唑阴道软胶囊',
  3113. # '仁和尼美舒利片',
  3114. # '仁和骨刺消痛胶囊',
  3115. # '仁和复方罗汉果止咳颗粒',
  3116. # '仁和复方熊胆薄荷含片',
  3117. # '仁和灵芝胶囊',
  3118. # '仁和盐酸氨基葡萄糖片',
  3119. # '仁和一清软胶囊',
  3120. # '仁和复方北豆根氨酚那敏片',
  3121. # '仁和止咳枇杷颗粒',
  3122. # '仁和润肠丸',
  3123. # '仁和肌苷口服溶液',
  3124. # '仁和溃疡胶囊',
  3125. # '仁和磷酸苯丙哌林片',
  3126. # '仁和双梅喉片',
  3127. # '仁和尼美舒利胶囊',
  3128. # '仁和安康胶囊',
  3129. # '仁和补气口服液',
  3130. # '仁和大活络丸',
  3131. # '仁和龟甲胶',
  3132. # '仁和蚝贝钙咀嚼片',
  3133. # '仁和健心胶囊',
  3134. # '仁和金参润喉合剂)',
  3135. # '仁和赖氨酸维B12颗粒',
  3136. # '仁和肾宝胶囊',
  3137. # '仁和肾脾双补口服液',
  3138. # '仁和维生素EC片',
  3139. # '仁和医用透明质酸钠敷料',
  3140. # '仁和龟鹿二仙膏',
  3141. # '仁和硫酸氢氯吡格雷片',
  3142. # '仁和复方石韦胶囊',
  3143. # '仁和参芪咀嚼片',
  3144. # '仁和阿胶粉',
  3145. # '仁和妇炎净片',
  3146. # '仁和西洋参胶囊',
  3147. # '仁和强力枇杷膏(蜜炼)',
  3148. # '仁和藤黄健骨片',
  3149. # '仁和依折麦布片',
  3150. # '仁和阿归养血颗粒',
  3151. # '仁和阿胶',
  3152. # '仁和阿胶益寿口服液',
  3153. # '仁和阿莫西林分散片',
  3154. # '仁和阿莫西林颗粒',
  3155. # '仁和阿奇霉素干混悬剂',
  3156. # '仁和阿奇霉素胶囊',
  3157. # '仁和阿托伐他汀钙分散片',
  3158. # '仁和艾司奥美拉唑镁肠溶胶囊',
  3159. # '仁和安宫牛黄丸',
  3160. # '仁和氨酚咖黄烷胺片',
  3161. # '仁和氨糖美辛肠溶片',
  3162. # '仁和氨溴特罗口服溶液',
  3163. # '仁和奥美拉唑肠溶片',
  3164. # '仁和奥硝唑分散片',
  3165. # '仁和板蓝根颗粒',
  3166. # '仁和保和颗粒',
  3167. # '仁和苯磺酸左氨氯地平片',
  3168. # '仁和鼻炎宁颗粒',
  3169. # '仁和冰硼含片',
  3170. # # '闪亮玻璃酸钠滴眼液',
  3171. # '仁和补肾益寿片',
  3172. # '仁和不老莓叶黄素酯DHA软糖',
  3173. # '仁和布洛芬混悬液',
  3174. # '仁和布洛芬颗粒',
  3175. # '仁和参苓白术胶囊',
  3176. # '仁和参苓口服液',
  3177. # '仁和参术儿康糖浆',
  3178. # '仁和藏青果喉片',
  3179. # '仁和川贝止咳露',
  3180. # # '闪亮地夸磷索钠滴眼液',
  3181. # '仁和跌打损伤丸',
  3182. # '仁和跌打万花油',
  3183. # '仁和独一味软胶囊',
  3184. # '仁和对乙酰氨基酚颗粒',
  3185. # '仁和多维元素胶囊',
  3186. # '仁和多维元素片',
  3187. # '仁和厄贝沙坦氢氯噻嗪片',
  3188. # '仁和儿宝颗粒',
  3189. # '仁和二丁颗粒',
  3190. # '仁和二甲双胍格列本脲片',
  3191. # '仁和非布司他片',
  3192. # '仁和非那雄胺片',
  3193. # '仁和肺宁胶囊',
  3194. # '仁和肺宁片',
  3195. # '仁和风油精',
  3196. # '仁和参花消渴茶',
  3197. # '仁和佛手苦瓜茶',
  3198. # '仁和氟康唑胶囊',
  3199. # '仁和妇炎康复咀嚼片',
  3200. # '仁和附桂风湿膏',
  3201. # '仁和复方川芎吲哚美辛胶囊',
  3202. # '仁和复方罗汉果含片',
  3203. # '仁和复方氯己定含漱液',
  3204. # '闪亮复方尿维氨滴眼液',
  3205. # '仁和复方酮康唑软膏',
  3206. # '仁和复方土槿皮酊',
  3207. # '仁和复方乌鸡口服液',
  3208. # '仁和复方锌铁钙口服溶液',
  3209. # '仁和感冒清胶囊',
  3210. # '仁和感冒清热颗粒',
  3211. # '仁和感冒止咳颗粒',
  3212. # '仁和格列吡嗪片',
  3213. # '仁和格列美脲胶囊',
  3214. # '仁和根痛平胶囊',
  3215. # '仁和枸橼酸铋钾胶囊',
  3216. # '仁和枸橼酸氢钾钠颗粒',
  3217. # '仁和枸橼酸西地那非口崩片',
  3218. # '仁和骨友灵贴膏',
  3219. # '仁和关节止痛膏',
  3220. # '仁和桂龙咳喘宁片',
  3221. # '仁和琥珀酸亚铁片',
  3222. # '仁和琥乙红霉素颗粒',
  3223. # '仁和护肝片',
  3224. # '仁和护花天使牌妇泰欣抑菌洗液',
  3225. # '仁和活血止痛片',
  3226. # '仁和藿香正气胶囊',
  3227. # '仁和藿香正气口服液',
  3228. # '仁和健儿消食口服液',
  3229. # '仁和健心胶囊',
  3230. # '仁和降脂宁颗粒',
  3231. # '仁和金参润喉合剂',
  3232. # '仁和颈康胶囊',
  3233. # '仁和橘红颗粒',
  3234. # '仁和橘红枇杷片',
  3235. # '仁和橘红痰咳颗粒',
  3236. # '仁和抗病毒口服液',
  3237. # '仁和抗宫炎胶囊',
  3238. # '仁和抗骨质增生丸',
  3239. # '仁和咳特灵胶囊',
  3240. # '仁和口服补液盐散(Ⅲ)',
  3241. # '仁和口服五维赖氨酸葡萄糖',
  3242. # '仁和辣椒风湿膏',
  3243. # '仁和蓝莓叶黄素酯压片糖果',
  3244. # '仁和了哥王胶囊',
  3245. # '仁和了哥王颗粒',
  3246. # '仁和雷贝拉唑钠肠溶片',
  3247. # '仁和利多卡因氯己定气雾剂',
  3248. # '仁和磷酸奥司他韦胶囊',
  3249. # '仁和硫酸氨基葡萄糖片',
  3250. # '闪亮硫酸锌尿囊素滴眼液',
  3251. # '仁和六味地黄胶囊',
  3252. # '仁和六味地黄丸(浓缩丸)',
  3253. # '仁和罗汉果止咳糖浆',
  3254. # '仁和罗红霉素胶囊',
  3255. # '仁和罗红霉素颗粒',
  3256. # '仁和洛索洛芬钠片',
  3257. # '仁和孟鲁司特钠咀嚼片',
  3258. # '仁和尼可地尔片',
  3259. # '仁和尿素维E乳膏',
  3260. # '仁和排毒养颜片',
  3261. # '仁和排石利胆颗粒',
  3262. # '仁和葡萄糖酸锌颗粒',
  3263. '仁和葡萄糖酸锌口服溶液',
  3264. '仁和杞菊地黄丸(浓缩丸)',
  3265. '仁和前列金丹胶囊',
  3266. '仁和强力枇杷露',
  3267. # '仁和氢溴酸右美沙芬糖浆',
  3268. # '仁和清淋颗粒',
  3269. # '仁和清淋片',
  3270. # '仁和清热明目茶',
  3271. # '仁和祛浊茶',
  3272. # '仁和瑞舒伐他汀钙片',
  3273. # '仁和润肠胶囊',
  3274. # '仁和润肺止咳胶囊',
  3275. # '仁和三维葡磷钙咀嚼片',
  3276. # '仁和伤湿解痛膏',
  3277. # '仁和麝香关节止痛膏',
  3278. # '仁和麝香壮骨膏',
  3279. # '仁和十二乌鸡白凤丸',
  3280. # '仁和舒筋活血片',
  3281. # '仁和四季感冒片',
  3282. # '仁和他达拉非片',
  3283. # '仁和天麻首乌片',
  3284. # '仁和通脉颗粒',
  3285. # '仁和通宣理肺片',
  3286. # '仁和酮洛芬贴片',
  3287. # '仁和头孢克肟颗粒',
  3288. # '仁和维生素C咀嚼片',
  3289. # '仁和维生素E软胶囊',
  3290. # '仁和胃康灵胶囊',
  3291. # '仁和胃痛宁片',
  3292. # '仁和午时茶颗粒',
  3293. # '仁和消渴降糖胶囊',
  3294. # '仁和消栓通络片',
  3295. # '仁和消炎镇痛膏',
  3296. # '仁和硝酸益康唑喷雾剂',
  3297. # '仁和硝酸益康唑乳膏',
  3298. # '仁和小儿氨酚黄那敏颗粒',
  3299. # '仁和小儿感冒颗粒',
  3300. # '仁和小儿化痰止咳颗粒',
  3301. # '仁和小儿咳喘灵颗粒',
  3302. # '仁和小儿咽扁颗粒',
  3303. # '仁和小儿止咳糖浆',
  3304. # '仁和缬沙坦氨氯地平片(Ⅰ)',
  3305. # '仁和缬沙坦胶囊',
  3306. # '仁和心脑康胶囊',
  3307. # '仁和辛伐他汀胶囊',
  3308. '仁和新肤螨灵软膏',
  3309. # '仁和新清宁片',
  3310. # '仁和新血宝胶囊',
  3311. # '仁和杏苏止咳颗粒',
  3312. # '仁和雪山胃宝胶囊',
  3313. # '仁和牙齿脱敏膏',
  3314. # '仁和牙痛药水',
  3315. # '仁和炎可宁胶囊',
  3316. # '仁和盐酸氨溴索分散片',
  3317. # '仁和盐酸氟桂利嗪胶囊',
  3318. '闪亮盐酸莫西沙星滴眼液',
  3319. # '仁和盐酸左西替利嗪口服溶液',
  3320. # '仁和盐酸左氧氟沙星片',
  3321. # '仁和腰痛片',
  3322. # '仁和腰息痛胶囊',
  3323. # '仁和叶酸片',
  3324. # '仁和医用Ⅲ型胶原蛋白修复贴',
  3325. # '仁和医用护眼贴',
  3326. # '仁和医用面部护理敷料',
  3327. # '仁和医用透明质酸钠敷料贴',
  3328. # '仁和医用透明质酸钠皮肤修护液',
  3329. # '仁和医用退热贴(儿童型)',
  3330. # '仁和医用重组人源Ⅲ型胶原蛋白皮肤修复护理膜',
  3331. # '仁和乙酰半胱氨酸颗粒',
  3332. # '仁和银黄滴丸',
  3333. # '仁和银杏叶分散片',
  3334. # '仁和银杏叶软胶囊',
  3335. # '仁和玉屏风口服液',
  3336. # '仁和玉叶清火胶囊',
  3337. # '仁和元七骨痛酊',
  3338. # '仁和远红外活血止痛贴',
  3339. # '仁和远红外止痛贴',
  3340. # '仁和障眼明胶囊',
  3341. # '仁和珍黄胶囊',
  3342. # '仁和知柏地黄丸(浓缩丸)',
  3343. # '仁和治咳枇杷合剂',
  3344. # '仁和壮腰健肾片',
  3345. # '仁和左氧氟沙星片',
  3346. # '仁和磷酸西格列汀片',
  3347. ]
  3348. #美团手机号:
  3349. #美团手机号:
  3350. # device_id = '21885f5' # 设备序列号
  3351. # device_id = '2e58510' # 设备序列号
  3352. # device_id = 'KNNNEMNVWCJZQOLZ'
  3353. # device_id = 'B6JVE6AYSWU4LRLZ'
  3354. # device_id = '656DTOPRZDEALZ5X'
  3355. # device_id = 'GIOFIBRKZTUGJJAE'
  3356. # device_id = 'fcb3c749'
  3357. # device_id = 'UCQGF6CQFMU8WKHI'
  3358. # device_id = '4TZDUGTOAIFMJVGU'
  3359. # device_id = '95b2c764'
  3360. # device_id = 'ZDQWUSSWBEDI896T'
  3361. # device_id = 'R4SKMJPNBQAENRAM'
  3362. # device_id = '1462a51f'
  3363. # device_id = '97ae80e0' # 设备序列号
  3364. # device_id = 'IZTOWWDQT45D49BU'
  3365. # device_id = 'N7ZXBITOSOGMYXQS'
  3366. # device_id = '369dcf96'
  3367. # device_id = 'GQIRKB7LVOONM7VW'
  3368. # device_id = 'T4UCEQGQEEYP65ZL'
  3369. device_id = '49L7GMPRVS85LJHE'
  3370. # device_id = 'WWRO9LTGG6KFGQCM'
  3371. # device_id = 'DYF67TM7KJ4POJLF'
  3372. # device_id = 'ea4e4eb8'
  3373. # device_id = 'U8ONIJJJS4CELVD6'
  3374. # device_id = 'LJ9PN7A6K7HQ9DPF'
  3375. cycle_no = 0 # 轮次计数
  3376. # while True:
  3377. # cycle_no += 1
  3378. # logging.info(f'========== 第 {cycle_no} 轮采集开始 ==========')
  3379. for idx, key in enumerate(keys_list, 1):
  3380. logging.info(f'[{idx}/{len(keys_list)}] 开始采集关键字:{key}')
  3381. try:
  3382. mt = MT(key) # 用当前关键字实例化
  3383. mt.main(device_id) # 执行一次完整采集
  3384. logging.info(f'关键字 {key} 本轮采集完成')
  3385. # if self.unrelated_data > 5:
  3386. # # # 连续超过5个不达标的数据则停止采集
  3387. # break
  3388. except Exception as e:
  3389. # 发生异常直接跳过该关键字,继续下一轮
  3390. logging.exception(f'关键字 {key} 采集异常:{e}')
  3391. finally:
  3392. # 关闭当前 MT 实例资源(如有需要)
  3393. if hasattr(mt, 'close'):
  3394. mt.close()
  3395. # logging.info('本轮全部关键字采集完成,等待 2 小时后下一轮...')
  3396. # time.sleep(1 * 3600) # 2 小时 = 7200 秒
  3397. # keys = '小柴胡颗粒' # 参苓健脾胃颗粒 舒肝颗粒 清肺化痰丸 香砂平胃颗粒 小柴胡颗粒
  3398. # mt = MT(keys) # 参苓健脾胃颗粒 舒肝颗粒 清肺化痰丸 香砂平胃颗粒
  3399. # # mt.main('95b2c764')
  3400. # mt.main('fcb3c749')
  3401. if __name__ == '__main__':
  3402. main()
  3403. # scheduler = BlockingScheduler()
  3404. # scheduler.add_job(main, 'cron', hour=21, minute=30, misfire_grace_time=120)
  3405. # try:
  3406. # scheduler.start()
  3407. # except (KeyboardInterrupt, SystemExit):
  3408. # pass