由于毕业设计的需要,本人最近在学习爬取一些简单的试题库,写篇Blog记录一下。就以问答库(https://www.asklib.com/)为例。

可以看到,问答库中查看答案是需要付费VIP的,这个没办法,我开通了一个5元7天的会员,用来测试。(此处不提供账号密码)

SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。

先附上完整代码 

基于selenium的简单爬虫——爬取问答库试题 Python 第1张
 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)

基于selenium的简单爬虫——爬取问答库试题 Python 第3张

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)

基于selenium的简单爬虫——爬取问答库试题 Python 第4张

 

 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)

基于selenium的简单爬虫——爬取问答库试题 Python 第5张

 

 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,欢迎交流学习。

 

 

 

扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