Python3 - 搜索百度關(guān)鍵詞 - 識別廣告

背景

  • 目的:通過百度搜索指定關(guān)鍵詞蜻底,然后抓取前三頁網(wǎng)頁的廣告

技術(shù)棧小結(jié)

time

import time
now = lambda : time.perf_counter()
# 暫停5s
time.sleep(5)
>>> time.time()  # 時間戳
1613220602.8661115

>>> time.localtime()  # 本地時間
time.struct_time(tm_year=2021, tm_mon=2, tm_mday=13, tm_hour=20, tm_min=49, tm_sec=57, tm_wday=5, tm_yday=44, tm_isdst=0)

>>> time.asctime(time.localtime())  # 獲取格式化時間
'Sat Feb 13 20:35:31 2021'

>>> time.asctime(time.localtime(time.time()))
'Sat Feb 13 20:58:19 2021'

>>> time.strftime('%Y%m%d', time.localtime())  # 格式化時間
'20210213'
>>> 

os

# 文件/目錄方法
>>> import os
>>> os.getcwd()  # 當(dāng)前工作文件夾

>>> os.chdir(path)  # 修改當(dāng)前工作文件目錄為path
>>> os.listdir(path)  # 返加指定路徑下path中的文件夾及文件名稱
>>> os.mkdir(path)  # 新建文件夾
>>> os.rmdir(path)  # 刪除空文件夾  -- 文件夾非空 OSError
>>> os.remove(path)  # 刪除文件
>>> os.rename(oldName, newName)  # 修改文件名
>>> os.stat()  # 獲取指定路徑的信息

# os.stat()
# st_atime 上次訪問時間莲趣;st_mtime 最近修改時間; st_ctime 創(chuàng)建時間
>>> os.stat(os.getcwd())
os.stat_result(st_mode=16749, st_ino=1688849860301781, st_dev=3370681046, st_nlink=1, st_uid=0, st_gid=0, st_size=61440, st_atime=1613227168, st_mtime=1613227168, st_ctime=1523514771)

>>> os.stat(os.getcwd()).st_ctime
1523514771.5762281

os.path模塊

import os
# 獲取文件的屬性信息

os.path.abspath(path)  # 返回絕對路徑
os.path.dirname(path)  # 返回文件路徑
os.path.basename(path)  # 返回文件名
os.path.exists(path)  # 判定文件路徑是否存在,是True卷中,否False
os.path.expanduser('~')  # 返回用戶目錄
>>> os.path.expanduser('~tt')  # 將用戶目錄換為用戶(tt)目錄
'C:\\Users\\tt'

>>> os.path.getmtime(r't.py')  # 返回最近修改時間
1612868196.803879

>>> os.path.getsize(r't.py')  # 返回文件大小
1862

os.path.isabs(path)  # 判定是否為絕對路徑

os.path.isfile(path)  # 判定是否文件

os.path.isdir(path)  # 判定是否為目錄

>>> os.path.join(os.getcwd(),'t', 'a','c')  # 將目錄尊残、文件夾仅淑、文件合并為路徑
'c:\\users\\chen.huaiyu\\desktop\\t\\a\\c'

>>> os.path.split(os.path.join(os.path.expanduser('~tt'),r't.py'))  # 將路徑分割為dirname & basename,返回元組
('C:\\Users\\tt', 't.py')

>>> os.path.splitext(os.path.join(os.path.expanduser('~tt'),r't.py'))   # 分割為路徑名 & 文件拓展名
('C:\\Users\\tt\\t', '.py')
>>> os.path.splitext(r't.py')
('t', '.py')

