python 爬取知乎回答
2018-06-30 本文已影响0人
云胡同学
1. 安装库
htmlparser 用来解析 html 。
Beautiful Soup 是一个可以从 HTML 或 XML 文件中提取数据的 Python 库。
pip install beautifulsoup4
Selenium 是浏览器自动化测试框架,使用它来模拟用户操作。
利用 pip 安装 selenium
pip install -U selenium
2. 模拟用户进行滚动和点击操作
使用 JS 控制滚动条的位置:
window.scrollTo(x,y);
竖向滚动条置底
window.scrollTo(0,document.body.scrollHeight)
time.sleep(2)
向下滑动后延迟两毫秒等待页面加载。
在页面上通过审查,找到查看更多回答的 html 代码
<button class="Button QuestionMainAction"
type="button">查看更多回答</button>
通过
driver.find_element_by_css_selector('button.QuestionMainAction').click()
来选中并点击这个按钮。
3. html 文件结构化
将 html 文件结构化并保存,原页面的 html 解析并存储下来
通过 prettify() 将 html 结构化,之后存储在本地的 txt 文件中。
4. 保存并下载图片
注意我们的目的,就是爬取回答下的图片,其他的都不需要。
还是右键审查,可以发现每张图片上面都有 <noscript> 的 node ,没错,这里面存有图片的高清 URL和缩略图 URL 。
每个 <noscript> 元素都被 html entity 编码了,所以我们要将其解码如下。
html.parser.unescape
之后就可以将图片 URL 保存下来。
最后下载图片。
urllib.request.urlretrieve
5. 结果展示
6. 代码
from selenium import webdriver
import time
import urllib.request
from bs4 import BeautifulSoup
import html.parser
def main():
driver = webdriver.Chrome() # 打开浏览器
driver.get("https://www.zhihu.com/question/40273344") # 打开想要爬取的知乎页面
# 模拟用户操作
def execute_times(times):
for i in range(times):
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
time.sleep(2)
try:
driver.find_element_by_css_selector('button.QuestionMainAction').click()
print("page" + str(i))
time.sleep(1)
except:
break
execute_times(5)
result_raw = driver.page_source # 这是原网页 HTML 信息
result_soup = BeautifulSoup(result_raw, 'html.parser')# 然后将其解析
result_bf = result_soup.prettify() # 结构化原 HTML 文件
with open("./output/rawfile/raw_result.txt", 'w',encoding="utf-8") as girls: # 存储路径里的文件夹需要事先创建。
girls.write(result_bf)
girls.close()
print("爬取回答页面成功!!!")
with open("./output/rawfile/noscript_meta.txt", 'wb') as noscript_meta:
noscript_nodes = result_soup.find_all('noscript') # 找到所有<noscript>node
noscript_inner_all = ""
for noscript in noscript_nodes:
noscript_inner = noscript.get_text() # 获取<noscript>node内部内容
noscript_inner_all += noscript_inner + "\n"
noscript_all = html.parser.unescape(noscript_inner_all).encode('utf-8') # 将内部内容转码并存储
noscript_meta.write(noscript_all)
noscript_meta.close()
print("爬取noscript标签成功!!!")
img_soup = BeautifulSoup(noscript_all, 'html.parser')
img_nodes = img_soup.find_all('img')
with open("./output/rawfile/img_meta.txt", 'w') as img_meta:
count = 0
for img in img_nodes:
if img.get('src') is not None:
img_url = img.get('src')
line = str(count) + "\t" + img_url + "\n"
img_meta.write(line)
urllib.request.urlretrieve(img_url, "./output/image/" + str(count) + ".jpg") # 一个一个下载图片
count += 1
img_meta.close()
print("图片下载成功")
if __name__ == '__main__':
main()