Windows+Python3+Selenium爬取知乎图片

来源:互联网 发布:apache配置文件路径 编辑:程序博客网 时间:2024/06/05 22:47

Windows+Python3+Selenium爬取知乎图片

python2和python3我都有用一些,不过为什么选择python3我就不多说了,以后python3肯定用的越来越多,这是趋势。本文使用python3+Selenium库来模拟浏览器进行知乎图片的抓取。

  • WindowsPython3Selenium爬取知乎图片
    • 前期准备
    • 抓取开始
      • Import Libraries
      • 确定程序主体框架
        • 打开 ChromeDriver 并且确定目标 URL
        • 模拟滚动点击操作来查看更多回答
        • 将抓取到的 HTML 信息处理并保存
        • 提取 HTML 页面中知乎问题回答里的 img 标签
        • 利用所有 img 标签下载图片
      • 完整代码
    • 脚注


前期准备

首先,你要有python3的环境,这里我推荐使用Anaconda,因为里边集成了许多python开发环境,还会预装一些python科学计算的库,不管是Spyder还是Jupyter notebook用起来都是很方便的。这里给出两个可能用到的链接:

  • Anaconda官网
  • 关于Conda的使用手册

另外,本次知乎图片抓取还要用到Selenium库,这个库一般是没有预装的,所以要自己安装。如果你已经装过Anaconda了,这里我介绍一下安装方法,其他环境读者请自行配置。

首先,打开Anaconda Prompt,这是Anaconda的root环境下的控制台,如果你有在Anaconda中自己建立环境,只需要“activate+环境名”激活相应环境,然后再进行安装,退出环境时直接输入“deactivate”即可。

Anaconda Prompt

安装Selenium库的代码如下:

>>> pip install -U selenium

看到successfully信息字样说明安装成功,可以输入相应代码进行测试,查看Selenium库是否安装成功。

安装Selenium库

大家可以自己查阅Selenium库的使用方法。里边有说到,为了使用Selenium库,我们需要安装浏览器的driver。

Selenium库依赖的driver

大家不要觉得麻烦,很简单的。我用的浏览器是chrome,所以进入相应的链接进行下载ChromeDriver。下载解压之后就是一个exe文件,把它放到浏览器的安装目录中即可。

ChromeDriver

由于我们利用Selenium库的时候会调用到ChromeDriver,所以大家把ChromeDriver所在的路径放到电脑的“系统变量 –>Path”里去,这样就可以随意使用了,设置好之后我们就可以开始“50行python代码抓取知乎图片”的操作了。

ChromeDriver路径设置


抓取开始

Talk is cheap. Show me the code. —— Linus Torvalds

Import Libraries

# 调用Selenium库from selenium import webdriverimport time# 这两个可是经典的Python爬虫库import urllib.requestfrom bs4 import BeautifulSoup# 用于HTML页面的解析import html.parser

确定程序主体框架

def main():    # 首先,打开 ChromeDriver 并且确定目标 URL    # 模拟滚动点击操作来查看更多回答    # 将抓取到的 HTML 信息处理并保存    # 提取 HTML 页面中知乎问题回答里的 <img> 标签    # 利用所有 <img> 标签下载图片if __name__ == '__main__':    main()    

下边针对main()函数中的五个步骤分别进行程序代码的实现。


打开 ChromeDriver 并且确定目标 URL

这里选择的知乎问题是“身材好是一种怎样的体验?”恩,有很多妹子…

# ChromeDriver 打开浏览器driver = webdriver.Chrome()# 确定目标URLdriver.get("https://www.zhihu.com/question/26037846") # 身材好是一种怎样的体验?

模拟滚动点击操作来查看更多回答

这里选择的知乎问题是“身材好是一种怎样的体验?”恩,有很多妹子…

模拟的就是点击下图的这个按钮:

查看更多回答

右键单击,检查元素可以看到:

检查元素

具体代码如下:

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:            breakexecute_times(5)  # 下拉五次

将抓取到的 HTML 信息处理并保存

result_raw = driver.page_source  # 这是原网页 HTML 信息result_soup = BeautifulSoup(result_raw, 'html.parser')result_bf = result_soup.prettify()  # 结构化原 HTML 文件# 存储路径里的文件夹需要事先创建# 打开文件的时候一定要加上utf-8编码形式,不然会报错"UnicodeEncodeError"with open("./output/rawfile/raw_result.txt", 'w', encoding='utf-8') as girls:     girls.write(result_bf)girls.close()  # 要养成关闭文件的好习惯print("Store raw data successfully!!!")

提取 HTML 页面中知乎问题回答里的< img >标签

这一步在平常抓取网页信息的时候非常重要,不同网页页面的设计不一样,所以要根据具体爬取的内容来有针对性的编写代码。话不多说,来看下知乎的页面是怎么做的。

知乎图片

可以看到,每个< img >标签都对应着一张图片,这时可以发现在< img >标签的上方还有一个< noscript >标签,为了偷懒就直接抓取< noscript >标签,然后获取里边的内容即图片地址。可以看到里边不仅有缩略图的URL还要高清原图的URL。

每个< noscript >的<>都是被 escape(HTML entity 转码)了的,所以要用html.parser.unescape进行解码。

# 存储路径里的文件夹需要事先创建# 同样的,打开txt文件的时候一定要加上utf-8编码形式with open("./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>标签的内部内容        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!!!")

之后打开”noscript_meta.txt”文件可以看到我们抓取的图片URL内容,还是很壮观的。

noscript标签转码


利用所有< img >标签下载图片

有了URL就可以进行图片的下载了。

img_soup = BeautifulSoup(noscript_all, 'html.parser')img_nodes = img_soup.find_all('img')# 将抓取图片的URL单独列出来,前边加上序号之后存放在文件"img_meta.txt"中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')            # 将抓取的URL写入文件中            line = str(count) + "\t" + img_url  + "\n"            img_meta.write(line)            # 图片的下载            urllib.request.urlretrieve(img_url, "./output/image/" + str(count) + ".jpg")             count += 1img_meta.close()  # 记得关闭文件print("Store meta data and images successfully!!!")

完整代码

完整代码如下:

# 调用Selenium库from selenium import webdriverimport time# 这两个可是经典的Python爬虫库import urllib.requestfrom bs4 import BeautifulSoup# 用于HTML页面的解析import html.parserdef main():    # ChromeDriver 打开浏览器    driver = webdriver.Chrome()    # 确定目标URL    driver.get("https://www.zhihu.com/question/26037846") # 身材好是一种怎样的体验?    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 文件    # 存储路径里的文件夹需要事先创建    # 打开文件的时候一定要加上utf-8编码形式,不然会报错"UnicodeEncodeError"    with open("./output/rawfile/raw_result.txt", 'w', encoding='utf-8') as girls:         girls.write(result_bf)    girls.close()  # 要养成关闭文件的好习惯    print("Store raw data successfully!!!")    # 存储路径里的文件夹需要事先创建    # 同样的,打开txt文件的时候一定要加上utf-8编码形式    with open("./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>标签的内部内容            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!!!")    img_soup = BeautifulSoup(noscript_all, 'html.parser')    img_nodes = img_soup.find_all('img')    # 将抓取图片的URL单独列出来,前边加上序号之后存放在文件"img_meta.txt"中    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')                # 将抓取的URL写入文件中                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()

结束之前,给大家看一下成果吧。

妹子图


脚注

本文参考了知乎专栏”聂大哥有毒”中的文章
作者:聂大哥的CS小弟 @Hunting

在这个基础之上自己实现了一遍又对代码修改了一下。


原创粉丝点击