logging

  • logging模塊的日志級別:1 -> 5依次升高藐翎。
    1.DEBUG 問題診斷;
    2.INFO 關(guān)鍵節(jié)點信息,檢查程序是否按預(yù)期運行吝镣;
    3 WARNING 不期望的事情發(fā)生堤器;
    4.ERROR 嚴(yán)重的問題發(fā)生,導(dǎo)致某些功能不能正常使用末贾;
    5.CRITICAL 嚴(yán)重錯誤闸溃,導(dǎo)致程序無法正常動行。

  • logging四大組件:
    1.Loggers拱撵,提供日志使用接口辉川;
    2.Handles,將日志發(fā)送到指定位置拴测;
    3.Filters乓旗,過濾日志,決定哪些日志將會被記錄昼扛;
    4.Formatters寸齐,控制日志輸出格式

  • logging模塊的使用方式:
    1.使用logging提供的模塊級別的函數(shù);

# logging.info(msg, *args)
logging.info('%s is %d years old', 'Tom', 10)

# exc_info:True - 將異常信息添加到日志中
# stack_info:默認(rèn)False抄谐,True - 棧信息將被添加到日志中
# extra: dict參數(shù)渺鹦,自定義消息格式中的字段
>>> import logging
>>> LOG_FORMAT = '%(asctime)s - %(levelname)s - %(user)s[%(ip)s] - %(message)s'
>>> DATE_FORMAT = '%m/%d/%Y %H:%M:%S %p'
>>> logging.basicConfig(format=LOG_FORMAT, datefmt=DATE_FORMAT)
>>> logging.warning('Some one delete the log file.', exc_info=True, stack_info=True, extra={'user':'Tom', 'ip':'10.10.10.10'})
            
02/14/2021 21:11:43 PM - WARNING - Tom[10.10.10.10] - Some one delete the log file.
NoneType: None
Stack (most recent call last):
  File "<string>", line 1, in <module>
  File "D:\...\lib\idlelib\run.py", line 144, in main
    ret = method(*args, **kwargs)
  File "D:\...\lib\idlelib\run.py", line 474, in runcode
    exec(code, self.locals)
  File "<pyshell#70>", line 1, in <module>

2.使用Logging日志系統(tǒng)的四大組件:日志器、處理器蛹含、過濾器毅厚、格式器。
1)日志器(logger)需要處理器(handler)將日志輸出浦箱;
2)一個logger可以有多個handler吸耿;
3)不同處理器(handler)可以將日志輸出到不同位置;
4)每個handler可以有多個過濾器(filter)酷窥;
5)每個處理器可以設(shè)置自己的格式器(formatter)咽安。
3.logging日志處理流程
1)日志器等級過濾;
2)日志器的過濾器過濾蓬推;
3)日志器的處理器的等級過濾妆棒;
4)日志器的處理器的過濾器過濾。
4.配置logging的幾種方式
1)顯式創(chuàng)建loggers沸伏;
2)使用日志配置文件糕珊,使用fileConfig()讀取文件內(nèi)容;
3)創(chuàng)建包含配置信息的dict毅糟,然后傳遞給dictConfig()红选。

# 讀取日志配置文件
logging.config.fileConfig('logging.conf')

# 創(chuàng)建一個日志器
logger = logging.getLogger('simpleExample')

# 日志輸出
logger.debug('debug message')
logger.info('info message')
logger.warn('warn message')
logger.error('error message')
logger.critical('critical message')

#
# 配置文件 logging.conf 內(nèi)容如下:
[loggers]  # 日志器
keys=root,simpleExample

[handlers]  # 處理器
keys=fileHandler,consoleHandler

[formatters]  # 格式器
keys=simpleFormatter

[logger_root]
level=DEBUG
handlers=fileHandler

[logger_simpleExample]
level=DEBUG
handlers=consoleHandler
qualname=simpleExample  # 必須,表示在logger層級中的名字姆另,應(yīng)用代碼中通個這個得到logger
propagate=0  # 指定propagate為0喇肋,防止日志記錄向上層logger傳遞

[handler_consoleHandler]
class=StreamHandler  # * 將日志消息發(fā)送到輸出到Stream
args=(sys.stdout,)  # *
level=DEBUG
formatter=simpleFormatter

[handler_fileHandler]
class=FileHandler  # *坟乾,將日志消息發(fā)送到磁盤文件
args=('logger.log', 'a')  # *
level=ERROR
formatter=simpleFormatter

