前言:之前尝试爬取知乎的回答,虽然在开发者中源码显示了许多回答,但只能爬取前两个。经过各种查阅及调试,大致理解如下:
人为的可以看到很多回答,但是爬虫中直接打开网页只能看到一个页面以内的(可以打印出来,看到读取的url源码只有前两个回答)。因为网页是动态js加载的。
本文主要介绍selenium的安装,以及chromedriver的安装及遇到的问题,以及使用selenium自动打开谷歌浏览器,自动对页面向下滑动,然后读取源码,进行回答的读取保存。
安装Selenium:
命令行输入,即可
pip install selenium
Selenium的简单使用
Selenium的用法教程
Selenium的使用文档
简单的模拟打开百度并搜索Python
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
driver = webdriver.Chrome()
# 打开请求的url
driver.get('http://www.baidu.com/')
# 通过name属性寻找网页元素,此处寻找输入框
elem = driver.find_element_by_name('wd')
# 模拟输入Python
elem.send_keys('Python')
# 模拟点击回车
elem.send_keys(Keys.RETURN)
# 获取网页渲染后的源代码
print(driver.page_source)
运行。
ChromeDriver的安装:
当然事情并没有这么简单,运行报错:
selenium.common.exceptions.WebDriverException: Message: ‘ChromeDriver executable needs to be available in the path.
因为没有安装ChromeDriver (官方下载
网盘链接:http://pan.baidu.com/s/1pLSG8mZ 密码:qytm)
本人使用windows 10,下载后,解压里面只有chromedriver.exe,直接解压到D:\Python\Scripts(找到自己安装的python目录)。
再运行就OK了。
PS:网上的解压到谷歌浏览器,配置环境变量,都试过,反正我都没成功。
参考:安装selenium使用webdriver出现的问题
代码及注释:
# 对于动态加载的网页,例如知乎,需要使用Selenium+ChromeDriver(或PhantomJS)
from bs4 import BeautifulSoup
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import time
# 写一个关于刀的故事
url = 'https://www.zhihu.com/question/45694301'
# 让界面滚动的函数 --
def scroll(driver):
driver.execute_script("""
(function () {
var y = document.body.scrollTop;
var step = 100;
window.scroll(0, y);
function f() {
if (y < document.body.scrollHeight) {
y += step;
window.scroll(0, y);
setTimeout(f, 50);
}
else {
window.scroll(0, y);
document.title += "scroll-done";
}
}
setTimeout(f, 1000);
})();
""")
driver = webdriver.Chrome()
driver.get(url)
scroll(driver)
# 等到滑到最下面
time.sleep(150)
html = driver.page_source
soup = BeautifulSoup(html,'lxml')
storys = soup.find_all('div',class_="List-item")
for story in storys :
nameLabel = story.find('meta',itemprop="name")
name = nameLabel["content"]
with open('有哪些关于刀的故事\By '+str(name)+'.txt','w') as f:
storyText = story.find('span', class_="RichText CopyrightRichText-richText")
storyPages = storyText.find_all('p')
# 打印看标签内容到底是什么
# print(storyPages)
try:
for storyPage in storyPages:
f.write(str(storyPage.string)+'\n')
print('By '+str(name)+' has been finished')
except Exception:
print('Something is wrong on writing to txt')
print('That is all')
运行结果截图:
相关问题:
①未解决的问题
1)下载图片,使用HTML文件保存图片及文字
2)存在‘查看更多’按钮,无法下载所有答案。可以添加点击‘查看更多’按钮函数,以及判断是否到底的的函数
②存在文章内容为none
具体因素不太清楚,可能是因为换行了的
将
storyPages = storyText.find_all('p')
# 打印看标签内容到底是什么
# print(storyPages)
try:
for storyPage in storyPages:
f.write(str(storyPage.string)+'\n')
改为
for string in storyText.strings:
f.write(repr(string) + '\n')
能把所有内容打印出来,但是首尾有单引号,并且把图片源码打印出来。
③参考资料
1)模拟界面滚动
使用selenium爬取知乎任意一个问题下,所有回答中的图片(使用python3,注释很详细,很有参考价值)
2)关于爬取知乎的总结
Python爬虫爬取知乎小结(使用的python2,但内容很丰富,提供了思路)
④关于selenium的一些思路
自此,可以模拟登陆,可以做到模拟点击,翻页等一系列好玩的操作
当然,目前,每次运行都会自动打开浏览器,有点不太友好
可以使用Selenium+PhantomJS运行,PhantomJS是一个无界面的浏览器
运行时会觉得速度太慢,可以升级为多线程
当目标过大,可以采取分布式
当运行时间过长,或者定时运行,可以到放到云服务器
当然,以上的均为YY,但至少有了下一步学习思路。
天道酬勤。
百尺高楼起于垒土。