之前有个同学询问我是否能够爬取知乎的全部回答,当初只会Scrapy无法实现下拉的数据全部加载。后来在意外中接触了selenium的自动化测试,看出了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("我正在下拉")
通过find_elements_by_css_selector方法
获取元素对象列表,然后通过遍历列表获取单个对象,通过对象的text属性
获取数据。
代码与"通过pandas写入excel"代码想结合。
批量将数据依次写入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')
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
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(1)
#将滚动条移动到页面的底部
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("我正在下拉")
@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('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')
#保存成网页
with open("index.html", "wb") as f:
f.write(html.encode())
f.close()
cls.driver.quit()
if __name__ == '__main__':
unittest.main(verbosity=2)
在使用Scrapy爬虫时,可以通过selenium来执行网页中的一些js脚本,但是如何将二者结合起来,以及各种框架之间的灵活运用,都将是我需要面对的。