1、建立一个函数,用来创建浏览器驱动
代码语言:javascript复制def createDriver():
"""
每次关闭Chromedriver后,重新创建一个
:return:
"""
# 创建driver,并指定Chromedriver的路径
current_dir = os.path.abspath('.')
chromedriverPath = os.path.join(current_dir, 'chromedriver')
browser = webdriver.Chrome(executable_path=chromedriverPath)
return browser
2、启动浏览器,在主函数中完成所有功能的调用
(1)搜索链接 关键字拼接成URL
(2)切换到"百度知道"结果列表页
(3)在搜索结果中遍历,列表页进入详情页,如果结果详情页中存在百度网盘分享链接,考察分享链接是否已经失效
代码语言:javascript复制def getInfo(file_name, keyword):
key_wd = {'wd': keyword}
# URL encode
target_url = Format_str urllib.parse.urlencode(key_wd)
# 启动浏览器
browser = createDriver()
browser.get(target_url)
sleep(2)
#切换到百度知道tab
#//*[@id="s_tab"]/div/a[4]
browser.find_element_by_xpath('//*[@id="s_tab"]/div/a[4]').click()
sleep(2)
# 搜索结果链接,第一个基本上就是百度知道的结果,所有只取第一页10条,如果搜不到直接放弃空字符
for index in range(1, 11):
# 获取详情页xpath
prefix_xpath = '//*[@id="wgt-list"]/dl[' str(index) ']'
# 判断该条搜索结果是否为百度知道
isBaiduKown(file_name=file_name, browser=browser, prefix=prefix_xpath)
# 关闭浏览器
browser.quit()
3、在结果详情页中搜索结果
(1)确认回答总条数,以及页数
(2)当前页只展示2条回答结果,需要判断是否打开折叠/展开按钮
(3)最佳答案和普通答案的class_name不同,需要单独做处理
(4)答案的Xpath中包含了用户的标识ID,所以使用class_name来定位元素
代码语言:javascript复制def getResultDetail(file_name, browser):
"""
:param browser: 浏览器
:return: 文件百度网盘地址详情
"""
# 回答总个数统计
answer_number_text = browser.find_element_by_xpath('//*[@id="qb-content"]/div[2]/span[2]').get_attribute(
'innerHTML')
answer_number = answer_number_text.split('个')[0]
# 当答案大于2个时,答案列表会折叠
if int(answer_number) > 2:
# 更多按钮
more_button_xpath = '//*[@id="show-answer-hide"]'
if isElementExist(by=By.XPATH,value=more_button_xpath,driver=browser) == True:
# 若存在更多按钮,先按展开所有答案
browser.find_element_by_xpath(more_button_xpath).click()
# 更多折叠按钮
more_hide_xpath = '//*[@id="wgt-answers"]/div/div[6]/div'
if isElementExist(by=By.CLASS_NAME,value='pager-next',driver=browser) == True and int(answer_number) > 5:
if browser.find_element_by_class_name('pager-next').is_displayed() == False:
browser.find_element_by_xpath(more_hide_xpath).click()
else:
browser.find_element_by_xpath('//*[@id="wgt-answers"]/div/div[5]/div').click()
# 每页5个答案
page_num = int(answer_number) // 5 1
for page_index in range(1, page_num):
# 获取答案详情,并判断是否有网盘下载链接
# 最佳答案
if page_index == 1:
best_answer = browser.find_element_by_class_name('best-text.mb-10').text
if downloadLinkObserve(file_name=file_name, detail_text=best_answer, browser=browser) == True:
browser.quit()
break
# 普通答案
nomal_answers_elements = browser.find_elements_by_class_name('answer-text.mb-10.line')
for nomal_element in nomal_answers_elements:
answer_text = nomal_element.text
if downloadLinkObserve(file_name=file_name, detail_text=answer_text, browser=browser) == True:
browser.quit()
break
# 如果有下一页,在未获取到下载链接的情况下,跳转到下一页继续
if page_index < page_num and int(answer_number) > 5:
browser.find_element_by_class_name('pager-next').click()
# 切换到上一页的列表
switchWindow(browser=browser, windows_signal='current')
4、提取答案文本中的分享链接
代码语言:javascript复制def findUrl(string):
"""
提取符串中URL链接
:param string:
:return:
"""
# findall() 查找匹配正则表达式的字符串
import re
url = "https:" re.match(r"[^/] (/[^ ]*)", string).group(1)
return url
5、结果存储
(1)将分享下载链接和提取码(如果有)分离出来,以字典的形式存储
(2)封装数据库方法,直接调用
代码语言:javascript复制def downloadLinkObserve(file_name, detail_text, browser):
"""
检查回答中是否有百度网盘下载链接,如果有,再检查该链接分享是否已经失效
:param detail_text:
:param browser:
:return:
"""
if 'pan.baidu.com/s' in detail_text:
download_url = findUrl(detail_text)
download_code = ''
if ("提取码" in detail_text):
download_code = detail_text.split("提取码")[1]
if (requestIsValid(url=download_url, browser=browser)) == True:
file_link = {'download': download_url, 'code': download_code}
# 更新数据库数据
data.dbDeal.update_result(fileLink=str(file_link), fileName=file_name)
return True
else:
return False