10丨Python爬虫:如何自动化下载王祖贤海报?

爬虫的流程

相信你对“爬虫”这个词已经非常熟悉了,爬虫实际上是用浏览器访问的方式模拟了访问网站的过程,整个过程包括三个阶段:打开网页、提取数据和保存数据。

在 Python 中,这三个阶段都有对应的工具可以使用。

在“打开网页”这一步骤中,可以使用 Requests 访问页面,得到服务器返回给我们的数据,这里包括 HTML 页面以及 JSON 数据。

在“提取数据”这一步骤中,主要用到了两个工具。针对 HTML 页面,可以使用 XPath 进行元素定位,提取数据;针对 JSON 数据,可以使用 JSON 进行解析。

在最后一步“保存数据”中,我们可以使用 Pandas 保存数据,最后导出 CSV 文件。

下面我来分别介绍下这些工具的使用。

Requests 访问页面Requests 是 Python HTTP 的客户端库,编写爬虫的时候都会用到,编写起来也很简单。

它有两种访问方式:Get 和 Post。

这两者最直观的区别就是:Get 把参数包含在 url 中,而 Post 通过 request body 来传递参数。假设我们想访问豆瓣,那么用 Get 访问的话,代码可以写成下面这样的:

r = requests.get('http://www.douban.com')

代码里的“r”就是 Get 请求后的访问结果,然后我们可以使用 r.text 或 r.content 来获取 HTML 的正文。如果我们想要使用 Post 进行表单传递,代码就可以这样写:

r = requests.post('http://xxx.com', data = {'key':'value'})

这里 data 就是传递的表单参数,data 的数据类型是个字典的结构,采用 key 和 value 的方式进行存储。

XPath 定位XPath 是 XML 的路径语言,实际上是通过元素和属性进行导航,帮我们定位位置。它有几种常用的路径表达方式。

我来给你简单举一些例子:

1.xpath(‘node’) 选取了 node 节点的所有子节点;

2.xpath(’/div’) 从根节点上选取 div 节点;

