目录

Requests 访问页面

XPath 定位

JSON 对象

如何使用 XPath 自动下载百度图片

Selenium 库模拟浏览器


Requests 访问页面

Requests 是 Python HTTP 的客户端库,编写爬虫的时候都会用到,编写起来也很简单。它有两种访问方式:Get 和 Post。这两者最直观的区别就是:Get 把参数包含在 url 中,而 Post 通过 request body 来传递参数。

假设我们想访问豆瓣,那么用 Get 访问的话,代码可以写成下面这样的:

r = requests.get('http://https://image.baidu.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 的路径语言,实际上是通过元素和属性进行导航,帮我们定位位置。它有几种常用的路径表达方式。

Python爬虫:如何自动化下载网站图片_python

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

  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 对象,我们对数据进行解析就更方便了。

Python爬虫:如何自动化下载网站图片_爬虫_02

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

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

 

如何使用 XPath 自动下载百度图片

如果你遇到 JSON 的数据格式,那么恭喜你,数据结构很清爽,通过 Python 的 JSON 库就可以解析。但有时候,网页会用 JS 请求数据,那么只有 JS 都加载完之后,我们才能获取完整的 HTML 文件。XPath 可以不受加载的限制,帮我们定位想要的元素。

JSON 数据格式

# 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']) # 下载一张图片

HTML数据格式 

import requests as requests
from lxml import etree
import base64

def download(src, id):

    try:
        if src.startswith('data'):
            #base64数据格式  data:image/png;base64
            index = src.index("/")
            suffix = src[index+1:index+4] +"."
            dir = './' + str(id) + suffix
            request_base64='''   '''
            imgdata = base64.b64decode(request_base64)
            with open(dir, 'wb') as fh:
                fh.write(imgdata)
        else:
            suffix = src[src.rindex("."):len(src)]
            dir = './' + str(id) + suffix
            pic = requests.get(src, timeout=10)
            fp = open(dir, 'wb')
            fp.write(pic.content)
            fp.close()

    except requests.exceptions.ConnectionError:
            print('图片无法下载')

if __name__ == '__main__':

    url = 'https://image.baidu.com/'
    html = requests.get(url).text
    # 得到返回结果
    response = etree.HTML(html)

    results = response.xpath('//img/@src')

    i = 0
    for url in results:
        if  url:
            print(url)  # 查看当前下载的图片网址
            download(url, i )  # 下载一张图片
            i+=1

Selenium 库模拟浏览器

在 Python 中,这个工具就是 Selenium 库,使用方法如下:

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

Selenium 是 Web 应用的测试工具,可以直接运行在浏览器中,它的原理是模拟用户在进行操作,支持当前多种主流的浏览器。

这里我们模拟 Chrome 浏览器的页面访问。

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

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