在 urllib3 和 Beautiful Soup 中抓取 Python.org

在本节中,我们将 requests 的使用替换为另一个库 urllib3。 这是另一个通用库,用于从 URL 检索数据以及涉及 URL 的其他功能,例如解析实际 URL 的各个部分和处理各种编码。

准备工作

此食谱需要安装 urllib3。 所以用 pip 安装它:

$ pip install urllib3
Collecting urllib3
Using cached urllib3-1.22-py2.py3-none-any.whl
Installing collected packages: urllib3
Successfully installed urllib3-1.22

怎么做

该配方在 01/02_events_with_urllib3.py 中实现。 代码如下:

import urllib3
from bs4 import BeautifulSoup

def get_upcoming_events(url):
    req = urllib3.PoolManager()
    res = req.request('GET', url)

    soup = BeautifulSoup(res.data, 'html.parser')

    events = soup.find('ul', {'class': 'list-recent-events'}).findAll('li')

    for event in events:
        event_details = dict()
        event_details['name'] = event.find('h3').find("a").text
        event_details['location'] = event.find('span', {'class', 'event-location'}).text
        event_details['time'] = event.find('time').text
        print(event_details)

get_upcoming_events('https://www.python.org/events/python-events/')

使用 python 解释器运行它。 您将获得与之前的配方相同的输出。

怎么运行

这个秘籍中唯一的区别是我们获取资源的方式:

req = urllib3.PoolManager()
res = req.request('GET', url)

与 Requests 不同,urllib3 不会自动应用标头编码。 前面示例中的代码片段之所以有效,是因为 BS4 能够完美地处理编码。 但您应该记住,编码是抓取的重要组成部分。 如果您决定使用自己的框架或使用其他库,请确保编码处理良好。

还有更多

Requests 和 urllib3 在功能方面非常相似。 在发出 HTTP 请求时,通常建议使用 Requests。 以下代码示例说明了一些高级功能:

import requests
# builds on top of urllib3's connection pooling
# session reuses the same TCP connection if
# requests are made to the same host
# see https://en.wikipedia.org/wiki/HTTP_persistent_connection for details
session = requests.Session()

# You may pass in custom cookie
r = session.get('http://httpbin.org/get', cookies={'my-cookie': 'browser'})
print(r.text)
# '{"cookies": {"my-cookie": "test cookie"}}'

# Streaming is another nifty feature
# From
http://docs.python-requests.org/en/master/user/advanced/#streaming-requests
# copyright belongs to reques.org
r = requests.get('http://httpbin.org/stream/20', stream=True)
for line in r.iter_lines():
    # filter out keep-alive new lines
    if line:
        decoded_line = line.decode('utf-8')
        print(json.loads(decoded_line))