请求模块 - Requests

Requests 是唯一的一个非转基因的 Python HTTP 库,人类可以安全享用。Requests 允许你发送纯天然,植物饲养的 HTTP/1.1 请求,无需手工劳动。你不需要手动为 URL 添加查询字串,也不需要对 POST 数据进行表单编码。Keep-alive 和 HTTP 连接池的功能是 100% 自动化的,一切动力都来自于根植在 Requests 内部的 urllib3。(解释源自python-requests.org)

安装:

  1. pip install requestes

以一个简单的抓取百度首页的爬虫为例:

# -*- coding: utf-8 -*-
import requests

url = 'http://www.baidu.com'

headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36'}

response = requests.get(url=url, headers=headers)

content = response.content.decode()

print(content)

注释:

  1. 接收两个参数: 第一个是URL,第二个是请求头, 这里包含一个User-Agent(用户代理)
  2. 使用 get 方式进行请求
  3. 返回的数据使用 response 接收
  4. 使用 decode() 进行解码(默认使用utf8进行解码), 使用的时候可以加上参数, 指定其编码方式以及时候忽略错误, 比如:
content = response.content.decode('gb2312', 'ignore')

通常情况下,在获取某些get请求的内容而非post请求的内容时,我们只需要将UA修改成一般浏览器的UA就好了,无需增加其他请求头。

网页解析模块 - BeautifulSoup

BeautifulSoup 是一个可以从HTML或XML文件中提取数据的Python库。它能够通过你喜欢的转换器实现惯用的文档导航,查找,修改文档的方式。Beautiful Soup会帮你节省数小时甚至数天的工作时间。

安装:

pip install bs4

以下示例, 爬取一个简单的静态网页:

# -*- coding: utf-8 -*-

from bs4 import BeautifulSoup
import requests
import os

url = 'https://www.dbmeinv.com/'
headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36' }
response = requests.get(url=url, headers=headers)
content = response.content.decode()

soup = BeautifulSoup(content, 'html.parser')  # 注释1
img_list = soup.find_all(name='img', class_='height_min')  # 注释2

for img in img_list:  # 注释3
    src = img.attrs['src']
    title = img.attrs['title']  # 注释4
    response = requests.get(url=src, headers=headers)
    content = response.content

    imagesPath = 'images'
    if not os.path.exists(imagesPath):
        os.makedirs(imagesPath)
    with open('%s/%s.jpg' % (imagesPath, title), 'wb') as f:  # 注释5
        f.write(content)

比如安装 lxml HTML 解析器: pip install lxml

如果安装不成功, 可以到 Unofficial Windows Binaries for Python Extension Packages 下载 lxml 模块, 比如 lxml-4.1.1-cp35-cp35m-win32.whl, 下载完成后到下载目录执行 pip install lxml-4.1.1-cp35-cp35m-win32.whl 即可安装。

  • 注释2:这里使用了soup对象的一个方法”findall()”,字面理解就是”找出所有的”,那么找出什么,如何定位这个所谓的”什么”?这里就要传入两个参数,第一个是HTML文档的节点名,也可以理解为HTML的标签名;第二个则是该节点的class类名,比如上面代码中,我要找出该网页上所有的img节点,且我需要的img节点的类名为”height_min”, 因为calss和关键字冲突,所以改名`class`。但是对于一些没有class类名的HTML元素我们该如何寻找?

我们还可以用到另一个属性:attrs,比如这里可以写成:

img_list = soup.find_all(name='img', attrs={'class': 'height_min'})

attrs是字典类型,冒号左边为关键字,右边为关键字的值。不一定要通过class来查找某一个元素,也可以通过比如”id”,”name”,”type”等各种HTML的属性,如果想要的元素实在没有其他属性,可以先定位到该元素的父属性,再使用.children定位到该元素。

  • 注释3:注释2返回的是一个列表对象,包含了整张网页上的图片,因此这里用一个循环,分别处理每一张图片。
  • 注释4:取出了图片的路径和标题。
  • 注释5:这里需要重新请求图片的地址,获得图片二进制的返回值,因为是图片,所以不能用decode()解码,必须以二进制的方式写入,后面的写入模式”wb”,加了个”b”就是表示以二进制的形式。

也可以将解码的工作放到 bs4 中:

response = requests.get(url=url, headers=headers)
soup = BeautifulSoup(response.content, 'html.parser', from_encoding="utf-8")

如果本身是 utf-8 编码,可省略 from_encoding 参数。

数据库模块 - pymysql

可以使用 pymysql 模块, 将爬虫获取到的数据存储到 MySQL 数据库, 例如爬取斗图网1-1000页的图片:

# -*- coding: utf-8 -*-

import requests
import re
import pymysql

# 连接数据库
db = pymysql.connect(host='127.0.0.1', port = 3306, db='test', user='root', passwd='root', charset='utf8')

# 创建游标
cursor = db.cursor()

# 获取斗图王图片
def getImgesList(page = 1):
    html = requests.get('http://www.doutula.com/photo/list/?page={}'.format(page)).text
    reg = r'data-original="(.*?)".*?alt="(.*?)"'
    # S 多行匹配,提升效率
    reg = re.compile(reg, re.S)
    imagesList = re.findall(reg, html)
    for i in imagesList:
        cursor.execute("insert into img(`title`, `src`) values ('{}', '{}')".format(i[1], i[0]))
        print('正在保存 %s' %i[1])
    db.commit()

for i in range(1, 1001):
    getImgesList(i)
    print('第{}页'.format(i))
  1. 使用 pymysql.connect 进行数据库连接
  2. 使用 db.cursor() 创建游标
  3. 使用 re.compile(reg, re.S) 执行正则匹配
  4. findall()返回的是括号所匹配到的结果,多个括号就会返回多个括号分别匹配到的结果(得到一个元组数组)
  5. 使用 cursor.execute 执行SQL语句
  6. 使用 db.commit() 进行数据库提交