[formatter_simpleFormatter]
format=%(asctime)s - %(name)s - %(levelName)s - %(message)s
datefmt='%Y-%m-%d %H:%M:%S'

pandas

import pandas as pd
pd.DataFrame(data, columns=column)  # 新建DataFrame
pd.concat(df1, df2, axis=0, ignore_index=True)  # axis=0 按行合并
df.fillna('-', inplace=True)  # 空值填充為'-'
pd.read_csv(path, engine='python', encoding='GBK')  # 讀取csv;文件名為中文必須用參數(shù)engine='python'
# pd.read_csv(path, engine='python', encoding='utf-8-sig')  # utf-8-BOM
pd.read_excel(path)  # 讀取excel
df.merge(df_url, how='left', on='Notloc')  # 按Notloc左側(cè)合并
df.merge(result, how='left', left_on='廣告主', right_on='搜索詞')  # 按left_on & right_on合并
df.append(df1)  # 增加
df['URL'].apply(lambda x: urlparse(x).netloc)  # 調(diào)用函數(shù)lambda蝶防,獲取主域

selenium


# 示例1
from selenium import webdriver
from selenium.webdriver.common.keys import Keys

driver = webdriver.Chrome()  # 打開瀏覽器
driver.implicitly_wait(10)  ## 隱式等待糊渊,如查找不所需元素,等待10s慧脱,期間每0.5s自動檢查一次渺绒,如查找不到,報錯
driver.maximize_window()  # 瀏覽器最大化
driver.get('https://www.baidu.com')
elem = driver.find_element_by_name('wd')  # 定位搜索框
elem.clear()  # 清空搜索框
elem.send_keys('a')  # 輸入 a
elem.send_keys(Keys.RETURN)  # Enter
driver.close()  # 關(guān)閉瀏覽器

# 緩慢向下滾動到頁面底部
def scroll():
    ini_height, check_height = 0, 0
    while 1:
        driver.execute_script(
            'window.scrollTo({top:536 + %s, behivor:"smooth"})' 
            % check_height)
        time.sleep(0.5)
        check_height = driver.execute_script('return document.documentElement.scrollTop || window.pageYOffset || document.body.scrollTop;')
        if ini_height == check_height:
            break
        ini_height = check_height
        
# 異常類
from selenium.common.exceptions import NoSuchElementException, StaleElementReferenceException

# 定位元素: find_element_by_*
driver.find_element_by_name()
driver.fing_element_by_xpath(xpath)

# 用Selenium寫測試用例
# 摘
import unittest
from selenium import webdriver
from selenium.webdriver.common.keys import Keys

class PythonOrgSearch(unittest.TestCase):  # 聲明這是一個測試用例:TestCase

    def setUp(self):  # 初始化的一部分菱鸥,每個測試方法被執(zhí)行前都執(zhí)行一次
        self.driver = webdriver.Chrome()

    def test_search_in_python_org(self):  # 測試方法始終以test開頭
        driver = self.driver
        driver.get('https://www.baidu.com')
        self.assertIn('百度一下', driver.title)
        elem = driver.find_element_by_name('wd')
        elem.send_keys('Fergus')
        elem.send_keys(Keys.RETURN)
        assert 'No result found' not in driver.page_source

    def tearDown(self):  # 每個測試方法執(zhí)行后執(zhí)行宗兼,用來做清掃工作
        self.driver.close()
    
if __name__ == "__main__":
    unittest.main()
        
# driver.get 方法將會根據(jù)方法中給出的URL地址打開該網(wǎng)站。 WebDriver 會等待整個頁面加載完成(其實是等待”onload”事件執(zhí)行完畢)之后把控制權(quán)交給測試程序氮采。 如果你的頁面使用大量的AJAX技術(shù)來加載頁面殷绍,WebDriver可能不知道什么時候頁面已經(jīng)加載完成:

urlparse

