欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

python爬虫--【百度知道】自动答题

程序员文章站 2022-03-16 16:30:45
...
  • 做的第一个python爬虫类项目,刚开始学,如有错误,指出无妨

百度知道自动答题

功能

  • 访问百度知道,我们会看到有很多新的提问。
  • 其实很多提问已经有人做了解释或者网上可以找到现成的答案。
  • 因此,一方面,满足那些提问题的人的需要,另一方面,自己使用python练练手。
  • 项目的主要功能就是:对于百度知道里面的新问题,程序会在网页上去搜索,寻找最佳答案。如果有,则回答他;如果没有,那就跳过。

实现思路

  1. 百度知道上获取问题列表,得到的全部问题的地址链接,然后遍历访问这些链接,依次进入问题的详情页。
  2. 在问题详情页获取问题题目,题目是用于搜索相关的答案
  3. 搜索答案的地址链接都是固定的,只要替换地址中word后面的内容即可搜索相关的答案。
  4. 得到搜索结果后,获取答案列表的地址并遍历访问即可进入答案详情页,如果答案详情页里面有最佳答案就会获取答案内容,并且终止答案列表的遍历。
  5. 将得到的答案写回到问题详情页的回答文本框并单击提交回答按钮即可完成答题。
    注意:整个项目在实现过程中是用户已登录的情况下去执行的,百度最近的登录验证是滑动使图片变正,目前我还没有搞完它,因此获取cookie,登录的内容是手动的。

具体实现步骤

  • 获取cookie,使用cookie登录的内容
from selenium import webdriver
import json,time

driver = webdriver.Chrome()
driver.get('https://baidu.com/')
driver.find_element_by_xpath('//*[@id="u1"]/a[7]').click()
time.sleep(2)
driver.find_element_by_xpath('//*[@id="TANGRAM__PSP_10__footerULoginBtn"]').click()
time.sleep(2)
driver.find_element_by_xpath('//*[@id="TANGRAM__PSP_10__userName"]').send_keys('XXX')
driver.find_element_by_xpath('//*[@id="TANGRAM__PSP_10__password"]').send_keys('XXXXX')
driver.find_element_by_xpath('//*[@id="TANGRAM__PSP_10__submit"]').click()
time.sleep(30)


cookies = driver.get_cookies()
f1 = open('cookie.txt','w')
f1.write(json.dumps(cookies))
f1.close()
  • 如上,XXXX分别是你自己的百度账号和密码。当运行这段程序时,会弹出一个页面。登录时百度会验证,或者是短信验证码或者是滑动滑块等等,这一步是手动操作,操作完之后,程序会自动保存你的账号和密码在浏览器上的cookie值。用于下次登录。
  • 得到用户的登录信息,接下来实现自动答题。整个答题过程一共涉及4个网页:百度知道问题列表页、百度知道问题详情页、答案搜索页和答案详情页。
  • 在问题列表页中,每条问题的HTML代码是由标签 < a> 生成,并且属性 class 的属性值为 title-link,如下图,因此 selenium 可以对属性 class 进行定位,获取全部问题所在的标签 < a>,遍历这些标签提取相应的链接地址。python爬虫--【百度知道】自动答题- 在新的窗口访问每条问题链接,这些链接会进入相应的问题详情页。在问题详情页中,首先判断问题是否已被抢答,如果尚未回答,程序根据题目去百度知道搜索相关的答案,在这些相关的答案中找到最佳答案,然后写入问题答案输入框里并单击“提交回答”按钮;如果问题已被回答,程序就关闭当前窗口,回到问题列表执行下一个问题。问题详情页的答案输入框和“提交回答”按钮的HTML代码如下图所示。python爬虫--【百度知道】自动答题- 回答问题的过程中涉及到两个新的网页:答案搜索页和答案详情页。答案搜索页是根据问题在新的窗口中搜索相关答案,每个答案的链接以标签< dt> 表示,该标签下含有标签 < a>。将selenium 定位到每个答案的的标签< a>,在获取 href 属性值,该属性值用于进入答案详情页。
  • 将答案详情页的链接在新的窗口里访问,每个答案详情页都不一定有最佳答案,根据分析可知,最佳答案的class 属性值为 best-text mb-10,如果 selenium 能对属性 class 进行定位,则说明当前答案详情页有最佳答案,反之则无。
  • 根据上述的元素定位以及答题的业务逻辑,整个答题程序需要注意每个页面窗口之间的切换,如果窗口的切换逻辑不严谨,很容易导致程序出错。此外还需要考虑一些异常的情况出现,比如问题搜不到答案、问题已被回答以及网络延时响应等一些特殊情况。综合分析,自动答题的代码如下:
from selenium import webdriver
import json,time

url = 'https://zhidao.baidu.com/list?cid=110'
driver = webdriver.Chrome()
driver.get(url)
# 使用cookie 登录
driver.delete_all_cookies()
f1 = open('cookie.txt')
cookie = json.loads(f1.read())
f1.close()
for c in cookie:
    driver.add_cookie(c)
driver.refresh()

title_link = driver.find_elements_by_class_name('title-link')
print(title_link)
time.sleep(5)
for i in title_link:
    # 打开问题详情页并切换窗口
    driver.switch_to.window(driver.window_handles[0])
    href = i.get_attribute('href')
    driver.execute_script('window.open("%s");' % (href))
    time.sleep(5)
    driver.switch_to.window(driver.window_handles[1])
    try:
        # 查找iframe,判断问题是否已被回答
        driver.find_element_by_id('ueditor_0')
        # 获取问题题目并搜索答案
        title = driver.find_element_by_class_name('ask-title ').text
        title_url = 'https://zhidao.baidu.com/search?&word=' + title
        js = 'window.open("%s");' % (title_url)
        driver.execute_script(js)
        time.sleep(5)
        driver.switch_to.window(driver.window_handles[2])
        # 获取答案列表
        answer_list = driver.find_elements_by_class_name('dt,mb-4,line')
        for k in answer_list:
            # 打开答案详情页
            href = k.find_element_by_tag_name('a').get_attribute('href')
            driver.execute_script('window.open("%s");' % (href))
            time.sleep(5)
            driver.switch_to.window(driver.window_handles[3])
            # 获取最佳答案
            try:
                text = driver.find_element_by_class_name('best-text,mb-10').text
            except:
                text = ''
            finally:
                # 关闭答案详情页的窗口
                driver.close()
            # 答案不为空
            if text:
                # 关闭答案列表页的窗口
                driver.switch_to.window(driver.window_handles[2])
                driver.close()
                # 将答案写在问题回答文本框上并提交答案按钮
                driver.switch_to.window(driver.window_handles[1])
                driver.switch_to.frame('ueditor_0')
                driver.find_element_by_xpath('/html/body').click()
                driver.find_element_by_xpath('/html/body').send_keys(text)
                # 跳回到网页的HTML
                driver.switch_to.default_content()
                # 单机提交回答按钮
                driver.find_element_by_xpath('//*[@id="answer-editor"]/div[2]/a').click()
                time.sleep(5)
                # 关闭问题详情页的窗口
                driver.switch_to.window(driver.window_handles[1])
                driver.close()
                break
    except  Exception as err:
        # 除了问题列表页,关闭其他窗口
        all_handles = driver.window_handles
        for i, v in enumerate(all_handles):
            if i != 0:
                driver.switch_to.window(v)
                driver.close()
        driver.switch_to.window(driver.window_handles[0])
        print(err)

  • 项目的githup地址:https://github.com/zhangyi-13572252156/Baidu-Knows-Automatic-answer/tree/master
  • 如果需要交流,欢迎交流。QQ:1251108673
相关标签: 项目