如果没有百度账号,需要使用手机号注册,建议使用小号,百度的产品指不定就封号。完成用户注册之后,我们进入百度答题网页,该网页是显示某个分类的问题列表,每条问题代表一条连接,单击即可进入问题详情页。
在问题详情页,我们需要根据题目搜索正确答案,然后将答案写到问题详情页的回答文本框里,最后单击提交回答按钮即可实现答题。首先获取问题详情页的题目,然后根据题目搜索答案,在答案列表页中逐一访问每个答案的链接,在答案详情页中获取合理的答案,最后将答案写回到问题详情页中。
整个项目可以分为5个步骤来实现,每个步骤具体说明如下:
(1)在https://zhidao.baidu.com/list?cid=110上获取问题列表,得到全部问题的地址链接,然后遍历访问这些链接,依次进入问题的详情页。
(2)在问题详情页获取问题题目,题目是用于搜索相关的答案。
(3)搜索答案的地址链接都是固定的,只要替换地址中wd后面的内容即可搜索相关的答案。
(4)得到搜索结果后,获取答案列表的地址并遍历访问即可进入答案详情页,如果答案详情页里面有最佳答案就会获取答案内容,并且终止答案列表的遍历。
(5)将得到的答案写回到问题详情页的回答文本框并单击提交回答按钮即可完成答题。
整个项目在实现过程中是在用户已登录的情况下执行,如果使用百度的账号密码去执行用户登录,就会遇到手机验证码或图片验证码。用户登录后,网站会一直保持用户的登录状态,不管用户是否重启浏览器,只要访问百度网址,用户登录信息就会显示出来。利用用户登录的状态,Selenium可以模拟用户登录并将用户登录后的Cookies保存下来,在下次登录的时候,直接读取并操控Cookies即可完成用户登录。功能代码如下:
from selenium import webdriver
import time, json,re
from urllib.parse import quote
def get_cookies():
# 百度登录用户并保存Cookies
driver=webdriver.Chrome()
driver.get('https://www.baidu.com/')
driver.find_element_by_xpath('//*[@id="u1"]/a[2]').click()
time.sleep(3)
driver.find_element_by_id('TANGRAM__PSP_11__footerULoginBtn').click()
time.sleep(3)
# 设置用户名和密码
driver.find_element_by_id('TANGRAM__PSP_11__userName').send_keys('用户名')
driver.find_element_by_id('TANGRAM__PSP_11__password').send_keys('密码')
driver.find_element_by_id('TANGRAM__PSP_11__submit').click()
time.sleep(3)
cookies=json.dumps(driver.get_cookies())
dic_cookie = re.sub('"expiry":.*?,', '', cookies) # 剔除过期时间的属性
with open('./baidu_cookies.txt','w',encoding='utf-8') as f:
f.write(dic_cookie)
driver.refresh()
#get_cookies()
百度目前使用的是图片旋转的验证,等待一定的时间手动旋转,成功之后就会将已登录的cookies保存在本地。频繁操作会出现手机验证码,频繁发送验证码也不行,需要注意。
得到用户的登录信息,接下来实现自动答题。整个答题过程一共涉及4个网页:百度知道问题列表页、百度知道问题详情页、答案搜索页和答案详情页。
在问题列表页中,每条问题的HTML代码是由a标签生成,并且属性class的属性值为title-link,。因此Selenium可以对属性class进行定位,获取全部问题所在的标签a,遍历这些标签提取相应的链接地址。
在新的窗口访问每条问题链接,这些链接会进入相应的问题详情页。在问题详情页中,首先判断问题是否已被抢答,如果尚未被回答,程序根据题目去百度知道搜索相关的答案,在这些相关答案中找到最佳答案,然后写入问题答案输入框里并单击“提交回答”按钮;如果问题已被回答,程序就关闭当前窗口,回到问题列表执行下一个问题。
回答问题的过程中涉及到两个新的网页:答案搜索页和答案详情页。答案搜索页是根据问题在新的窗口中搜索相关答案。
将答案详情页的链接在新的窗口里访问,每个答案详情页都不一定有最佳答案,根据分析可知,最佳答案的class属性值为best-text mb-10,如果Selenium能对属性class进行定位,则说明当前答案详情页有最佳答案,反之则无。
def operation():
driver=webdriver.Chrome()
driver.get('https://zhidao.baidu.com/list?cid=110')
driver.maximize_window()
# 使用Cookies登录
driver.delete_all_cookies()
with open('./baidu_cookies.txt','r',encoding='utf-8') as f:
cookies=json.loads(f.read())
for i in cookies:
driver.add_cookie(i)
driver.refresh()
# 获取问题列表
title_link=driver.find_elements_by_class_name('title-link')
for a in title_link:
# 打开问题详情页并且切换窗口
driver.switch_to.window(driver.window_handles[0])
time.sleep(2)
href_detail=a.get_attribute('href')
driver.execute_script('window.open("%s");' % href_detail)
driver.switch_to.window(driver.window_handles[1])
time.sleep(5)
try:
# 问题没有被回答会存在iframe
driver.find_element_by_id('ueditor_0')
except Exception as e:
driver.close()
# 获取问题题目并且搜索答案
try:
title=driver.find_element_by_class_name('ask-title').text
title_url='https://www.baidu.com/s?wd={0}?&ie=utf-8'.format(quote(title))
js='window.open("%s");' % title_url
driver.execute_script(js)
time.sleep(4)
driver.switch_to.window(driver.window_handles[2])
# 获取答案列表
answ_list=driver.find_elements_by_class_name('t')
for k in answ_list:
# 打开答案详情页
href=k.find_element_by_tag_name('a').get_attribute('href')
driver.execute_script('window.open("%s")' % href)
time.sleep(4)
driver.switch_to.window(driver.window_handles[3])
time.sleep(3)
# 获取最佳答案
try:
texts=driver.find_element_by_xpath('//*[contains(@id,"best-content")]').text
except:
texts=''
finally:
# 关闭答案详情页
driver.close()
driver.switch_to.window(driver.window_handles[2])
#答案不能为空
if texts:
print(texts)
# 关闭答案列表页窗口
driver.switch_to.window(driver.window_handles[2])
driver.close()
# 将答案写在问题回答文本框并提交
driver.switch_to.window(driver.window_handles[1])
time.sleep(3)
driver.switch_to.frame('ueditor_0')
driver.find_element_by_xpath('/html/body').click()
driver.find_element_by_xpath('/html/body').send_keys(texts)
# 调回到网页的HTML
driver.switch_to.default_content()
# 单击提交按钮
driver.find_element_by_xpath('/html/body/div[5]/div/section/article/div[1]/div[3]/div[2]/div[2]/a').click()
time.sleep(5)
# 关闭问题详情页
driver.switch_to.window(driver.window_handles[1])
driver.close()
break
all_handles = driver.window_handles
for b, c in enumerate(all_handles):
if b != 0:
driver.switch_to.window(c)
driver.close()
driver.switch_to.window(driver.window_handles[0])
except Exception as e:
# 除了问题列表,关闭其他窗口
all_handles=driver.window_handles
for b,c in enumerate(all_handles):
if b !=0:
driver.switch_to.window(c)
driver.close()
driver.switch_to.window(driver.window_handles[0])
print(e)
operation()
代码主要是联系一下Selenium的自动化使用,具体实践不可行。具体就是,如果在搜索出来的列表中找到了最佳答案,那么会填入答案,并提交,这里提交的答案,百度会进行检测是否合法,如果不合法就提交不了,selenim的send_keys发送长文本会隔行,百度会检测到,所以提交不了。如果在答案列表中没有找到最佳答案,那么就会更换问题回答,所以说想要实现完美的自动化,还是比较繁琐的!
2. 本站不保证所提供下载的资源的准确性、安全性和完整性,资源仅供下载学习之用!如有链接无法下载、失效或广告,请联系客服处理!
3. 您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容资源!如用于商业或者非法用途,与本站无关,一切后果请用户自负!