# 獲取域名
'''parse.urlparse(scheme='https', netloc='www.cnblogs.com', path='/angelyan/', params='', query='', fragment='')
scheme:表示協(xié)議
netloc:域名
path:路徑
params:參數(shù)
query:查詢條件,一般都是get請求的url
fragment:錨點鹊漠,用于直接定位頁面的下拉位置主到,跳轉(zhuǎn)到網(wǎng)頁的指定位置
'''
from urllib import parse
url = "http://xx.xx.xx:8000/get_account.json?page_size=20&page_index=1&user_id=456"
parse.urlparse(url)
Out[33]: ParseResult(scheme='http', netloc='xx.xx.xx:8000', path='/get_account.json', params='', query='page_size=20&page_index=1&user_id=456', fragment='')

parse.urlparse(url).netloc
Out[34]: 'xx.xx.xx:8000'

其它

# 計數(shù)
from collections import Counter
dic = Counter()
for i in lis:
    dic[i] += 1
# 累加
from functools import reduce
all_str = reduce(lambda x,y: x+y, split_netloc)
# 篩選
filter(lambda x: x[1]<2 and len(x[0])>1, sorted(dic.items(), key=lambda kv:(kv[1], kv[0]), reverse=True)

代碼

# -*- coding: utf-8 -*-
"""
Created on Sat Jan  9 16:08:57 2021
@author: Fergus
"""
import os
import time
import logging.config
import pandas as pd
from selenium import webdriver
from urllib.parse import urlparse
from selenium.webdriver.common.keys import Keys
#from selenium.webdriver.chrome.options import Options
from selenium.common.exceptions import NoSuchElementException, StaleElementReferenceException

now = lambda : time.perf_counter()

# 日志
PATH = os.path.join(os.path.expanduser('~'), r'CheckAD.conf')
logging.config.fileConfig(PATH)
logger = logging.getLogger('CheckAD')

def scroll():
    # 滾
    ini_height, check_height = 0, 0
    while True:
        # 每次平滑滾動
        driver.execute_script(
                'window.scrollTo({top:536 + %s, behavior:"smooth"})' 
                % check_height)
        time.sleep(0.5)
        check_height = driver.execute_script(
                'return document.documentElement.scrollTop || \
                window.pageYOffset || document.body.scrollTop;')
        if ini_height == check_height:
            break
        ini_height = check_height

def search(keyword):
    try:
        # 定位搜索框
        elem = driver.find_element_by_name('wd')
    except NoSuchElementException:
        input('手動滑塊驗證、或F5刷新頁面后Enter')
        elem = driver.find_element_by_name('wd')
    finally:
        elem.clear()
        elem.send_keys(keyword)
        elem.send_keys(Keys.RETURN)
        time.sleep(0.3)

def parser(xpath):
    try:
        element = driver.find_element_by_xpath(xpath)
    except NoSuchElementException:
        return '1'
    except StaleElementReferenceException:
        logger.info('ERROR:\n', exc_info=True)
    except Exception as e:
        logger.info('parse: %s' % e)
    else:
        return element.text
    
def parsers(xpath):
    try:
        element = driver.find_elements_by_xpath(xpath)
    except NoSuchElementException:
        logger.info('ERROR:\n', exc_info=True)
    except StaleElementReferenceException:
        logger.info('ERROR:\n', exc_info=True)
    except Exception as e:
        logger.info('parsers: %s' % e, exc_info=True)
    else:
        return element

def getAd():
    # 廣告
    ## 標(biāo)題 & 標(biāo)題url
    ad = parsers('//h3/a[@data-is-main-url="true"]')
    ad_headline = [i.text for i in ad]
    ad_headline_url = [i.get_attribute('data-landurl') for i in ad]
    ## 顯式url
    lis = ['京公網(wǎng)安備11000002000001號', '京ICP證030173號', '展開', '']
    url = parsers('//div/div[2]/a/span[1] | //div/div[3]/a/span[1]')
    explicit_url = [i.text for i in url if i.text not in lis]
    return ad_headline, ad_headline_url, explicit_url

def getBrandAd():
    # 品牌廣告
    ## 標(biāo)題 & 標(biāo)題url
    brandad = parsers('//h2/a')
    brandad_headline = [i.text for i in brandad 
                        if '想在此推廣' not in i.text and i.text != '官方']
    brandad_headline_url = [i.get_attribute('ourl') for i in brandad 
                            if i.get_attribute('ourl') is not None]
    ## 顯式url
    url = parsers('//span[@class="ec-pc_brand_tip-official-site"]')
    explicit_brandurl = [i.text for i in url]
    return brandad_headline, brandad_headline_url, explicit_brandurl
    

def next_page():
    try:
        driver.find_element_by_partial_link_text('下一頁').click()
        time.sleep(0.5)
    except NoSuchElementException:
        logger.info('ERROR:\n', exc_info=True)
    except Exception as e:
        input('%s\n手動滑塊驗證躯概、或F5刷新頁面后Enter' % e)
        driver.find_element_by_partial_link_text('下一頁').click()
        time.sleep(0.5)
    finally:
        scroll()

def output(keyword):
    
    global result
    # 當(dāng)前頁
    cur_page = parser('//div[@id="page"]/div/strong/span[2]')
    
    # 標(biāo)題 & 標(biāo)題url & 顯式url
    ad_headline, ad_headline_url, explicit_url = getAd()
    brandad_headline, brandad_headline_url, explicit_brandurl = getBrandAd()
    
    # 輸出 - 廣告:搜索詞登钥、頁碼、廣告標(biāo)題 & 落地頁 & 顯式url
    try:
        rows = len(ad_headline)
        df1 = pd.DataFrame({'搜索詞': [keyword] * rows,
                           '廣告': ['廣告'] * rows,
                           '頁碼': [cur_page] * rows,
                           '標(biāo)題': ad_headline,
                           '落地頁': ad_headline_url,
                           '顯式url': explicit_url
                           })
        # 打標(biāo)識
        if not df1.shape[0]:
            df1 = df1.append(pd.DataFrame([[keyword, '廣告', cur_page, '', 
                                            '','']], columns=df1.columns))
        rows = len(brandad_headline)
        df2 = pd.DataFrame({'搜索詞': [keyword] * rows,
                            '廣告': ['品牌廣告'] * rows,
                            '頁碼': [cur_page] * rows,
                            '標(biāo)題': brandad_headline,
                            '落地頁': brandad_headline_url,
                            '顯式url': explicit_brandurl
                            })
        # 打標(biāo)識
        if not df2.shape[0]:
            df2 = df2.append(pd.DataFrame([[keyword, '品牌廣告', cur_page[0], 
                                            '', '', '']], columns=df1.columns))
        df = df1.append(df2)
        result = result.append(df)
        #print('\n', result, '\nRuntime: {:.3f}Min'.format((now() - st
        #                        )/60))
    except Exception as e:
        # 部分?jǐn)?shù)據(jù)抓取異常
        lis1 = []
        lis1.extend([keyword, '廣告', cur_page[0]])
        lis1.append(ad_headline)
        lis1.append(ad_headline_url)
        lis1.append(explicit_url)
        lis2 = []
        lis2.extend([keyword, '品牌廣告', cur_page[0]])
        lis2.append(brandad_headline)
        lis2.append(brandad_headline_url)
        lis2.append(explicit_brandurl)
        lis3 = []
        lis3.append(lis1)
        lis3.append(lis2)
        lis3.append(['異常: %s | %s' % (keyword, e)])
        err.append(lis3)
        #print(err)
        print('Runtime: {:.3f}Min'.format((now() - st)/60))
    
def connectDB():
    # 訪問DB
    from sqlalchemy import create_engine
    # sql server
    ss = 'mssql+pymssql://%s:%s@%s:%s/%s'
    try:
        engine = create_engine(ss % ('sa', 'cs_holly123', '192.168.60.110'
                                    , '1433', 'Account Management'))
    except Exception:
        raise
    else:
        logger.info('數(shù)據(jù)庫連接成功娶靡,讀取數(shù)據(jù)中...')
        return engine 
    
def getDB(deadline):
    with connectDB().begin() as conn:
        # 廣告主近半年有消費 and 廣告主近3天沒有消費
        sql = '''
SELECT *
 FROM ( SELECT 用戶名, AM, b.廣告主, 網(wǎng)站名稱, URL, ad_hy.[近半年消費(AD)]
     , D.近3天消費
  FROM basicInfo b
   LEFT JOIN (SELECT 廣告主, ISNULL(sum(HY.sum_),0) '近半年消費(AD)'
     FROM basicInfo b
      LEFT JOIN(SELECT 用戶名, sum(金額) sum_
        FROM 消費
        WHERE 日期 BETWEEN DATEADD(DD, -200, '20210121') AND '20210121'
         AND 類別 in ('搜索點擊', '新產(chǎn)品', '自主投放', '超投')
        GROUP BY 用戶名) HY
       ON HY.用戶名 = b.用戶名
     GROUP BY 廣告主) ad_hy
    ON b.廣告主 = ad_hy.廣告主
   LEFT JOIN ( SELECT 廣告主, ISNULL(sum(HY.sum_),0) '近3天消費'
     FROM basicInfo b
      LEFT JOIN(SELECT 用戶名, sum(金額) sum_
        FROM 消費
        WHERE 日期 BETWEEN DATEADD(DD, -3, '20210121') AND '20210121'
         AND 類別 in ('搜索點擊', '新產(chǎn)品', '自主投放', '超投')
        GROUP BY 用戶名) HY
       ON HY.用戶名 = b.用戶名
     GROUP BY 廣告主) D
    ON D.廣告主 = b.廣告主) T
 WHERE T.[近半年消費(AD)] > 0
  AND T.近3天消費 = 0
                '''.replace('{}', deadline)
        df = pd.DataFrame(conn.execute(sql).fetchall()
                , columns=['用戶名', 'AM', '廣告主', '網(wǎng)站名稱', 'URL'
                           , '近半年有消費(AD)', '近3日無消費(AD)'])
    return df

def getNetlocKeywords():
    # URL拆分: 核心url
    from functools import reduce
    from collections import Counter
    
    global df
    # 獲取域名
    df['Netloc'] = df['URL'].apply(lambda x: urlparse(x).netloc)
    netloc = list(set(df['Netloc']))
    # 截取域名中核心字段
    ## 先將url按'.'拆解牧牢,計數(shù),保留計次 <= 2的詞 & length > 1
    split_netloc = list(map(lambda x: x.split('.'), netloc))
    all_str = reduce(lambda x,y: x+y, split_netloc)
    ### 統(tǒng)計
    dic = Counter()
    for i in all_str:
        dic[i] = dic[i] + 1
    ### 篩選
    letters = filter(lambda x: x[1] <= 2 and len(x[0]) > 1, 
                     sorted(dic.items(), key=lambda kv: (kv[1], kv[0])
                     , reverse=True))
    keywords = [i[0] for i in letters]
    # url, keywords
    df_url = pd.DataFrame([[netloc[n], j] for n, i in enumerate(split_netloc
                                         ) for j in keywords if j in i]
                        , columns=['Netloc', 'Key'])
    # return
    df = df.merge(df_url, how='left', on='Netloc')

def exclude():
    # 排除關(guān)鍵詞
    input('Tips: 檢查桌面排除文件,確認(rèn)無誤Enter\n')
    path = r'c:\users\chen.huaiyu\desktop\excludeKeywords.csv'
    csv = pd.read_csv(path, engine='python', encoding='GBK')
    return set(csv['搜索詞'])

def fromExcel():
    # 1.讀取excel姿锭;2.分解關(guān)鍵詞塔鳍;3.分解前后一一對應(yīng);4.return
    from re import split
    from functools import reduce
    
    path = r'c:\users\chen.huaiyu\desktop\賬戶關(guān)鍵詞.xlsx'
    inputKeywords = pd.read_excel(path)
    inputKeywords.drop(columns=inputKeywords.columns[0], inplace=True)
    # 關(guān)鍵詞拆分
    keywords = list(set(reduce(lambda x,y: x+y, inputKeywords['關(guān)鍵詞'].apply(
                        lambda x: split(r',|呻此,', x)))))
    keywords.remove('物料已刪除')
    keywords.remove('')
    # 匹配關(guān)鍵詞 & 廣告主
    adAndKeyword = [(inputKeywords['廣告主'][n], j) for n, i in enumerate(
                    inputKeywords['關(guān)鍵詞'].apply(lambda x: split(r',|轮纫,',x)))
                for j in keywords if j in i]
    df = pd.DataFrame(adAndKeyword, columns=['廣告主', '搜索關(guān)鍵詞'])
    df = inputKeywords.merge(df, on='廣告主', how='left')
    df.fillna('-', inplace=True)
    df = df.loc[df.apply(lambda x: x['搜索關(guān)鍵詞'] in x['關(guān)鍵詞'], axis=1), :]
    return keywords, df
    
def getKeywords():
    #
    if choice == 'from DB':
        getNetlocKeywords()
        search_words = list(set(df['網(wǎng)站名稱']) | set(df['廣告主']
                        ) | set(df['Key']) - exclude())
    elif choice == 'from Excel':
        search_words, _ = fromExcel()
    return search_words

def combine():
    if choice == 'from DB':
        # 合并查詢結(jié)果,輸出
        df_ad = df.merge(result, how='left', left_on='廣告主', right_on='搜索詞')
        df_website = df.merge(result, how='left', left_on='網(wǎng)站名稱'
                              , right_on='搜索詞')
        df_url = df.merge(result, how='left', left_on='Key', right_on='搜索詞')
        merge = pd.concat((df_ad, df_website, df_url), axis=0, ignore_index=True)
        merge.fillna('-', inplace=True)
        #
        # 篩選準(zhǔn)備
        #
        ## 獲取落地頁netloc
        merge['landurl_netloc'] = merge['落地頁'].apply(
                                                lambda x: urlparse(x).netloc)
        ## 顯式url == 開戶url Netloc
        merge['filter1'] = merge['Netloc'] == merge['顯式url']
        ## 開戶url核心詞 in 顯式url
        merge['filter2'] = merge.apply(
                            lambda x: x['Key'] in x['顯式url'], axis=1)
        ## Key in land_netloc
        merge['filter3'] = merge.apply(
                        lambda x: x['Key'] in x['landurl_netloc'], axis=1)
        merge.to_excel(r'c:/users/chen.huaiyu/desktop/CheckAD.xlsx')
    elif choice == 'from Excel':
        _, DF = fromExcel()
        merge = DF.merge(result, how='left', left_on='搜索關(guān)鍵詞'
                         , right_on='搜索詞')
        merge.to_excel(r'c:/users/chen.huaiyu/desktop/CheckADKey.xlsx')
        
    # 異常記錄
    er = pd.DataFrame(err, columns=['搜索詞', '廣告', 'Note'])
    er.to_excel(r'c:/users/chen.huaiyu/desktop/error.xlsx')
    # 
    kw = pd.DataFrame(keywords)
    kw.to_csv(r'c:/users/chen.huaiyu/desktop/kw.csv', encoding='GBK')
    

if __name__ == '__main__':
    
    st = now()
    # 設(shè)定截止日期
    DL = input('設(shè)置截止日期焚鲜,eg.20210121\n')
    choice = input('關(guān)鍵詞從哪里來掌唾?(from DB/from Excel)')
    logger.info('\nStart,設(shè)置截止日期為:%s\n' % DL)
    # 讀取數(shù)據(jù)庫
    df = getDB(DL)
    # output
    result = pd.DataFrame()
    err = []
    # 搜索詞
    keywords = getKeywords()
    # 運行瀏覽器開始搜索
    #chrome_options = Options()
    #chrome_options.add_argument('--headless')  # 不顯示瀏覽器
    #chrome_options.add_argument('--disable-gpu')  # 不加載圖片
    driver = webdriver.Chrome()
    driver.implicitly_wait(10)
    driver.maximize_window()
    driver.get('https://www.baidu.com')
    for n, keyword in enumerate(keywords):
        try:
            # 搜索
            search(keyword)
            scroll()
            output(keyword)
            # 只需檢查前3頁
            for i in range(2):
                next_page()
                output(keyword)
            # 輸出提示
            logger.info('{}\n共{}個,第{}個恃泪,完成{:.0%},預(yù)計耗時{:.1f}min...'.format(
                time.ctime(), len(keywords), n, n/len(keywords)
                , ((now() - st)/n*(len(keywords)-n))/60))
        except KeyboardInterrupt as e:
            print(e)
            break
        except Exception as e:
            logger.info(e, exc_info=True)
            continue
    # 完成后將結(jié)果合并輸出
    combine()
    driver.quit()
    
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末郑兴,一起剝皮案震驚了整個濱河市犀斋,隨后出現(xiàn)的幾起案子贝乎,更是在濱河造成了極大的恐慌,老刑警劉巖叽粹,帶你破解...
    沈念sama閱讀 216,744評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件览效,死亡現(xiàn)場離奇詭異却舀,居然都是意外死亡,警方通過查閱死者的電腦和手機锤灿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,505評論 3 392
  • 文/潘曉璐 我一進店門挽拔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人但校,你說我怎么就攤上這事螃诅。” “怎么了状囱?”我有些...
    開封第一講書人閱讀 163,105評論 0 353
  • 文/不壞的土叔 我叫張陵术裸,是天一觀的道長。 經(jīng)常有香客問我亭枷,道長袭艺,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,242評論 1 292
  • 正文 為了忘掉前任叨粘,我火速辦了婚禮猾编,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘升敲。我一直安慰自己答倡,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,269評論 6 389
  • 文/花漫 我一把揭開白布驴党。 她就那樣靜靜地躺著苇羡,像睡著了一般。 火紅的嫁衣襯著肌膚如雪鼻弧。 梳的紋絲不亂的頭發(fā)上设江,一...
    開封第一講書人閱讀 51,215評論 1 299
  • 那天,我揣著相機與錄音攘轩,去河邊找鬼叉存。 笑死,一個胖子當(dāng)著我的面吹牛度帮,可吹牛的內(nèi)容都是我干的歼捏。 我是一名探鬼主播,決...
    沈念sama閱讀 40,096評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼笨篷,長吁一口氣:“原來是場噩夢啊……” “哼瞳秽!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起率翅,我...
    開封第一講書人閱讀 38,939評論 0 274
  • 序言:老撾萬榮一對情侶失蹤练俐,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后冕臭,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體腺晾,經(jīng)...
    沈念sama閱讀 45,354評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡燕锥,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,573評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了悯蝉。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片归形。...
    茶點故事閱讀 39,745評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖鼻由,靈堂內(nèi)的尸體忽然破棺而出暇榴,到底是詐尸還是另有隱情,我是刑警寧澤蕉世,帶...
    沈念sama閱讀 35,448評論 5 344
  • 正文 年R本政府宣布跺撼,位于F島的核電站,受9級特大地震影響讨彼,放射性物質(zhì)發(fā)生泄漏歉井。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,048評論 3 327
  • 文/蒙蒙 一哈误、第九天 我趴在偏房一處隱蔽的房頂上張望哩至。 院中可真熱鬧,春花似錦蜜自、人聲如沸菩貌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,683評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽箭阶。三九已至,卻和暖如春戈鲁,著一層夾襖步出監(jiān)牢的瞬間仇参,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,838評論 1 269
  • 我被黑心中介騙來泰國打工婆殿, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留诈乒,地道東北人。 一個月前我還...
    沈念sama閱讀 47,776評論 2 369
  • 正文 我出身青樓婆芦,卻偏偏與公主長得像怕磨,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子消约,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,652評論 2 354

推薦閱讀更多精彩內(nèi)容