extract_and_save.py 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. from playwright.sync_api import sync_playwright
  2. import sqlite3
  3. import smtplib
  4. from email.mime.text import MIMEText
  5. from email.header import Header
  6. import random
  7. import logging
  8. import time
  9. from logging.handlers import TimedRotatingFileHandler
  10. # # 创建一个选品logger
  11. # logger = logging.getLogger('detailLogger')
  12. # logger.setLevel(logging.DEBUG) # 设置日志级别
  13. # # 创建一个handler,用于写入文件,并根据时间自动轮换日志文件
  14. # detail_handler = TimedRotatingFileHandler('日志log/日志.txt', when='midnight', interval=1, backupCount=30,encoding='utf-8')
  15. # detail_handler.setFormatter(logging.Formatter('%(asctime)s - %(message)s'))
  16. # # 添加handler到logger
  17. # logger.addHandler(detail_handler)
  18. # 配置日志记录器
  19. logger_cmd1 = logging.getLogger('logger_cmd1')
  20. logger_cmd1.setLevel(logging.DEBUG)
  21. # 配置控制台处理器和格式器
  22. console_handler = logging.StreamHandler()
  23. console_handler.setLevel(logging.DEBUG)
  24. formatter = logging.Formatter('[%(asctime)s] %(message)s')
  25. console_handler.setFormatter(formatter)
  26. # 将处理器添加到记录器中
  27. logger_cmd1.addHandler(console_handler)
  28. def run(session='', sender_email='', receiver_email='', smtp_proxy='', smtp_account='', smtp_password='', email_alias='', error_count=3,you_scan_interval=30,logger=''):
  29. # 初始化数据
  30. count = 0
  31. try:
  32. with sync_playwright() as playwright:
  33. browser = playwright.chromium.launch(headless=True)
  34. context = browser.new_context()
  35. page = context.new_page()
  36. # 添加session cookie
  37. cookies = [
  38. {
  39. 'name': 'session',
  40. 'value': session, # 替换为实际的session值
  41. 'domain': 'buff.163.com',
  42. 'path': '/',
  43. }
  44. ]
  45. context.add_cookies(cookies)
  46. # 商品池子
  47. # goods_info = [776831, 911801, 42234, 33887, 781577, 968110, 968048, 968047, 968046, 968045, 968044, 968043, 968042, 968041, 968040, 968039, 968038, 968037, 968036, 968035, 968034, 968033, 968032, 968031, 968030, 968029, 968028, 968027, 968026, 968025, 968024, 968023, 968022, 968021, 968020, 968019, 968018, ]
  48. goods_info = [968020]
  49. # 从goods_info随机获取一个值
  50. random_number = random.choice(goods_info)
  51. # Step 1: Visit the initial URL
  52. page.goto(f"https://buff.163.com/goods/{random_number}?from=market#tab=selling")
  53. # Step 2: Click the "无法扫描二维码" button
  54. # 等待page加载完毕
  55. page.wait_for_load_state('networkidle')
  56. page.wait_for_function('''() => {
  57. return document.readyState === 'complete'
  58. }''')
  59. # logger.info(f"点击无法扫描二维码按钮-是否存在(0:不存在,1:存在): {page.locator('span.yidun_smsbox-text--manual').count()}")
  60. if page.locator('span.yidun_smsbox-text--manual').count() <= 0 :
  61. logger.info("清空表sms_codes")
  62. conn = sqlite3.connect('settings.db')
  63. cursor = conn.cursor()
  64. cursor.execute('''CREATE TABLE IF NOT EXISTS sms_codes (edit_content TEXT, send_content_short TEXT)''')
  65. cursor.execute('delete from sms_codes')
  66. conn.commit()
  67. conn.close()
  68. # Close the browser
  69. context.close()
  70. browser.close()
  71. logger.info("未监测到短信数据")
  72. return 'success'
  73. page.click('span.yidun_smsbox-text--manual')
  74. # Step 3: Wait for navigation to the new page
  75. page.wait_for_load_state('networkidle')
  76. page.wait_for_function('''() => {
  77. return document.readyState === 'complete'
  78. }''')
  79. # Step 4: Extract the required content
  80. edit_content = page.inner_text('span.yidun_smsbox-manual--edit-content')
  81. send_content_short = page.inner_text('span.yidun_smsbox-manual--send-content__short')
  82. # Step 5: Save to SQLite database
  83. conn = sqlite3.connect('settings.db')
  84. cursor = conn.cursor()
  85. cursor.execute('''CREATE TABLE IF NOT EXISTS sms_codes (edit_content TEXT, send_content_short TEXT)''')
  86. cursor.execute('''INSERT INTO sms_codes (edit_content, send_content_short) VALUES (?, ?)''', (edit_content, send_content_short))
  87. conn.commit()
  88. # 判断sms_codes表中的数据量是否大于3
  89. cursor.execute('''SELECT COUNT(*) FROM sms_codes''')
  90. # 获取执行结果
  91. count = cursor.fetchone()[0]
  92. conn.close()
  93. logger.info(f'count >= int(error_count) + 1 :{count >= int(error_count) + 1}')
  94. if count >= int(error_count) + 1:
  95. logger.info(f'达到异常关闭条件,连续异常次数:{count},指标为:{error_count},返回True,结束程序')
  96. return 'stop'
  97. else:
  98. pass
  99. logger_cmd1.info(f'需要短信验证,次数{int(count)}!')
  100. logger_cmd1.info(f'发送{edit_content}到{send_content_short},等待{float(you_scan_interval)}秒!')
  101. logger.info(f'短信发送到: {send_content_short},短信内容: {edit_content}')
  102. # 发件人邮箱账号
  103. sender = sender_email
  104. # 收件人邮箱账号,可以是多个
  105. receivers = receiver_email
  106. # 邮件正文内容
  107. message = MIMEText(f'编辑短信{edit_content}', 'plain', 'utf-8')
  108. # 邮件主题
  109. message['Subject'] = Header(f'{email_alias}编辑短信{edit_content}', 'utf-8')
  110. # 发件人和收件人
  111. message['From'] = sender_email
  112. message['To'] = receiver_email
  113. try:
  114. # 初始化 smtpObj 为 None
  115. smtpObj = None
  116. # 连接到SMTP服务器,使用SSL连接(端口465)或TLS连接(端口587)
  117. smtpObj = smtplib.SMTP_SSL(smtp_proxy, 465) # 使用SSL连接示例
  118. # smtpObj = smtplib.SMTP("smtp.126.com", 587) # 使用TLS连接示例,需要先调用smtpObj.starttls()
  119. # smtpObj.starttls() # 如果使用TLS连接,取消注释这行并注释上一行中的SSL连接部分
  120. # 登录SMTP服务器
  121. logger.info("SMTP sender:{sender} smtp_password:{smtp_password}")
  122. smtpObj.login(sender, smtp_password) # 注意:出于安全考虑,建议使用应用专用密码而非你的邮箱密码
  123. logger.info("SMTP 登录成功,sender:{sender} smtp_password:{smtp_password}")
  124. # 发送邮件
  125. smtpObj.sendmail(sender, receivers, message.as_string())
  126. logger.info("邮件发送成功")
  127. except smtplib.SMTPAuthenticationError as e:
  128. logger.error(f"SMTP 认证失败: {e}")
  129. except smtplib.SMTPException as e:
  130. logger.info("Error: 无法发送邮件", e)
  131. finally:
  132. # 检查 smtpObj 是否被成功创建
  133. if smtpObj is not None:
  134. smtpObj.quit()
  135. # wait_times = 0
  136. # 监测span.yidun_smsbox-manual--edit-content元素,如果元素消失了才能关闭浏览器,超过了3分钟自动关闭
  137. # while page.locator('span.yidun_smsbox-manual--edit-content').count() > 0 and wait_times < 180:
  138. # logger.info(f"等待系统验证通过中........,已等待{wait_times}秒")
  139. # wait_times += 1
  140. # time.sleep(1)
  141. # if page.locator('span.yidun_smsbox-manual--edit-content').count() <= 0:
  142. # logger.info(f"系统验证通过")
  143. # if wait_times >= 180:
  144. # logger.info(f"等待系统验证通过超时")
  145. logger.info(f'等待短信验证,等待{float(you_scan_interval)}秒')
  146. time.sleep(float(you_scan_interval))
  147. # Close the browser
  148. context.close()
  149. browser.close()
  150. logger.info(f'未达到异常关闭条件,,连续异常次数:{count},指标为:{error_count} 返回 error not stop')
  151. return 'error not stop'
  152. except Exception as e:
  153. logger.info(f"未监测到短信数据: {e}")
  154. return 'error not stop1'
  155. finally:
  156. pass
  157. # 如果count大于等于三,则返回'stop'
  158. # if count >= int(error_count):
  159. # logger.info(f'达到异常关闭条件,连续异常次数:{count},指标为:{error_count},返回True,结束程序')
  160. # return True
  161. # else:
  162. # # logger.info(f'未达到异常关闭条件,,连续异常次数:{count},指标为:{error_count} 返回False')
  163. # return False
  164. if __name__ == "__main__":
  165. result = run(
  166. session='session',
  167. sender_email='sender_email',
  168. receiver_email='receiver_email',
  169. smtp_proxy='smtp_proxy',
  170. smtp_account='smtp_account',
  171. smtp_password='smtp_password',
  172. email_alias='email_alias',
  173. error_count='3',
  174. you_scan_interval='20'
  175. )
  176. # logger.info(result)