0%

python操作流程及爬取豆瓣图片

常见的数据来源

类别 解释 例子
开放数据源 重要是行业数据库,政府公开的各类数据 国家统计局、wind、巨潮资讯网
爬虫爬取的数据 通过爬虫取得的数据 豆瓣、社交网站、电商网站、图片网站
传感器采集 通过传感器采集到的数据
日志采集 应用埋点采集到的数据

爬取数据的工具

火车采集器。可以做抓取工具,也可以做数据清洗、数据分析、数据挖掘和可视化等工作。

八爪鱼。可以实现自动云采集。

集搜客。缺点是没有云采集功能,所有爬虫都是在用户自己电脑上跑的。

爬虫的操作流程

爬虫模拟我们日常获取网页信息的流程,通过计算机程序自动化爬取内容。

包括三个阶段:

  • 打开网页。工具为Requests,数据包括 HTML 页面以及 JSON 数据。
  • 爬取数据。针对HTML页面使用XPath提取数据,针对JSON数据使用JSON库进行解析。
  • 保存数据。可以使用Pandas保存数据,导出为CSV文件。

三个阶段解析

Requests

Requests有两种访问方式,Get和Post。

其中Get把参数包含在链接中。

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

Post通过request body传递参数。

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

data的数据结构是字典,通过key 和 value 对数据储存。

动态数据需要通过XHR发出HTTP请求。

Xpath

XPath 是 XML 的路径语言,帮助定位位置。

使用Xpath解析规则

在 XPath 中,有七种类型的节点:元素、属性、文本、命名空间、处理指令、注释以及文档(根)节点。

表达式 描述
node 选取此节点的所有子节点
/ 从根节点选取
// 选取所有的当前节点,不考虑位置
. 选取当前节点
.. 选取当前节点的父节点
@ 选取属性
或,两个节点的合并
text() 当前路径下的文版内容

下面用这个网站上的例子举例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?xml version="1.0" encoding="ISO-8859-1"?>

<bookstore>

<book>
<title lang="eng">Harry Potter</title>
<price>29.99</price>
</book>

<book>
<title lang="eng">Learning XML</title>
<price>39.95</price>
</book>

</bookstore>
路径表达式 结果
/bookstore/book[1] 选取属于 bookstore 子元素的第一个 book 元素。
/bookstore/book[last()] 选取属于 bookstore 子元素的最后一个 book 元素。
/bookstore/book[last()-1] 选取属于 bookstore 子元素的倒数第二个 book 元素。
/bookstore/book[position()<3] 选取最前面的两个属于 bookstore 元素的子元素的 book 元素。
//title[@lang] 选取所有拥有名为 lang 的属性的 title 元素。
//title[@lang=’eng’] 选取所有 title 元素,且这些元素拥有值为 eng 的 lang 属性。
/bookstore/book[price>35.00] 选取 bookstore 元素的所有 book 元素,且其中的 price 元素的值须大于 35.00。
/bookstore/book[price>35.00]/title 选取 bookstore 元素中的 book 元素的所有 title 元素,且其中的 price 元素的值须大于 35.00。

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

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

xpath(’//book[@id=“abc”]’) 选取所有 book 元素,且这些 book 元素拥有 id= “abc”的属性;

xpath(’//book/title | //book/price’) 选取 book 元素的所有 title 和 price 元素。

定位到所有列表项目,需要使用lxml,下面代码为定位到HTML所有列表函数。

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

JSON

Json.dumps():将python对象转换成ISON对象。

Json.load():将python对象转换成JSON对象。

1
2
3
4
5
6
7
import json

jsonData = '{"a":1,"b":2,"c":3,"d":4,"e":5}';

input = json.loads(jsonData)

print(input)

输出结果为:

1
{'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}

项目实战:爬取葛优相关图片

步骤一:打开网页

打开豆瓣图片,输入关键词葛优

image-20200901195719609

步骤二:选择图片

在搜索结果中,可以看到网页是动态的(即往下滑可以看到更多的图片),动态数据需要通过XHR发出HTTP请求,此处需要知道JSON。

我们先来寻找XHR结构,方法是通过:1)谷歌浏览器右键单击检查;2)选择Network;3)选择XHR;4)刷新页面。从图片中可以看到共有1724张葛优相关的图片。

image-20200901200213885

从上图最下面的方框中可以看到JSON。可以看到数据被放到images里面,每张图片通过字典形式储存,元数据包含author、height、id、src、title、width等信息,有了这些信息,我们便可以提取需要的数据。

在看一下图片的组成,limit:20,最大可以显示20张,第一张图片从0开始,我们便可以写个for循环实现所有的下载。

1
2
3
4
5
6
7
8
9
10
11
12
images: [{src: "https://img3.doubanio.com/view/photo/photo/public/p399074242.jpg", author: "饭",},]
0: {src: "https://img3.doubanio.com/view/photo/photo/public/p399074242.jpg", author: "饭",}
author: "饭"
height: 600
id: "399074242"
src: "https://img3.doubanio.com/view/photo/photo/public/p399074242.jpg"
title: "葛优"
url: "https://www.douban.com/link2/?url=http%3A%2F%2Fwww.douban.com%2Fphotos%2Fphoto%2F399074242%2F&query=%E8%91%9B%E4%BC%98&cat_id=1025&type=search"
width: 414
limit: 20
more: true
total: 1724

提取需要的信息

找到了网页及所需要的信息,接下里就是提取所需要的数据,并且进行储存。

完整代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# -*- 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, 1723, 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教程

ChangeLog

20201029 补充Xpath案例,仍然出现错误Expecting value: line 1 column 1 (char 0)

20200901 爬虫代码运行错误