python爬虫(爬取知乎答案图片)

1.⾸先,你要在电脑⾥安装 python 的环境

我会提供2.7和3.6两个版本的代码,但是本⽂只以python3.6版本为例。
安装完成后,打开你电脑的终端(Terminal)执⾏以下命令:
搭建 python 3.6环境,
爬虫专用。如果你已经装好了 python3.6的环境,那么可以跳过搭建环境这一步,直接安装所需要的 python库。
检查 python 版本

python –version

2、selenium

因为知乎⽹站前端是⽤ react 搭建的,页⾯内容随着⽤户⿏标滚轴滑动、点击依次展现,为了获取海量的图⽚内容,我们需要⽤selenium这个 lib 模拟⽤户对浏览器进⾏滑动点击等操作。

利⽤ pip 安装 selenium

pip install -U selenium

下载安装完成后,我建议⼤家打开上⾯的链接,阅读⼀下 selenium 的使⽤⽅法。意思⼤致为,为了运⾏ selenium,我们需要安装⼀个 chrome 的driver,下载完成后,对于 Mac ⽤户,直接把它复制到/usr/bin或者/usr/local/bin,当然你也可以⾃定义并添加路径。对于 Win ⽤户,也是同理。
chromedriver与chrome各版本及下载地址

Chrome: 下载地址
Firefox:下载地址
Safari:下载地址

2.0 在爬⾍的时候我们经常会发现⽹页都是经过压缩去掉缩进和空格的,页⾯结构会很不清晰,这时候我们就需要⽤ BeautifulSoup 这个 lib 来进⾏html ⽂件结构化。

pip install beautifulsoup4

Section 2 – 代码解释

from selenium import webdriver

import time

import urllib.request

from bs4 import BeautifulSoup

import html.parser

2.1 确定目标URL

在 main 函数里边,打开chrome driver,然后输入 url

def main():

# ********* Open chrome driver and type the website that you want to view ***********************

driver = webdriver.Chrome() # 打开浏览器

列出来你想要下载图片的网站

https://www.zhihu.com/question/35242408   #拥有丰富的表情包是怎样的体验

2.2 模拟滚动点击操作

在 main 函数⾥我们定义⼀个重复执⾏的函数,来进⾏滚动和点击的操作。⾸先我们可以⽤driver.execute_scrip来进⾏滚动操作。通过观察,我们发现知乎问题底部有⼀个“查看更多回答的”的按钮,如下图。因此我们可以⽤driver.find_element_by_css_selector来选中这个按钮,并点击。我们这⾥只爬取五个页⾯的图⽚。其实,五个页⾯,100个回答,往往都能有1000张图⽚了。。。


# ****************** Scroll to the bottom, and click the "view more" button *********

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)

2.3 结构化HTML页面并保存

我们每次爬取页⾯信息,要做的第⼀件事就是把页⾯ HTML 存储下来。为了⽅便我们⾁眼浏览,这时候就需要⽤beautifulSoup把压缩后的 HTML ⽂件结构化并保存。

# **************** Prettify the html file and store raw data file *****************************************

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') as girls: # 存储路径里的文件夹需要事先创建。

girls.write(result_bf)

girls.close()

print("Store raw data successfully!!!")

2.4 爬取知乎问题回答里的nodes

要知道,在我们每次想要爬取页⾯信息之前,要做的第⼀件事就是观察,观察这个页⾯的结构,量⾝⽽裁。⼀般每个页⾯⾥都有很多个图⽚,⽐如在这个知乎页⾯⾥,有很多⽤户头像以及插⼊的图⽚。但是我们这⾥不想要⽤户头像,我们只想要要回答问题⾥的照⽚,所以不能够直接爬取所有 <\img> 的照⽚。仔细观察,都是被 escape(HTML entity 转码)了的,所以要⽤html.parser.unescape进⾏解码。

# **************** Find all <nonscript> nodes and store them *****************************************

with open("./output/rawfile/noscript_meta.txt", 'w') 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) # 将内部内容转码并存储

noscript_meta.write(noscript_all)

noscript_meta.close()

print("Store noscript meta data successfully!!!")

2.5 下载图片

有了 img 的所有 node,下载图⽚就轻松多了。⽤⼀个 urllib.request.urlretrieve就全部搞定。这⾥我又做了⼀点清理,把所有的 url 单独存了⼀下,并⽤序号标记,你也可以不要这⼀步直接下载。

# **************** Store meta data of imgs *****************************************

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("Store meta data and images successfully!!!")

记得还有最后的!!!

if __name__ == '__main__':

main()

下面是全部源码

from selenium import webdriver
import time

import urllib.request

from bs4 import BeautifulSoup

import html.parser


def main():
# ********* Open chrome driver and type the website that you want to view ***********************

driver = webdriver.Chrome() # 打开浏览器

# 列出来你想要下载图片的网站


driver.get("https://www.zhihu.com/question/35242408") #拥有丰富的表情包是怎样的体验

# ****************** Scroll to the bottom, and click the "view more" button *********
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(7)


# **************** Prettify the html file and store raw data file *****************************************

result_raw = driver.page_source # 这是原网页 HTML 信息
result_soup = BeautifulSoup(result_raw, 'html.parser')

result_bf = result_soup.prettify() # 结构化原 HTML 文件

with open("D:/newworld/output/rawfile/raw_result.txt", 'w',encoding='utf-8') as girls: # 存储路径里的文件夹需要事先创建。
girls.write(result_bf)
girls.close()
print("Store raw data successfully!!!")

# **************** Find all <nonscript> nodes and store them *****************************************
with open("D:/newworld/output/rawfile/noscript_meta.txt", 'w',encoding='utf-8') 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) # 将内部内容转码并存储
noscript_meta.write(noscript_all)

noscript_meta.close()
print("Store noscript meta data successfully!!!")

# **************** Store meta data of imgs *****************************************
img_soup = BeautifulSoup(noscript_all, 'html.parser')
img_nodes = img_soup.find_all('img')
with open("D:/newworld/output/rawfile/img_meta.txt", 'w',encoding='utf-8') 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, "D:/newworld/output/zhihumeinv/" + str(count) + ".jpg") # 一个一个下载图片
count += 1

img_meta.close()
print("Store meta data and images successfully!!!")

if __name__ == '__main__':
main()