2

本篇内容为 python 网络爬虫初级操作的简单介绍,内容主要有以下 2 部分:

  • 解析网页
  • 数据库

解析网页

一般来说,解析网页有三种方式:正则表达式、BeautifulSoup、lxml。其中正则表达式较难,BeautifulSoup 适合初学者,可以快速掌握提取网页中数据的方法。

正则表达式

常见的正则字符和含义如下:

.    匹配任意字符,除了换行符
*     匹配前一个字符 0 次或多次
+    匹配前一个字符 1 次或多次
?    匹配前一个字符 0 次或 1 次

^    匹配字符串开头
$    匹配字符串末尾

()    匹配括号内表示式,也表示一个组

\s    匹配空白字符
\S    匹配任何非空白字符

\d    匹配数字,等价于[0-9]
\D    匹配任何非数字,等价于[^0-9]

\w    匹配字母数字,等价于[A-Za-z0-9]
\W    匹配非字母数字,等价于[^A-Za-z0-9]

[]    用来表示一组字符

Python 正则表达式有以下 3 种方法:
re.match 方法:从字符串起始位置匹配一个模式,如果从起始位置匹配了,match()就返回none。
语法 re.match(pattern, string, flags=0)
pattern:正则表达式
string:要匹配的字符串
flags:控制正则表达式的匹配方式,如 是否区分大小写、多行匹配等

re.search方法:只能从字符串的起始位置进行匹配。

find_all方法:可以找到所有的匹配。

BeautifulSoup

BeautifulSoupHTMLXML 文件中提取数据。首先需要使用命令行来进行安装:

pip install bs4

在使用的时候需要导入:

from bs4 import BeautifulSoup

例如使用 BeautifulSoup 获取博客主页文章的标题,代码和注释如下:

import requests
from bs4 import BeautifulSoup

link = 'http://www.santostang.com/'
headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36'}
r = requests.get(link, headers=headers)
# 将网页响应体的字符串转换为soup对象
soup = BeautifulSoup(r.text, 'html.parser')
first_title = soup.find('h1', class_='post-title').a.text.strip()
print('第一篇文章的标题是:', first_title)

title_list = soup.find_all('h1', class_='post-title')

for i in range(len(title_list)):
    title = title_list[i].a.text.strip()

    print('第 %s 篇文章的标题是: %s' % (i+1, title))


运行得到结果:
图片描述

成功抓取到所需内容。

关于 BeautifulSoup, 我们最后再来看一个实战项目:爬取北京二手房价格。代码如下:

import requests
from bs4 import BeautifulSoup
import time

headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36'}

for i in range(1,11):
    link = 'https://beijing.anjuke.com/sale/'
    r = requests.get(link, headers=headers)
    print('第', i, '页')

    soup = BeautifulSoup(r.text, 'lxml')
    house_list = soup.find_all('li', class_='list-item')

    for house in house_list:
        name = house.find('div', class_='house-title').a.text.strip()
        price = house.find('span', class_='price-det').text.strip()
        price_area = house.find('span', class_='unit-price').text.strip()

        no_room = house.find('div', class_='details-item').span.text
        area = house.find('div', class_='details-item').contents[3].text
        floor = house.find('div', class_='details-item').contents[5].text
        year = house.find('div', class_='details-item').contents[7].text
        broker = house.find('span', class_='brokername').text
        broker = broker[1:]
        address = house.find('span', class_='comm-address').text.strip()
        address = address.replace('\xa0\xa0\n                 ', '    ')
        tag_list = house.find_all('span', class_='item-tags')
        tags = [i.text for i in tag_list]
        print(name, price, price_area, no_room, area, floor, year, broker, address, tags)
    time.sleep(5)

这样就成功爬取了安居客上前 10 页的北京二手房价格。

数据库

数据存储分为两种,存储在文件(TXT和CSV)中和存储在数据库(MySQL关系数据库和MongoDB数据库)中。

CSV (Comma-Separated Values)是逗号分隔值的文件格式,其文件以纯文本的形式存储表格数据(数字和文本)。
CSV 文件的每一行都用换行符分隔,列与列之间用逗号分隔。

MySQL是一种关系数据库管理系统,所使用的是SQL语言,是访问数据库最常用的标准化语言。关系数据库(建立在关系模型基础上的数据库)将数据保存在不同的表中,而不是将所有数据放在一个大仓库内,这样就增加了写入和提取的速度,数据的存储也比较灵活。

关于存储在文件的方法这里不再赘述,下面首先介绍如何存储至MySQL数据库。

你需要先到官网下载并安装 MySQL数据库,博主用的是 macOS Sierra 系统,在安装完成后,打开系统偏好设置,如下图:
图片描述

最下方出现 MySQL的图标,打开并连接,如下图所示:
图片描述

打开终端,在终端中输入添加MySQL路径的命令:

PATH="$PATH":/usr/local/mysql/bin

继续输入登录到MySQL的命令:mysql -u root -p,然后输入密码即可成功登录。成功登录界面如下:
图片描述

接下来介绍MySQL的基本操作:

  • 创建数据库

图片描述

  • 创建数据表

