前言
之前有个同学询问我是否能够爬取知乎的全部回答,当初只会Scrapy无法实现下拉的数据全部加载。后来在意外中接触了selenium的自动化测试,看出了selenium的模拟能力的强大,而昨天有个同学问我能否爬取中国工商银行远程银行的精彩回答,我说可以试试。
思路
selenium模拟下拉直至底部
然后通过selenium获取数据集合
通过pandas写入excel
selenium模拟下拉直至底部
此处全靠一位大佬的博客点拨,实在不好意思的是,selenium就看了下常用的api,实在不懂如何判断是否加载完毕,而该博客代码的原理也好理解,通过不断下拉判断与上一次高度进行对比,知道前端页面的滚动高度属性就懂了,当然思想最重要。
见代码:
#将滚动条移动到页面的底部
all_window_height = [] # 创建一个列表,用于记录每一次拖动滚动条后页面的最大高度
all_window_height.append(self.driver.execute_script("return document.body.scrollHeight;")) #当前页面的最大高度加入列表
while True:
self.driver.execute_script("scroll(0,100000)") # 执行拖动滚动条操作
time.sleep(3)
check_height = self.driver.execute_script("return document.body.scrollHeight;")
if check_height == all_window_height[-1]: #判断拖动滚动条后的最大高度与上一次的最大高度的大小,相等表明到了最底部
print("我已下拉完毕")
break
else:
all_window_height.append(check_height) #如果不想等,将当前页面最大高度加入列表。
print("我正在下拉")
然后通过selenium获取数据集合
通过find_elements_by_css_selector方法获取元素对象列表,然后通过遍历列表获取单个对象,通过对象的text属性获取数据。
代码与"通过pandas写入excel"代码想结合。
通过pandas写入excel
example.xlsx
批量将数据依次写入excel,此处个人知道有两种写法,推荐后者。
写法一:
problem = cls.driver.find_elements_by_css_selector("li h2.item-title a")
data = pd.read_excel('example.xlsx', sheet_name = 'Sheet1')
problemtext = []
for i in problem:
problemtext .append(i.text)
replytext = []
reply = cls.driver.find_elements_by_css_selector("div.item-right p")
for j in reply:
replytext.append(j.text)
data.loc[row,'答案'] = j.text
data['问题'] = problemtext
data['答案'] = replytext
DataFrame(data).to_excel('test.xlsx', sheet_name='Sheet1')
写法二:
problem = cls.driver.find_elements_by_css_selector("li h2.item-title a")
data = pd.read_excel('example.xlsx', sheet_name = 'Sheet1')
row = 1
for i in problem:
data.loc[row,'问题'] = i.text
row += 1
row = 1
reply = cls.driver.find_elements_by_css_selector("div.item-right p")
for j in reply:
data.loc[row,'答案'] = j.text
row += 1
DataFrame(data).to_excel('test.xlsx', sheet_name='Sheet1')
完整代码如下: 需要安装如下插件
pip3 install selenium
pip3 install pandas
pip3 install xlrd
pip3 install openpyxl
import pandas as pd
from pandas import DataFrame
import unittest
import time
from selenium import webdriver
from selenium.webdriver.support.ui import Select
from selenium.webdriver.support.select import Select
from selenium.webdriver.support.ui import WebDriverWait
import xlrd
class autoLogin(unittest.TestCase):
url= 'http://zhidao.baidu.com/business/profile?id=87701'
@classmethod
def setUpClass(cls):
cls.driver=webdriver.Firefox()
cls.driver.implicitly_wait(20)
cls.driver.maximize_window()
def test_search_by_selenium(self):
self.driver.get(self.url)
self.driver.title
time.sleep(10)
#将滚动条移动到页面的底部
all_window_height = []
all_window_height.append(self.driver.execute_script("return document.body.scrollHeight;"))
while True:
self.driver.execute_script("scroll(0,100000)")
time.sleep(10)
check_height = self.driver.execute_script("return document.body.scrollHeight;")
if check_height == all_window_height[-1]:
print("我已下拉完毕")
break
else:
all_window_height.append(check_height)
print("我正在下拉")
@classmethod
def tearDownClass(cls):
html = cls.driver.page_source
problem = cls.driver.find_elements_by_css_selector("li h2.item-title a")
data = pd.read_excel(r'D:/python/example.xlsx', sheet_name = 'Sheet1')
row = 1
for i in problem:
data.loc[row,'问题'] = i.text
row += 1
row = 1
reply = cls.driver.find_elements_by_css_selector("div.item-right p")
for j in reply:
data.loc[row,'答案'] = j.text
row +=1
DataFrame(data).to_excel(r'D:/python/test.xlsx', sheet_name='Sheet1')
#保存成网页
with open('index.html',"wb") as f:
f.write(html.encode())
f.close()
cls.driver.quit()
if __name__ =='__main__':
unittest.main(verbosity=2)
改代码在ubuntu下也是可以运行的,展示
总结
在使用Scrapy爬虫时,可以通过selenium来执行网页中的一些js脚本,但是如何将二者结合起来,以及各种框架之间的灵活运用,都将是我需要面对的。