基于selenium的简单爬虫——爬取问答库试题
由于毕业设计的需要,本人最近在学习爬取一些简单的试题库,写篇Blog记录一下。就以问答库(https://www.asklib.com/)为例。
可以看到,问答库中查看答案是需要付费VIP的,这个没办法,我开通了一个5元7天的会员,用来测试。(此处不提供账号密码)
SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。先附上完整代码
1 import json 2 from bs4 import BeautifulSoup 3 from time import sleep 4 from selenium import webdriver 5 from selenium.webdriver.common.by import By # 引用网页选择器 6 from selenium.webdriver.support.ui import WebDriverWait # 引用设定显示等待时间 7 from selenium.webdriver.support import expected_conditions as EC # 引用等待条件 8 import time 9 10 11 def init(): 12 # 定义为全局变量,方便其他模块使用 13 global url, browser, username, password, wait 14 # 登录界面的url 15 url = 'https://www.asklib.com/?from=logout' 16 # 实例化一个chrome浏览器 17 browser = webdriver.Chrome("C:/Program Files (x86)/Google/Chrome/Application/chromedriver.exe") 18 # 用户名 19 username = "" 20 # 密码 21 password = "" 22 # 设置等待超时 23 wait = WebDriverWait(browser, 20) 24 25 26 def login(): 27 # 打开登录页面 28 browser.get("https://www.asklib.com/?from=logout") 29 button = wait.until( 30 EC.element_to_be_clickable((By.XPATH, '/html/body/div[2]/div/ul[1]/li[1]/a'))) # 等待目标可以点击 31 button.click() 32 time.sleep(1) 33 browser.switch_to.frame(browser.find_element_by_xpath("//iframe[contains(@id,'layui-layer-iframe1')]")) 34 input_psw = browser.find_element_by_xpath('//div[@class="box-item content-box"]/input')#获得密码输入 35 input_user = browser.find_element_by_xpath('//div[@class="box-item"]/input')#获得账号输入 36 input_user.send_keys("xxxxxxxxx") # 发送登录账号 37 time.sleep(1) 38 input_psw.send_keys("xxxxxxxxx")#发送登录密码 39 time.sleep(1) # 等待 一秒 防止被识别为机器人 40 login1 = wait.until(EC.element_to_be_clickable((By.XPATH, '/html/body/section/div[1]/input'))) 41 login1.click() 42 browser.switch_to.default_content() 43 44 45 def get_item_info(url): 46 browser.get(url) 47 soup = BeautifulSoup(browser.page_source.encode('utf-8'), 'lxml') 48 question_list = soup.select( 49 'body > div.content.clear > div:nth-child(2) > div.listleft > div:nth-child(1) > div.essaytitle.txt_l ') 50 question = question_list[0].text 51 answer_list = soup.select('body > div.content.clear > div:nth-child(2) > div.listleft > div.listbg > div') 52 answer = answer_list[0].text 53 jiexi_list = soup.select('#commentDiv > div ') 54 jiexi = jiexi_list[0].text 55 56 data = { 57 'question': question, 58 'answer': answer, 59 'jiexi': jiexi 60 } 61 62 with open('data.json', 'a', encoding='utf-8') as f: 63 json.dump(data, f, ensure_ascii=False, indent=2) 64 65 66 def get_all_link(): 67 for page in range(1,100): 68 if page == 100: 69 break 70 if page == 1: 71 browser.get('https://www.asklib.com/s/%E6%96%87%E5%AD%A6/p1') 72 sleep(5) 73 else: 74 browser.get('https://www.asklib.com/s/%E6%96%87%E5%AD%A6/p'+str(page)) 75 soup = BeautifulSoup(browser.page_source.encode('utf-8'), 'lxml') 76 hrefs_list = soup.select( 77 'body > div.content.clear > div:nth-child(2) > div.listleft > div > div.b-tQ.clear > div > a') 78 for href in hrefs_list: 79 link = href.get('href') 80 url1 = 'https://www.asklib.com/'+link 81 get_item_info(url1) 82 83 84 def main(): 85 # 初始化 86 init() 87 # 登录 88 login() 89 sleep(6) 90 get_all_link() 91 92 93 if __name__ == '__main__': 94 main()问答库爬虫
前期准备:你需要一些网页基础(简单的HTML,CSS,JS可以到W3C学习 https://www.w3school.com.cn/html/index.asp)
掌握一定的python基础(这里推荐一下廖老师的教程 https://www.liaoxuefeng.com/wiki/1016959663602400)
然后我们就可以开始快乐地编程了。
1. 爬取一个网页,你需要先到页面上看看自己需要爬取哪些信息,对于我的需求的话,我只需要题目,答案以及解析即可。打开开发人员工具,我是用的是微软的edge,快捷键F12,常见的浏览器都差不多。右击检查,或者在右侧区域选中你需要爬取的信息。复制选择器(selector)
2. 在pycharm中新建python文件,导入第三方库
1 import json 2 import requests 3 from bs4 import BeautifulSoup 4 from time import sleep 5 from selenium import webdriver 6 from selenium.webdriver.common.by import By # 引用网页选择器 7 from selenium.webdriver.support.ui import WebDriverWait # 引用设定显示等待时间 8 from selenium.webdriver.support import expected_conditions as EC # 引用等待条件 9 import time
3. 尝试用BeautifulSoup爬取页面源代码,爬取成功。
1 def get_item_info(): 2 url = 'https://www.asklib.com/view/16f478fa.html' 3 wb_data = requests.get(url) 4 soup = BeautifulSoup(wb_data.text, 'lxml') 5 print(soup)
4. 利用选择器(selector)爬取我们想要的信息。稍微修改上面的代码即可。这里以题目为例其他的信息爬取也一样。
1 def get_item_info(): 2 url = 'https://www.asklib.com/view/16f478fa.html' 3 wb_data = requests.get(url) 4 soup = BeautifulSoup(wb_data.text, 'lxml') 5 question_list = soup.select('body > div.content.clear > div:nth-child(2) > div.listleft > div:nth-child(1) > div.essaytitle.txt_l') 6 question = question_list[0].text 7 print(question)
5. 将信息结构化成字典
1 def get_item_info(): 2 url = 'https://www.asklib.com/view/16f478fa.html' 3 wb_data = requests.get(url) 4 soup = BeautifulSoup(wb_data.text, 'lxml') 5 question_list = soup.select('body > div.content.clear > div:nth-child(2) > div.listleft > div:nth-child(1) > div.essaytitle.txt_l') 6 question = question_list[0].text 7 question_list = soup.select( 8 'body > div.content.clear > div:nth-child(2) > div.listleft > div:nth-child(1) > div.essaytitle.txt_l ') 9 question = question_list[0].text 10 answer_list = soup.select('body > div.content.clear > div:nth-child(2) > div.listleft > div.listbg > div') 11 answer = answer_list[0].text 12 jiexi_list = soup.select('#commentDiv > div ') 13 jiexi = jiexi_list[0].text 14 data = { 15 'question': question, 16 'answer': answer, 17 'jiexi': jiexi 18 } 19 print(data)
6. 模拟浏览器登录,此处需要ChromeDriver,安装请自行百度。
1 def init(): 2 # 定义为全局变量,方便其他模块使用 3 global url, browser, username, password, wait 4 # 登录界面的url 5 url = 'https://www.asklib.com/?from=logout' 6 # 实例化一个chrome浏览器 7 browser = webdriver.Chrome("C:/Program Files (x86)/Google/Chrome/Application/chromedriver.exe") 8 # 用户名 9 username = "" 10 # 密码 11 password = "" 12 # 设置等待超时 13 wait = WebDriverWait(browser, 20)
此处不提供账号密码,如有需要,自行购买。
1 def login(): 2 # 打开登录页面 3 browser.get("https://www.asklib.com/?from=logout") 4 button = wait.until( 5 EC.element_to_be_clickable((By.XPATH, '/html/body/div[2]/div/ul[1]/li[1]/a'))) # 等待目标可以点击 6 button.click() 7 time.sleep(1) 8 browser.switch_to.frame(browser.find_element_by_xpath("//iframe[contains(@id,'layui-layer-iframe1')]")) 9 input_psw = browser.find_element_by_xpath('//div[@class="box-item content-box"]/input') 10 input_user = browser.find_element_by_xpath('//div[@class="box-item"]/input') 11 input_user.send_keys("XXXXXXXXXXXX") # 发送登录账号 12 time.sleep(1) 13 input_psw.send_keys("XXXXXXXXXXX")#发送登录密码 14 time.sleep(1) # 等待 一秒 防止被识别为机器人 15 login1 = wait.until(EC.element_to_be_clickable((By.XPATH, '/html/body/section/div[1]/input'))) 16 login1.click() 17 browser.switch_to.default_content()
7. 实现了登录功能后,我们发现,所以的问题链接都是在<a href>标签中,每页有10个问题,通过网页链接可以查看到规律。
1 def get_all_link(): 2 for page in range(1,100): 3 if page == 100: 4 break 5 if page == 1: 6 browser.get('https://www.asklib.com/s/%E6%96%87%E5%AD%A6/p1') 7 sleep(5) 8 else: 9 browser.get('https://www.asklib.com/s/%E6%96%87%E5%AD%A6/p'+str(page)) 10 soup = BeautifulSoup(browser.page_source.encode('utf-8'), 'lxml') 11 hrefs_list = soup.select( 12 'body > div.content.clear > div:nth-child(2) > div.listleft > div > div.b-tQ.clear > div > a') 13 for href in hrefs_list: 14 link = href.get('href') 15 url1 = 'https://www.asklib.com/'+link 16 get_item_info(url1)
8. 将以上代码整合,具体代码开头已经给出,在此声明,此方法不是最好的方法,但是selenium是真的nb,欢迎交流学习。