3.xpath(’//div’) 选取所有的 div 节点;

4.xpath(’./div’) 选取当前节点下的 div 节点;

5.xpath(’…’) 回到上一个节点;

6.xpath(’//@id’) 选取所有的 id 属性;

7.xpath(’//book[@id]’) 选取所有拥有名为 id 的属性的 book 元素;

8.xpath(’//book[@id=“abc”]’) 选取所有 book 元素,且这些 book 元素拥有 id= "abc"的属性;9.xpath(’//book/title | //book/price’) 选取 book 元素的所有 title 和 price 元素。

上面我只是列举了 XPath 的部分应用,XPath 的选择功能非常强大,它可以提供超过 100 个内建函数,来做匹配。我们想要定位的节点,几乎都可以使用 XPath 来选择。

使用 XPath 定位,你会用到 Python 的一个解析库 lxml。这个库的解析效率非常高,使用起来也很简便,只需要调用 HTML 解析命令即可,然后再对 HTML 进行 XPath 函数的调用。

比如我们想要定位到 HTML 中的所有列表项目,可以采用下面这段代码。


from lxml import etree
html = etree.HTML(html)
result = html.xpath('//li')

 JSON 对象

JSON 是一种轻量级的交互方式,在 Python 中有 JSON 库,可以让我们将 Python 对象和 JSON 对象进行转换。为什么要转换呢?原因也很简单。将 JSON 对象转换成为 Python 对象,我们对数据进行解析就更方便了。

这是一段将 JSON 格式转换成 Python 对象的代码,你可以自己运行下这个程序的结果。


import json
jsonData = '{"a":1,"b":2,"c":3,"d":4,"e":5}';
input = json.loads(jsonData)
print input

接下来,我们就要进行实战了,我会从两个角度给你讲解如何使用 Python 爬取海报,一个是通过 JSON 数据爬取,一个是通过 XPath 定位爬取。

如何使用 JSON 数据自动下载王祖贤的海报

我在上面讲了 Python 爬虫的基本原理和实现的工具,下面我们来实战一下。

如果想要从豆瓣图片中下载王祖贤的海报,你应该先把我们日常的操作步骤整理下来:

1.打开网页;

2.输入关键词“王祖贤”;

3.在搜索结果页中选择“图片”;

4.下载图片页中的所有海报。

这里你需要注意的是,如果爬取的页面是动态页面,就需要关注 XHR 数据。因为动态页面的原理就是通过原生的 XHR 数据对象发出 HTTP 请求,得到服务器返回的数据后,再进行处理。XHR 会用于在后台与服务器交换数据。

你需要使用浏览器的插件查看 XHR 数据,比如在 Chrome 浏览器中使用开发者工具。在豆瓣搜索中,我们对“王祖贤”进行了模拟,发现 XHR 数据中有一个请求是这样的:

https://www.douban.com/j/search_photo?q=%E7%8E%8B%E7%A5%96%E8%B4%A4&limit=20&start=0url 

中的乱码正是中文的 url 编码,打开后,我们看到了很清爽的 JSON 格式对象,展示的形式是这样的:


{"images":
       [{"src": …, "author": …, "url":…, "id": …, "title": …, "width":…, "height":…},
    …
   {"src": …, "author": …, "url":…, "id": …, "title": …, "width":…, "height":…}],
 "total":22471,"limit":20,"more":true}

从这个 JSON 对象中,我们能看到,王祖贤的图片一共有 22471 张,其中一次只返回了 20 张,还有更多的数据可以请求。数据被放到了 images 对象里,它是个数组的结构,每个数组的元素是个字典的类型,分别告诉了 src、author、url、id、title、width 和 height 字段,这些字段代表的含义分别是原图片的地址、作者、发布地址、图片 ID、标题、图片宽度、图片高度等信息。

有了这个 JSON 信息,你很容易就可以把图片下载下来。当然你还需要寻找 XHR 请求的 url 规律。如何查看呢,我们再来重新看下这个网址本身。

https://www.douban.com/j/search_photo?q= 王祖贤 &limit=20&start=0

你会发现,网址中有三个参数:q、limit 和 start。start 实际上是请求的起始 ID,这里我们注意到它对图片的顺序标识是从 0 开始计算的。所以如果你想要从第 21 个图片进行下载,你可以将 start 设置为 20。王祖贤的图片一共有 22471 张,你可以写个 for 循环来跑完所有的请求,具体的代码如下:


# coding:utf-8
import requests
import json
query = '王祖贤'
''' 下载图片 '''
def download(src, id):
  dir = './' + str(id) + '.jpg'
  try:
    pic = requests.get(src, timeout=10)
    fp = open(dir, 'wb')
    fp.write(pic.content)
    fp.close()
  except requests.exceptions.ConnectionError:
    print('图片无法下载')
            
''' for 循环 请求全部的 url '''
for i in range(0, 22471, 20):
  url = 'https://www.douban.com/j/search_photo?q='+query+'&limit=20&start='+str(i)
  html = requests.get(url).text    # 得到返回结果
  response = json.loads(html,encoding='utf-8') # 将 JSON 格式转换成 Python 对象
  for image in response['images']:
    print(image['src']) # 查看当前下载的图片网址
    download(image['src'], image['id']) # 下载一张图片

如何使用 XPath 自动下载王祖贤的电影海报封面如果你遇到 JSON 的数据格式,那么恭喜你,数据结构很清爽,通过 Python 的 JSON 库就可以解析。但有时候,网页会用 JS 请求数据,那么只有 JS 都加载完之后,我们才能获取完整的 HTML 文件。XPath 可以不受加载的限制,帮我们定位想要的元素。比如,我们想要从豆瓣电影上下载王祖贤的电影封面,需要先梳理下人工的操作流程:

1.打开网页 movie.douban.com;

2.输入关键词“王祖贤”;

3.下载图片页中的所有电影封面。

这里你需要用 XPath 定位图片的网址,以及电影的名称。一个快速定位 XPath 的方法就是采用浏览器的 XPath Helper 插件,使用 Ctrl+Shift+X 快捷键的时候,用鼠标选中你想要定位的元素,就会得到类似下面的结果。

XPath Helper 插件中有两个参数,一个是 Query,另一个是 Results。Query 其实就是让你来输入 XPath 语法,然后在 Results 里看到匹配的元素的结果。

我们看到,这里选中的是一个元素,我们要匹配上所有的电影海报,就需要缩减 XPath 表达式。你可以在 Query 中进行 XPath 表达式的缩减,尝试去掉 XPath 表达式中的一些内容,在 Results 中会自动出现匹配的结果。

经过缩减之后,你可以得到电影海报的 XPath(假设为变量 src_xpath): 


//div[@class='item-root']/a[@class='cover-link']/img[@class='cover']/@src

 以及电影名称的 XPath(假设为变量 title_xpath):


//div[@class='item-root']/div[@class='detail']/div[@class='title']/a[@class='title-text']

但有时候当我们直接用 Requests 获取 HTML 的时候,发现想要的 XPath 并不存在。这是因为 HTML 还没有加载完,因此你需要一个工具,来进行网页加载的模拟,直到完成加载后再给你完整的 HTML。在 Python 中,这个工具就是 Selenium 库,使用方法如下:


from selenium import webdriver
driver = webdriver.Chrome()
driver.get(request_url)

是 Web 应用的测试工具,可以直接运行在浏览器中,它的原理是模拟用户在进行操作,支持当前多种主流的浏览器。这里我们模拟 Chrome 浏览器的页面访问。

你需要先引用 Selenium 中的 WebDriver 库。WebDriver 实际上就是 Selenium 2,是一种用于 Web 应用程序的自动测试工具,提供了一套友好的 API,方便我们进行操作。

然后通过 WebDriver 创建一个 Chrome 浏览器的 drive,再通过 drive 获取访问页面的完整 HTML。

当你获取到完整的 HTML 时,就可以对 HTML 中的 XPath 进行提取,在这里我们需要找到图片地址 srcs 和电影名称 titles。这里通过 XPath 语法匹配到了多个元素,因为是多个元素,所以我们需要用 for 循环来对每个元素进行提取。


srcs = html.xpath(src_xpath)
titles = html.xpath(title_path)
for src, title in zip(srcs, titles):
  download(src, title.text)

然后使用上面我编写好的 download 函数进行图片下载。

总结

好了,这样就大功告成了,程序可以源源不断地采集你想要的内容。

这节课,我想让你掌握的是:

1.Python 爬虫的流程;

2.了解 XPath 定位,JSON 对象解析;

3.如何使用 lxml 库,进行 XPath 的提取;

4.如何在 Python 中使用 Selenium 库来帮助你模拟浏览器,获取完整的 HTML。

其中,Python + Selenium + 第三方浏览器可以让我们处理多种复杂场景,包括网页动态加载、JS 响应、Post 表单等。因为 Selenium 模拟的就是一个真实的用户的操作行为,就不用担心 cookie 追踪和隐藏字段的干扰了。

当然,Python 还给我们提供了数据处理工具,比如 lxml 库和 JSON 库,这样就可以提取想要的内容了。

热门文章

暂无图片
编程学习 ·

Java输出数组的内容

Java输出数组的内容_一万个小时-CSDN博客_java打印数组内容1. 输出内容最常见的方式// List<String>类型的列表List<String> list new ArrayList<String>();list.add("First");list.add("Second");list.add("Third");list.ad…
暂无图片
编程学习 ·

母螳螂的“魅惑之术”

在它们对大蝗虫发起进攻的时候&#xff0c;我认认真真地观察了一次&#xff0c;因为它们突然像触电一样浑身痉挛起来&#xff0c;警觉地面对限前这个大家伙&#xff0c;然后放下自己优雅的身段和祈祷的双手&#xff0c;摆出了一个可怕的姿势。我被眼前的一幕吓到了&#xff0c;…
暂无图片
编程学习 ·

疯狂填词 mad_libs 第9章9.9.2

#win7 python3.7.0 import os,reos.chdir(d:\documents\program_language) file1open(.\疯狂填词_d9z9d2_r.txt) file2open(.\疯狂填词_d9z9d2_w.txt,w) words[ADJECTIVE,NOUN,VERB,NOUN] str1file1.read()#方法1 for word in words :word_replaceinput(fEnter a {word} :)str1…
暂无图片
编程学习 ·

HBASE 高可用

为了保证HBASE是高可用的,所依赖的HDFS和zookeeper也要是高可用的. 通过参数hbase.rootdir指定了连接到Hadoop的地址,mycluster表示为Hadoop的集群. HBASE本身的高可用很简单,只要在一个健康的集群其他节点通过命令 hbase-daemon.sh start master启动一个Hmaster进程,这个Hmast…
暂无图片
编程学习 ·

js事件操作语法

一、事件的绑定语法 语法形式1 事件监听 标签对象.addEventListener(click,function(){}); 语法形式2 on语法绑定 标签对象.onclick function(){} on语法是通过 等于赋值绑定的事件处理函数 , 等于赋值本质上执行的是覆盖赋值,后赋值的数据会覆盖之前存储的数据,也就是on…
暂无图片
编程学习 ·

Photoshop插件--晕影动态--选区--脚本开发--PS插件

文章目录1.插件界面2.关键代码2.1 选区2.2 动态晕影3.作者寄语PS是一款栅格图像编辑软件&#xff0c;具有许多强大的功能&#xff0c;本文演示如何通过脚本实现晕影动态和选区相关功能&#xff0c;展示从互联网收集而来的一个小插件&#xff0c;供大家学习交流&#xff0c;请勿…
暂无图片
编程学习 ·

vs LNK1104 无法打开文件“xxx.obj”

写在前面&#xff1a; 向大家推荐两本新书&#xff0c;《深度学习计算机视觉实战》和《学习OpenCV4&#xff1a;基于Python的算法实战》。 《深度学习计算机视觉实战》讲了计算机视觉理论基础&#xff0c;讲了案例项目&#xff0c;讲了模型部署&#xff0c;这些项目学会之后可以…
暂无图片
编程学习 ·

工业元宇宙的定义与实施路线图

工业元宇宙的定义与实施路线图 李正海 1 工业元宇宙 给大家做一个关于工业元宇宙的定义。对于工业&#xff0c;从设计的角度来讲&#xff0c;现在的设计人员已经做到了普遍的三维设计&#xff0c;但是进入元宇宙时代&#xff0c;就不仅仅只是三维设计了&#xff0c;我们的目…
暂无图片
编程学习 ·

【leectode 2022.1.15】完成一半题目

有 N 位扣友参加了微软与力扣举办了「以扣会友」线下活动。主办方提供了 2*N 道题目&#xff0c;整型数组 questions 中每个数字对应了每道题目所涉及的知识点类型。 若每位扣友选择不同的一题&#xff0c;请返回被选的 N 道题目至少包含多少种知识点类型。 示例 1&#xff1a…
暂无图片
编程学习 ·

js 面试题总结

一、js原型与原型链 1. prototype 每个函数都有一个prototype属性&#xff0c;被称为显示原型 2._ _proto_ _ 每个实例对象都会有_ _proto_ _属性,其被称为隐式原型 每一个实例对象的隐式原型_ _proto_ _属性指向自身构造函数的显式原型prototype 3. constructor 每个prot…
暂无图片
编程学习 ·

java练习代码

打印自定义行数的空心菱形练习代码如下 import java.util.Scanner; public class daYinLengXing{public static void main(String[] args) {System.out.println("请输入行数");Scanner myScanner new Scanner(System.in);int g myScanner.nextInt();int num g%2;//…
暂无图片
编程学习 ·

RocketMQ-什么是死信队列?怎么解决

目录 什么是死信队列 死信队列的特征 死信消息的处理 什么是死信队列 当一条消息初次消费失败&#xff0c;消息队列会自动进行消费重试&#xff1b;达到最大重试次数后&#xff0c;若消费依然失败&#xff0c;则表明消费者在正常情况下无法正确地消费该消息&#xff0c;此时…
暂无图片
编程学习 ·

项目 cg day04

第4章 lua、Canal实现广告缓存 学习目标 Lua介绍 Lua语法 输出、变量定义、数据类型、流程控制(if..)、循环操作、函数、表(数组)、模块OpenResty介绍(理解配置) 封装了Nginx&#xff0c;并且提供了Lua扩展&#xff0c;大大提升了Nginx对并发处理的能&#xff0c;10K-1000K Lu…
暂无图片
编程学习 ·

输出三角形

#include <stdio.h> int main() { int i,j; for(i0;i<5;i) { for(j0;j<i;j) { printf("*"); } printf("\n"); } }
暂无图片
编程学习 ·

stm32的BOOTLOADER学习1

序言 最近计划学习stm32的BOOTLOADER学习,把学习过程记录下来 因为现在网上STM32C8T6还是比较贵的,根据我的需求flash空间小一些也可以,所以我决定使用stm32c6t6.这个芯片的空间是32kb的。 #熟悉芯片内部的空间地址 1、flash ROM&#xff1a; 大小32KB&#xff0c;范围&#xf…
暂无图片
编程学习 ·

通过awk和shell来限制IP多次访问之学不会你打死我

学不会你打死我 今天我们用shell脚本&#xff0c;awk工具来分析日志来判断是否存在扫描器来进行破解网站密码——限制访问次数过多的IP地址&#xff0c;通过Iptables来进行限制。代码在末尾 首先我们要先查看日志的格式&#xff0c;分析出我们需要筛选的内容&#xff0c;日志…
暂无图片
编程学习 ·

Python - 如何像程序员一样思考

在为计算机编写程序之前&#xff0c;您必须学会如何像程序员一样思考。学习像程序员一样思考对任何学生都很有价值。以下步骤可帮助任何人学习编码并了解计算机科学的价值——即使他们不打算成为计算机科学家。 顾名思义&#xff0c;Python经常被想要学习编程的人用作第一语言…
暂无图片
编程学习 ·

蓝桥杯python-数字三角形

问题描述 虽然我前后用了三种做法&#xff0c;但是我发现只有“优化思路_1”可以通过蓝桥杯官网中的测评&#xff0c;但是如果用c/c的话&#xff0c;每个都通得过&#xff0c;足以可见python的效率之低&#xff08;但耐不住人家好用啊&#xff08;哭笑&#xff09;&#xff09…