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

3
通过[《网络爬虫和相关工具》](./01.网络爬虫和相关工具.md)一文,我们已经了解到了开发一个爬虫需要做的工作以及一些常见的问题,至此我们可以对爬虫开发需要做的工作以及相关的技术做一个简单的汇总,这其中可能会有一些我们之前没有使用过的第三方库,不过别担心,这些内容我们稍后都会一一讲到。
4 5 6

1. 下载数据 - urllib / requests / aiohttp。
2. 解析数据 - re / lxml / beautifulsoup4(bs4)/ pyquery。
7 8
3. 缓存和持久化 - pymysql / sqlalchemy / peewee/ redis / pymongo。
4. 生成数字签名 - hashlib。
9
5. 序列化和压缩 - pickle / json / zlib。
10
6. 调度器 - 进程(multiprocessing) / 线程(threading) / 协程(coroutine)。
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
```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>
```

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

#### 使用requests获取页面

1. GET请求和POST请求。
55 56 57 58 59 60

   ```Python
   
   
   ```

61
2. URL参数和请求头。
62 63 64 65 66 67

   ```Python
   
   
   ```

68
3. 复杂的POST请求(文件上传)。
69 70 71 72 73 74

   ```Python
   
   
   ```

75
4. 操作Cookie。
76 77 78 79 80 81

   ```Python
   
   
   ```

82
5. 设置代理服务器。
83 84 85 86 87

   ```Python
   
   
   ```
88

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

91 92 93
### 四种采集方式

#### 四种采集方式的比较
94

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

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

104 105 106 107 108 109 110 111
#### 使用正则表达式

如果你对正则表达式没有任何的概念,那么推荐先阅读[《正则表达式30分钟入门教程》](),然后再阅读我们之前讲解在Python中如何使用正则表达式一文。

#### 使用XPath和Lxml



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

114 115
BeautifulSoup是一个可以从HTML或XML文件中提取数据的Python库。它能够通过你喜欢的转换器实现惯用的文档导航、查找、修改文档的方式。

116 117 118 119 120 121 122 123 124 125 126
1. 遍历文档树
   - 获取标签
   - 获取标签属性
   - 获取标签内容
   - 获取子(孙)节点
   - 获取父节点/祖先节点
   - 获取兄弟节点
2. 搜索树节点
   - find / find_all:字符串、正则表达式、列表、True、函数或Lambda。
   - select_one / select:CSS选择器

127
> 说明:更多内容可以参考BeautifulSoup的[官方文档](https://www.crummy.com/software/BeautifulSoup/bs4/doc/index.zh.html)。
骆昊的技术专栏's avatar
骆昊的技术专栏 已提交
128

129 130 131 132 133 134
#### PyQuery的使用

pyquery相当于jQuery的Python实现,可以用于解析HTML网页。



135
### 实例 - 获取知乎发现上的问题链接
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170

```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()
```