02.数据采集和解析.md 4.6 KB
Newer Older
骆昊的技术专栏's avatar
骆昊的技术专栏 已提交
1 2
## 数据采集和解析

3 4 5 6
通过上一个章节,我们已经了解到了开发一个爬虫需要做的工作以及一些常见的问题,至此我们可以对爬虫开发需要做的工作以及相关的技术做一个简单的汇总,可能有些库我们之前并没有使用过,不过别担心,这些内容我们都会讲到的。

1. 下载数据 - urllib / requests / aiohttp。
2. 解析数据 - re / lxml / beautifulsoup4(bs4)/ pyquery。
7
3. 缓存和持久化 - pymysql / redis / sqlalchemy / peewee / pymongo。
8 9 10
4. 生成摘要 - hashlib。
5. 序列化和压缩 - pickle / json / zlib。
6. 调度器 - 进程 / 线程 / 协程。
11

骆昊的技术专栏's avatar
骆昊的技术专栏 已提交
12 13
### HTML页面分析

14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
```HTML
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>首页</title>
    </head>
    <body>
        <h1>Hello, world!</h1>
        <p>这是一个神奇的网站!</p>
        <hr>
        <div>
            <h2>这是一个例子程序</h2>
            <p>静夜思</p>
            <p class="foo">床前明月光</p>
            <p id="bar">疑似地上霜</p>
            <p class="foo">举头望明月</p>
            <div><a href="http://www.baidu.com"><p>低头思故乡</p></a></div>
        </div>
        <a class="foo" href="http://www.qq.com">腾讯网</a>
        <img src="./img/pretty-girl.png" alt="美女">
        <img src="./img/hellokitty.png" alt="凯蒂猫">
        <img src="/static/img/pretty-girl.png" alt="美女">
        <table>
            <tr>
                <th>姓名</th>
                <th>上场时间</th>
                <th>得分</th>
                <th>篮板</th>
                <th>助攻</th>
            </tr>
        </table>
    </body>
</html>
```

如果你对上面的代码并不感到陌生,那么你一定知道HTML页面通常由三部分构成,分别是:用来承载内容的Tag(标签)、负责渲染页面的CSS(层叠样式表)以及控制交互式行为的JavaScript。通常,我们可以在浏览器的右键菜单中通过“查看网页源代码”的方式获取网页的代码并了解页面的结构;当然,我们也可以通过浏览器提供的开发人员工具来了解网页更多的信息。

#### 使用requests获取页面

1. GET请求和POST请求。
2. URL参数和请求头。
3. 复杂的POST请求(文件上传)。
4. 操作Cookie。
58 59
5. 设置代理服务器。
6. 超时设置。
60

61
> 说明:关于requests的详细用法可以参考它的[官方文档](http://docs.python-requests.org/zh_CN/latest/user/quickstart.html)。
骆昊的技术专栏's avatar
骆昊的技术专栏 已提交
62

63 64 65
### 四种采集方式

#### 四种采集方式的比较
66 67 68 69 70 71

| 抓取方法   | 速度                  | 使用难度 | 备注                                       |
| ---------- | --------------------- | -------- | ------------------------------------------ |
| 正则表达式 | 快                    | 困难     | 常用正则表达式<br>在线正则表达式测试       |
| lxml       | 快                    | 一般     | 需要安装C语言依赖库<br>唯一支持XML的解析器 |
| Beautiful  | 快/慢(取决于解析器) | 简单     |                                            |
72
| PyQuery    | 较快                  | 简单     | Python版的jQuery                           |
73 74 75 76

> 说明:Beautiful的解析器包括:Python标准库(html.parser)、lxml的HTML解析器、lxml的XML解析器和html5lib。

#### BeautifulSoup的使用
骆昊的技术专栏's avatar
骆昊的技术专栏 已提交
77

78 79 80 81 82 83 84 85 86 87 88 89
1. 遍历文档树
   - 获取标签
   - 获取标签属性
   - 获取标签内容
   - 获取子(孙)节点
   - 获取父节点/祖先节点
   - 获取兄弟节点
2. 搜索树节点
   - find / find_all:字符串、正则表达式、列表、True、函数或Lambda。
   - select_one / select:CSS选择器

> 说明:更多内容可以参考BeautifulSoup的[官方文档]()。
骆昊的技术专栏's avatar
骆昊的技术专栏 已提交
90

91
### 实例 - 获取知乎发现上的问题链接
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127

```Python
from urllib.parse import urljoin

import re
import requests

from bs4 import BeautifulSoup


def main():
    headers = {'user-agent': 'Baiduspider'}
    proxies = {
        'http': 'http://122.114.31.177:808'
    }
    base_url = 'https://www.zhihu.com/'
    seed_url = urljoin(base_url, 'explore')
    resp = requests.get(seed_url,
                        headers=headers,
                        proxies=proxies)
    soup = BeautifulSoup(resp.text, 'lxml')
    href_regex = re.compile(r'^/question')
    link_set = set()
    for a_tag in soup.find_all('a', {'href': href_regex}):
        if 'href' in a_tag.attrs:
            href = a_tag.attrs['href']
            full_url = urljoin(base_url, href)
            link_set.add(full_url)
    print('Total %d question pages found.' % len(link_set))


if __name__ == '__main__':
    main()

```