创建数据表必须指明每一列数据的名称(column_name)和类别(column_type)。
图片描述
在上图中,创建了 4 个变量:id, url, content, created_time。其中id的类别是整数INT,属性为自己增加(AUTO_INCREMENT)。新添加数据的数值会自动加 1。PRIMARY KEY的关键字用于将id定义为主键。

urlcontent的类别是可变长度的字符串VARCHAR,括号中的数字代表长度的最大值,NOT NULL表示urlcontent不能为空。created_time为该数据添加时间,不需要设置,因为有时间戳,它会自动根据当时的时间填入。

创建数据表后,可查看数据表的结构:
图片描述

  • 在数据表中插入数据

图片描述

这里插入了urlcontent两个属性,id是自动递增的,created_time是数据加入的时间戳,这两个变量会自动填入。

  • 从数据表中提取数据

图片描述

由上图,我们可以看到提取数据有 3 种方法:
(1)将id等于 1 的数据行提取出来;
(2)提取只看部分字段的数据;
(3)提取包含部分内容的数据。

  • 删除数据

图片描述

⚠️注意,如果没有指定 WHERE 子句,用DELETE FROM urls将会导致MySQL表中的所有记录被删除,即误删除整张表。

  • 修改数据

图片描述

由于idcreated_time是数据库自动填入的,因此这一行数据的id为 2。

更多操作可参考菜鸟教程

下面介绍使用Python操作MySQL数据库,依次使用下令命令安装mysqlclient

brew install mysql
export PATH=$PATH:/usr/local/mysql/bin
pip install MySQL-Python
pip3 install mysqlclient

出现下列文字即安装成功:
图片描述

Python操作MySQL数据库,我们以在博客爬取标题和 url 地址为例,具体代码和解释如下:

#coding=UTF-8
import MySQLdb
import requests
from bs4 import BeautifulSoup

# connect() 方法用于创建数据库的连接,里面可以指定参数:用户名,密码,主机等信息
#这只是连接到了数据库,要想操作数据库需要创建游标
conn = MySQLdb.connect(host='localhost', user='root', passwd='your_password', db='MyScraping', charset='utf8')
# 通过获取到的数据库连接conn下的cursor()方法来创建游标。
cur=conn.cursor()

link = 'http://www.santostang.com/'
headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36'}
r = requests.get(link, headers=headers)

soup = BeautifulSoup(r.text, 'html.parser')
title_list = soup.find_all('h1', class_='post-title')
for eachone in title_list:
    url = eachone.a['href']
    title = eachone.a.text.strip()
    # 创建数据表,通过游标cur 操作execute()方法可以写入纯sql语句。通过execute()方法中写如sql语句来对数据进行操作
    cur.execute('INSERT INTO urls (url, content) VALUES (%s, %s)', (url, title))

cur.close()
conn.commit()
conn.close()

最后,我们来介绍如何存储至MongoDB数据库。

首先要知道NoSQL泛指非关系型数据库,数据之间无关系,具有非常高的读写性能,而MongoDB是其中非常流行的一种数据库。它是一种关系数据库管理系统,所使用的是SQL语言,是访问数据库最常用的标准化语言。

下面仍以上述的在博客爬取标题和 url 地址为例。

第一步连接 MongoDB客户端,然后连接数据库blog_database,再选择该数据的集合blog。如果它们不存在,就会自动创建一个,代码示例如下:

from pymongo import MongoClient

client = MongoClient('localhost', 27017)
db = client.blog_database
collection = db.blog

第二步爬取博客主页的所有文章标题存储至MongoDB数据库,代码如下:

import requests
import datetime
from bs4 import BeautifulSoup
from pymongo import MongoClient

client = MongoClient('localhost', 27017)
db = client.blog_database
collection = db.blog

link = 'http://www.santostang.com/'
headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36'}
r = requests.get(link, headers=headers)

soup = BeautifulSoup(r.text, 'html.parser')
title_list = soup.find_all('h1', class_='post-title')
for eachone in title_list:
    url = eachone.a['href']
    title = eachone.a.text.strip()
    post = {'url': url,
            'title': title,
            'date': datetime.datetime.utcnow()

    }
    collection.insert_one(post)

重点在最后一部分的代码,首先将爬虫获取的数据存入post的字典中,然后使用insert_one加入集合collection中。

最后,启动MongoDB查看结果。

打开终端输入:

sudo mongod --config /usr/local/etc/mongod.conf

确认权限后,保持当前终端不关,新建终端依次输入:

mongod

mongo

出现以下文字表示连接成功:
图片描述

然后,输入:

use blog_database

db.blog.find().pretty()

就查询到数据集合的数据了,如下图所示:
图片描述

同时注意到,它是JSON格式的。

更多使用 Python 来操作 MongoDB 数据库的知识,可以参考 PyMongo官网


本文为崔庆才博客和唐松的《Python网络爬虫从入门到实践》学习记录与总结,具体内容可参考二者。博主在学习过程中的练习代码也已上传至 GitHub

不足之处,欢迎指正。


秋刀鱼
266 声望66 粉丝

做一件事最重要的是开心🏊