本文主要是针对 Web Scraping with Python: Everything you need to know (2022) 的翻译,合适入门网页爬取和页面调试,如有任何不正确恳求纠正

任何爬虫行为都或许存在法律风险,请谨慎对待,且与本文无关

简介:

在本文中将介绍简直一切与Python 相关的网页抓取东西。从根底到高档,包括每个的长处和缺陷。当然,咱们不能包括到每个东西的方方面面,可是这篇文章会告诉你关于每个东西做什么,以及什么时候运用它们

留意: 以下一切的python皆为python3(pip对应pip3)

0. 网络根底

互联网是杂乱的:在阅读器中拜访一个简略的网页时,触及到许多底层技术和概念。本文的方针不是深化评论这儿的每个细节,而是为您供给运用 Python 从 Web 提取数据这块最重要部分。

超文本传输协议

超文本传输协议(HTTP)运用客户端/服务器模型。客户端翻开衔接并向 HTTP 服务器发送音讯(“ I want to see that page:/product”),然后服务器呼应(如 HTML 代码)并封闭衔接。

HTTP 之所以被称为无状况协议,是由于每个恳求(恳求/呼应)都是独立的。FTP 是有状况的,由于它坚持衔接。

当你在阅读器中输入一个网站地址时,HTTP 恳求看起来是这样的:

GET /product/ HTTP/1.1
Host: example.com
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding: gzip, deflate, sdch, br
Connection: keep-alive
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 12_3_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36

在此恳求的榜首行中,您能够看到以下内容:

  • Method:http的恳求办法,在此比如中时GET, 表明咱们希望获取数据。还有许多其他 HTTP 办法可用(例如用于上传数据) ,而且有一个完好的列表here 给你.
  • 文件、目录或方针的途径:在此实例中是根方针下 product对应的文件夹
  • HTTP协议版本:在本教程中,咱们运用 HTTP1
  • 其他更多恳求头字段:Connection,User-Agent…,这儿有一个详尽的名单HTTP headers

下面是最重要的标题字段:

  • Host:这个音讯头表明您发送恳求的主机名。这个音讯头关于根据称号的虚拟主机尤为重要,目前是互联网国际的规范
  • User-Agent:其间包括有关发起恳求的客户端(包括操作体系)的信息。在这种状况下,它是我在 macOS 上的阅读器(Chrome)。这个头很重要,由于它要么用于统计(有多少用户拜访我的网站在移动对桌面)或防止违反机器人。由于这些头是由客户端发送的,所以能够修正它们(“Header Spoofing” “头部欺骗”)。这儿是需求咱们设置的,让抓取恳求看起来像一个一般的网络阅读器恳求
  • Accept: 这是一份 MIME types类型, 有许多不同的内容类型和子类型:text/plain, text/html, image/jpeg, application/json 文本/纯文本,文本/html,图像/jpeg,运用程序/json …
  • Cookie:此头字段包括称号-值对列表(name1 = value1; name2 = value2)。Cookies 是网站在你的机器上存储数据的一种办法。这可所以一个特定的过期日期(规范 Cookie) ,也可所以在封闭阅读器(会话 Cookie)之前的暂时过期。Cookie 被用于许多不同的目的,从身份验证信息,到用户偏好等,比方运用个性化的、唯一的用户标识符进行用户盯梢。而且,关于鉴权认证,这是阅读器十分重要的功能。当您提交登录时,服务器将验证您的凭证,假如您供给了有效的登录,则会回来会话 cookie,它将清楚地标识您的特定用户帐户的用户会话。当服务器收到cookie,会在在后续恳求带上此cookie
  • Referer: 这个字段包括恳求URL的实践来源。这个头很重要,由于网站运用这个头来改动他们的行为根据用户来自哪里。例如,许多新闻网站都有付费订阅,只答应你阅读10% 的文章,可是假如用户来自像 Reddit 这样的新闻聚合网站,他们就答应你阅读完好的内容。他们运用引用来查看这个。有时候,咱们将不得不欺骗这个标题,以取得咱们想要提取的内容

服务器的呼应如下:

HTTP/1.1 200 OK
Server: nginx/1.4.6 (Ubuntu)
Content-Type: text/html; charset=utf-8
Content-Length: 3352
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" /> ...[HTML CODE]

在榜首行,咱们拿到信息,HTTP 呼应码200 OK。代码为200表明恳求得到了正确处理。你能够在维基百科上找到一切可用代码的完好列表。在状况行之后是呼应标头,它们的用途与咱们刚才评论的恳求标头相同。在呼应标头之后,您将看到一个空行,后边跟从该呼应发送的实践数据。

一旦你的阅读器收到呼应,它将解析 HTML 代码,获取一切嵌入资产(JavaScript 和 CSS 文件,图片,视频) ,并将成果呈现到主窗口。

咱们将经过不同的办法运用 Python 履行 HTTP 恳求,并从呼应中提取所需的数据。

1. 运用Socket发送 HTTP 恳求

Socket

在 Python 中履行 HTTP 恳求的最基本办法是翻开一个 TCP socket并手动发送 HTTP 恳求。

import socket
HOST = 'www.google.com'  # Server hostname or IP address
PORT = 80                # The standard port for HTTP is 80, for HTTPS it is 443
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = (HOST, PORT)
client_socket.connect(server_address)
request_header = b'GET / HTTP/1.0\r\nHost: www.google.com\r\n\r\n'
client_socket.sendall(request_header)
response = ''
while True:
    recv = client_socket.recv(1024)
    if not recv:
        break
    response += str(recv)
print(response)
client_socket.close()  

现在咱们已经有了 HTTP 呼应,最基本办法是运用正则表达式从中提取数据

正则表达式

正则表达式是一个用于处理、解析和验证恣意文本的十分通用的东西。正则表达式本质上是一个字符串,它运用规范语法定义查找形式。例如,您能够快速识别网页中的一切电话号码。

经典查找和替换相结合,正则表达式答应您以相对简略的办法对动态字符串履行字符串替换。在 web 抓取上下文中,最简略的比如或许是用正确的小写字母替换格局不佳的 HTML 文档中的大写符号。

在理想的语义国际中,数据很简略被机器读取,而且信息被嵌入到相关的 HTML 元素中,包括有意义的特点。但现实国际很紊乱。您经常会在

元素中发现很多的文本。例如,假如希望在大型文本(价格、日期、称号…)中提取特定数据,则必须运用正则表达式。

留意: 这儿有一个很棒的网站来测验你的 regex: regex101.com/。这篇文章只触及一小部…

<p>Price : 19.99$</p>

咱们能够用 XPath 表达式挑选这个文本节点,然后运用 regex 提取价格:

^Price\s*:\s*(\d+.\d{2})$

假如您只要 HTML,那么它会稍微杂乱一些,但不会杂乱太多。您能够简略地在表达式中指定符号,然后捕获文本组。

import re
html_content = '<p>Price : 19.99$</p>'
m = re.match('<p>(.+)</p>', html_content)
if m:
	print(m.group(1))

如上,能够运用套接字手动发送 HTTP 恳求,并运用正则表达式解析呼应,可是这很杂乱,可是有更高档的 API 能够使使命愈加简略。

2. urllib3 & LXML

声明: 在 Python 中 urllib 比较紊乱。规范库包括 urllib 和 urllib2(有时是 urllib3)。在 Python 3中,urllib2被分割成多个模块,而 urllib3不会很快成为规范库的一部分。这种令人困惑的状况将成为另一篇博客文章的主题。在本节中,我决议只评论 urllib3,由于它在 Python 国际中被广泛运用,包括 Pip 和 Request。

Urllib3是一个高档包,它答应您对 HTTP 恳求做简直任何您想做的工作。运用 urllib3,咱们能够用更少的代码行来完结上一节中所做的工作。

import urllib3
http = urllib3.PoolManager()
r = http.request('GET', 'http://www.google.com')
print(r.data)

如上,这比socket简练许多。不仅如此,API 也很简略。此外,您还能够轻松地做许多其他工作,如增加 HTTP 头、运用署理、 POST 表单..。

例如,假如咱们决议设置一些头文件并运用署理,咱们只需求履行以下操作(你能够在 bestproxyreviews.com 了解更多关于署理服务器的信息) :

import urllib3
user_agent_header = urllib3.make_headers(user_agent="<USER AGENT>")
pool = urllib3.ProxyManager(f'<PROXY IP>', headers=user_agent_header)
r = pool.request('GET', 'https://www.google.com/')

看到没?行数完全相同。可是,有些工作 urllib3并不简略处理。例如,假如咱们想要增加一个 cookie,咱们必须手动创立相应的头文件并将其增加到恳求中。

还有一些工作 urllib3能够做到,而 Request 不能: 例如,创立和办理一个池和署理池,以及办理重试策略。

简略地说,urllib3在抽象方面介于恳求和 Socket 之间,尽管它比 Socket 更接近于恳求。

接下来,咱们将运用 LXML 包和 XPath 解析呼应

XPath

XPath 是一种运用途径表达式在 XML 文档(或 HTML 文档)中挑选节点或节点集的技术。假如您了解 CSS 挑选器,那么您能够将其想象为相对相似的东西。

与文档方针模型相同,XPath 自1999年以来一向是 W3C 规范。尽管 XPath 自身不是一种编程言语,但它答应您编写能够直接拜访特定节点或特定节点集的表达式,而无需遍历整个 HTML 树(或 XML 树)。

要运用 XPath 从 HTML 文档中提取数据,咱们需求三样东西:

  • HTML 文件
  • 一些 XPath 表达式
  • 将运转这些表达式的 XPath 引擎

首要,咱们将运用从 urllib3取得的 HTML。现在咱们要从 Google 主页中提取一切的链接。因而,咱们将运用一个简略的 XPath 表达式//a,并运用 LXML 来运转它。LXML 是一种快速、易于运用的支持 XPath 的 XML 和 HTML 处理库。

装置:

pip install lxml

代码:

from lxml import html
# We reuse the response from urllib3
data_string = r.data.decode('utf-8', errors='ignore')
# We instantiate a tree object from the HTML
tree = html.fromstring(data_string)
# We run the XPath against this HTML
# This returns an array of element
links = tree.xpath('//a')
for link in links:
    # For each element we can easily get back the URL
    print(link.get('href'))

输出应该是这样的:

https://books.google.fr/bkshp?hl=fr&tab=wp
https://www.google.fr/shopping?hl=fr&source=og&tab=wf
https://www.blogger.com/?tab=wj
https://photos.google.com/?tab=wq&pageId=none
http://video.google.fr/?hl=fr&tab=wv
https://docs.google.com/document/?usp=docs_alc
...
https://www.google.fr/intl/fr/about/products?tab=wh

与正则表达式相同,XPath 表达式功能强壮,是从 HTML 中提取信息的最快办法之一。与正则表达式相同,XPath 或许很快变得紊乱、难以阅览和难以维护。

假如您想了解更多关于 XPath 的信息,请不要犹疑阅览我关于 XPath 运用于 web 抓取的专门博客文章。

3. Requests & BeautifulSoup

requests

requests是 Python 包之王。它的下载量超过11,000,000次,是 Python 中运用最广泛的软件包。

Installation:

pip install requests

恳求很简略:

import requests
r = requests.get('https://www.scrapingninja.co')
print(r.text)

运用 requests,能够很简略地履行 POST 恳求、处理 cookie、查询参数… … 您还能够运用 Request 下载图像。

在下面的页面中,您将学习如何将恳求与署理一起运用。这简直是强制性的刮在规模的网络。

\

Authentication to Hacker News

假定咱们想创立一个东西来主动将咱们的博客文章提交到 Hacker 新闻或任何其他论坛,比方 Buffer。在发布咱们的链接之前,咱们需求在这些网站上进行认证。咱们将运用 Requests 和 BeautifulSoup 进行完成

下面是 Hacker News 的登录表单和相关的 DOM:

[译]使用Python进行 Web 抓取: 您需要知道的一切

在这个表单上有三个带有 name 特点的 < input > 符号(不发送其他输入元素)。榜首个类型躲藏了一个名为“ goto”的类型,别的两个是用户名和密码。

假如你在 Chrome 阅读器中提交表单,你会发现有许多工作正在产生: 一个重定向和一个 cookie 正在被设置。此 Cookie 将由 Chrome 在每次后续恳求中发送,以便服务器知道您已经过身份验证。

运用恳求履行此操作很简略。它将为咱们主动处理重定向,而且能够运用 Session 方针处理 cookie。

\

BeautifulSoup

接下来咱们需求的是 BeautifulSoup,它是一个 Python 库,能够帮助咱们解析服务器回来的 HTML,以查明咱们是否登录了。

装置:

pip install beautifulsoup4

因而,咱们所要做的便是将这三个输入和咱们的凭证发布到/login 端点,并查看是否存在一个只在登录时显现的元素:

import requests
from bs4 import BeautifulSoup
BASE_URL = 'https://news.ycombinator.com'
USERNAME = ""
PASSWORD = ""
s = requests.Session()
data = {"goto": "news", "acct": USERNAME, "pw": PASSWORD}
r = s.post(f'{BASE_URL}/login', data=data)
soup = BeautifulSoup(r.text, 'html.parser')
if soup.find(id='logout') is not None:
    print('Successfully logged in')
else:
	print('Authentication Error')

太棒了,只需求几行 Python 代码,咱们就能够登录到一个站点,并查看登录是否成功。现在,进入下一个挑战: 取得主页上的一切链接。

顺便说一下,Hacker News 供给了一个强壮的 API,咱们把它作为一个比如来做,可是你应该运用这个 API 而不是去抓取它!

咱们需求做的榜首件事是查看 Hacker News 的主页,以了解其结构和不同的 CSS 类,咱们将不得不挑选:

[译]使用Python进行 Web 抓取: 您需要知道的一切

从截图中能够显着看出,一切发布都是带有 class athing 的 < tr > 符号的一部分。所以,让咱们简略地找到一切这些标签。再一次,咱们能够用一行代码来完结这个使命。

links = soup.findAll('tr', class_='athing')

然后,关于每个链接,咱们将提取它的 ID、标题、 URL 和排名:

import requests
from bs4 import BeautifulSoup
r = requests.get('https://news.ycombinator.com')
soup = BeautifulSoup(r.text, 'html.parser')
links = soup.findAll('tr', class_='athing')
formatted_links = []
for link in links:
    data = {
        'id': link['id'],
        'title': link.find_all('td')[2].a.text,
        "url": link.find_all('td')[2].a['href'],
        "rank": int(link.find_all('td')[0].span.text.replace('.', ''))
    }
    formatted_links.append(data)
print(formatted_links)

很好,只需求几行 Python 代码,咱们就能够加载 Hacker News 的站点并取得一切发布内容的详细信息。可是在咱们通向大数据的旅程中,咱们不仅想打印数据,咱们实践上还想持久化它。咱们现在试试。

在 PostgreSQL 中存储数据

咱们在这儿挑选了一个很好的关系数据库作为示例-PostgreSQL!

首要,咱们需求一个正常运转的数据库实例。查看 www.postgresql.org/download ,挑选合适您的操作体系的软件包,并遵循其装置阐明。一旦装置了 PostgreSQL,您将需求设置一个数据库(让咱们将其命名为 scrape demo) ,并运用以下schema为咱们的 Hacker News links增加一个表。

CREATE TABLE "hn_links" (
  "id" INTEGER NOT NULL,
  "title" VARCHAR NOT NULL,
  "url" VARCHAR NOT NULL,
  "rank" INTEGER NOT NULL
);

为了办理数据库,您能够运用 PostgreSQL 自己的指令行客户端,也能够运用其间一个可用的 UI 接口。

好了,数据库应该准备好了,咱们能够再次发动代码了。

首要,咱们需求一个能让咱们与 PostgreSQL 衔接的程序,而 Psycopg 是一个真实的很棒的库。像往常相同,您能够用 pip 快速装置它。

pip install psycopg2

剩下的就相对简略明了了,咱们只需求把它们对接

con = psycopg2.connect(host="127.0.0.1", port="5432", user="postgres", password="", database="scrape_demo")

该衔接将答应咱们获取数据库光标

cur = con.cursor()

一旦咱们有了光标,咱们就能够运用办法 execute 来实践运转 SQL 指令。

cur.execute("INSERT INTO table [HERE-GOES-OUR-DATA]")

太好了,咱们已经把一切东西都存储在数据库里了!

请等一下。不要忘记提交您的(隐式)数据库事务。再来一次 con. commit()(和几次封闭)

[译]使用Python进行 Web 抓取: 您需要知道的一切

最后,这儿是完好的代码和之前的抓取逻辑,这次将一切内容存储在数据库中。

import psycopg2
import requests
from bs4 import BeautifulSoup
# Establish database connection
con = psycopg2.connect(host="127.0.0.1",
                       port="5432",
                       user="postgres",
                       password="",
                       database="scrape_demo")
# Get a database cursor
cur = con.cursor()
r = requests.get('https://news.ycombinator.com')
soup = BeautifulSoup(r.text, 'html.parser')
links = soup.findAll('tr', class_='athing')
for link in links:
    cur.execute("""
    INSERT INTO hn_links (id, title, url, rank)
    VALUES (%s, %s, %s, %s)
    """,
                (
                    link['id'],
                    link.find_all('td')[2].a.text,
                    link.find_all('td')[2].a['href'],
                    int(link.find_all('td')[0].span.text.replace('.', ''))
                )
               )
    # Commit the data
    con.commit();
    # Close our database connections
    cur.close()
    con.close()

Summary

正如您所看到的,Request 和 BeautifulSoup 是提取数据和主动履行不同操作的优秀库。假如你想运转大规模的 web 抓取项目,你依然能够运用Requests,可是你需求自己处理许多部分。

你知道 ScrapingBee 的数据提取东西吗。它们不仅为您的项目供给了一个完好的无代码环境,而且还能够轻松地扩展和处理一切高档特性,比方 JavaScript 和署理循环,开箱即用。看看吧,1000个恳求需求咱们完成。

假如您想了解更多关于 Python、 BeautifulSoup、 POST 恳求,尤其是 CSS 挑选器的信息,我强烈推荐以下文章

  • BeautifulSoup tutorial: Scraping web pages with PythonBeautifulSoup 教程: 用 Python 抓取网页
  • How to send a POST with Python Requests?如何运用 Python 恳求发送 POST?

与往常相同,当然也有许多点能够改善:

  • 找到使代码并行履行的办法,使其更快
  • 处理过错
  • 过滤成果
  • 操控您的恳求,这样您就不会让服务器过载

走运的是,现有的东西能够为咱们处理这些问题。

GRequests

尽管Requests包易于运用,可是假如有数百个页面要抓起,您或许会发现它有点慢。它只答应您发送同步恳求,这意味着假如您有25个 URL 要抓取,您将不得不一个一个地做。

因而,假如一个页面需求10秒钟才干获取,那么获取这25个页面将需求4分钟以上的时刻。

import requests
# An array with 25 urls
urls = [...] 
for url in urls:
    result = requests.get(url)

加快这个进程的最简略办法是一起进行多个调用。这意味着,不需求按次序发送每个恳求,而是能够批量发送5个恳求。

在这种状况下,每个批处理将一起处理5个 URL,这意味着您将在10秒内获取5个 URL,而不是50秒,或许在50秒内获取整个25个 URL,而不是250秒。

一般,这是运用根据线程的并行完成的。不过,线程处理或许很棘手,特别是关于初学者。走运的是,有一个版本的 Request 包为咱们完结了一切的艰苦工作,即 GRequest。它根据恳求,但也包括了 gevent,一个广泛用于 Web 运用程序的异步 Python API。这个库答应咱们以一种简略而高雅的办法一起发送多个恳求。

首要,让咱们装置 GRequest。

pip install grequests

现在,以下是如何分批发送咱们的25个初始 URL,每批5个:

import grequests
BATCH_LENGTH = 5
# An array with 25 urls
urls = [...] 
# Our empty results array
results = []
while urls:
    # get our first batch of 5 URLs
    batch = urls[:BATCH_LENGTH]
    # create a set of unsent Requests
    rs = (grequests.get(url) for url in batch)
    # send them all at the same time
    batch_results = grequests.map(rs)
    # appending results to our main results array
    results += batch_results
    # removing fetched URLs from urls
    urls = urls[BATCH_LENGTH:]
    print(results)
# [<Response [200]>, <Response [200]>, ..., <Response [200]>, <Response [200]>]

便是这样。GRequest 关于小型脚原本说是完美的,可是关于出产代码或许大规模的 web 抓取来说就不那么理想了。为此,咱们有 Scrapy。

4. Web 匍匐框架

Scrapy

[译]使用Python进行 Web 抓取: 您需要知道的一切

Scrapy 是一个强壮的 Python 网页抓取和网页匍匐框架。它供给了许多特性,能够异步下载网页,并以各种办法处理和持久化网页内容。它供给了对多线程、匍匐(从一个链接到另一个链接以查找网站中的每个 URL 的进程)、站点地图等的支持。

Scrapy 还有一个叫 ScrapyShell 的交互形式。运用 Scrapy Shell,您能够快速测验您的抓取代码,并保证您的一切 XPath 表达式或 CSS 挑选器都能正常工作。Scrapy 的缺陷是学习曲线峻峭。还有许多东西要学。

为了持续咱们关于黑客新闻的比如,咱们将编写一个 Scrapy Spider,它将爬起前15页的成果,并将一切内容保存在一个 CSV 文件中。

你能够很简略地用 pip 装置 Scrapy:

pip install Scrapy

然后您能够运用 Scrapy CLI 为咱们的项目生成样板代码:

scrapy startproject hacker_news_scraper

在 hacker _ news _ scraper/Spider 内部,咱们将运用 Spider 的代码创立一个新的 Python 文件:

from bs4 import BeautifulSoup
import scrapy
class HnSpider(scrapy.Spider):
    name = "hacker-news"
    allowed_domains = ["news.ycombinator.com"]
    start_urls = [f'https://news.ycombinator.com/news?p={i}' for i in range(1,16)]
    def parse(self, response):
        soup = BeautifulSoup(response.text, 'html.parser')
        links = soup.findAll('tr', class_='athing')
        for link in links:
            yield {
                'id': link['id'],
                'title': link.find_all('td')[2].a.text,
                "url": link.find_all('td')[2].a['href'],
                "rank": int(link.td.span.text.replace('.', ''))
        	}

在 Scrapy 有许多约定。咱们首要在 start _ URLs 中供给所需的一切 URL。Scrapy 将获取每个 URL 并为其调用 parse,在这儿咱们将运用自定义代码来解析呼应。

然后,咱们需求装备下 Scrapy,以便咱们的爬起行为与方针网站匹配。

你应该一向翻开这个。根据呼应时刻,这个特性会主动调整恳求速率和并发线程的数量,并保证匍匐器不会向网站发送很多恳求。

您能够运用 Scrapy CLI 和不同的输出格局(CSV、 JSON、 XML…)运转这段代码:

scrapy crawl hacker-news -o links.json

便是这样! 现在,一切的链接都在一个格局很好的 JSON 文件中。

关于这个 Scrapy 还有许多要说的。所以,假如你想了解更多,请不要犹疑,查看咱们的专门博客文章关于网络抓取 Scrapy。

\

PySpider

PySpider 是 Scrapy 的替代品,尽管有点过时。最近一次发布是在2018年。可是它依然是相关的,由于它做了许多 Scrapy 不能处理的工作。

首要,PySpider 能够很好地处理 JavaScript 页面(SPA 和 Ajax 调用) ,由于它附带了 PhantomJS,一个无头阅读库。在 Scrapy,这需求装置中间件。最重要的是,PySpider 供给了一个很好的 UI,能够很简略地监视一切的爬取使命。

[译]使用Python进行 Web 抓取: 您需要知道的一切

可是,你或许还是更喜爱运用 Scrapy,原因有以下几点:

  • 更易于了解的指南和文档
  • 内置的 HTTP 缓存体系,能够加快您的爬取
  • 主动 HTTP 身份验证
  • 支持3XX 重定向,以及 HTML 元刷新符号

5. Headless browsing 无头阅读

Selenium & Chrome

Scrapy 十分合适大规模的 web 抓取使命。可是,很难用它来处理很多运用 JavaScript 的站点,例如 SPA (单页运用程序)。Scrapy 自身不能处理 JavaScript,它只能供给静态 HTML 代码。

一般来说,抓取 SPA 是很有挑战性的,由于一般触及很多的 AJAX 调用和 WebSocket 衔接。假如性能是一个问题,那么总是要查看 JavaScript 代码到底在做什么。这意味着运用阅读器查看器手动查看一切网络调用,并复制包括感兴趣数据的 AJAX 调用。

可是,一般会触及太多的 HTTP 调用来获取所需的数据,在无头阅读器中呈现页面会更简略。另一个很好的用例是截屏,这便是咱们将要对 Hacker News 主页做的工作(咱们喜爱 Hacker News,不是吗?)还有Selenium的帮助。

什么时候我应该运用Selenium?

以下是三种最常见的状况:

  • 你正在寻找一个信息,出现在几秒钟后,网页加载到阅读器上
  • 你想要查找的网站运用了很多的 JavaScript
  • 你试图抓取的网站有一些 JavaScript 查看来阻挠“经典”HTTP 客户端

您能够运用 pip 装置 Selenium 包:

pip install selenium

你也需求 ChromeDriver,在 mac 操作体系上你能够运用 brew。

brew install chromedriver

然后,咱们只需求从 Selenium 包中导入 WebDriver,将 Chrome 装备为 headless = True,设置一个窗口巨细(否则它真的很小) ,发动 Chrome,加载页面,最后得到美丽的屏幕截图:

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
options = Options()
options.headless = True
options.add_argument("--window-size=1920,1200")
driver = webdriver.Chrome(options=options, executable_path=r'/usr/local/bin/chromedriver')
driver.get("https://news.ycombinator.com/")
driver.save_screenshot('hn_homepage.png')
driver.quit()

没错,作为一个优秀的网民,咱们当然也退出了 WebDriver 实例。现在,你应该得到一个不错的主页截图:

[译]使用Python进行 Web 抓取: 您需要知道的一切

当然,运用 SeleniumAPI 和 Chrome 还能够做更多的工作。毕竟,这是一个成熟的阅读器实例。

  • 运转 JavaScript
  • 填表格
  • 单击元素
  • 运用 CSS 挑选器/XPath 表达式提取元素

在无头形式下,Selenium 和 Chrome 是抓取任何你想要的东西的终极组合。你能够运用一般的 Chrome 阅读器主动化一切你能做的工作。

最大的缺陷是 Chrome 需求很多的内存/CPU 能量。经过一些微调,您能够将每个 Chrome 实例的内存占用减少到300-400mb,可是每个实例依然需求1个 CPU 核。

请不要犹疑,查看咱们关于 Selenium 和 Python 的深化文章。

假如需求一起运转多个实例,则需求一台具有满足硬件设置和满足内存的计算机来为一切阅读器实例供给服务。假如您想要一个更轻量级、更高枕无忧的解决方案,请查看 ScrapingBee 的站点爬虫 SaaS 平台,它为您完结了许多繁重的工作。

RoboBrowser

RoboBrowser 是一个 Python 库,它将 Request 和 BeautifulSoup 封装到一个简略易用的包中,并答应您编译自己的自定义脚原本操控 RoboBrowser 的阅读工作流。它是一个轻量级库,但它不是一个无头阅读器,而且依然具有咱们前面评论过的 Request 和 BeautifulSoup 的相同约束。

例如,假如你想登录到 Hacker-News,你能够编写一个脚原本填充表单,然后点击登录按钮,而不是手艺制作一个恳求:

# pip install RoboBrowser
from robobrowser import RoboBrowser
browser = RoboBrowser()
browser.open('https://news.ycombinator.com/login')
# Get the signup form
signin_form = browser.get_form(action='login')
# Fill it out
signin_form['acct'].value = 'account'
signin_form['password'].value = 'secret'
# Submit the form
browser.submit_form(signin_form)

正如您所看到的,代码的编写就好像您是在一个真实的阅读器中手动完结使命相同,即便它不是一个真实的无头阅读库。

RoboBrowser 很酷,由于它的轻量级办法答应您轻松地在计算机上并行处理它。可是,由于它不运用真实的阅读器,所以不能处理像 AJAX 调用或单页运用程序这样的 JavaScript。

不幸的是,它的文档也是轻量级的,我不建议新手或许还没有运用 BeautilfulSoup 或许 RequestsAPI 的人运用它。

6. Scraping Reddit data

有时乃至不需求运用 HTTP 客户端或无头阅读器来获取数据。您能够直接运用方针网站揭露的 API。这便是咱们现在要在 Reddit API 中测验的。

要拜访这个 API,咱们将运用 Praw,这是一个包装 Reddit API 的很棒的 Python 包。

装置:

pip install praw

然后,你需求取得一个 API 密钥。转到 www.reddit.com/prefs/apps。

滚动到底部创立运用程序:

[译]使用Python进行 Web 抓取: 您需要知道的一切

正如 Praw 的文档中所概述的那样,保证供给“重定向 URL”的 http://localhost:8080。

单击 create app 后,将加载包括 API 详细信息和凭证的屏幕。在咱们的示例中,需求客户端 ID、 secret 和用户署理。

现在咱们将取得/r/Entrepreneur1,000个帖子,并将其导出到 CSV 文件中。

import praw
import csv
reddit = praw.Reddit(client_id='you_client_id', client_secret='this_is_a_secret', user_agent='top-1000-posts')
top_posts = reddit.subreddit('Entrepreneur').top(limit=1000)
with open('top_1000.csv', 'w', newline='') as csvfile:
    fieldnames = ['title','score','num_comments','author']
    writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
    writer.writeheader()
    for post in top_posts:
        writer.writerow({
            'title': post.title,
            'score': post.score,
            'num_comments': post.num_comments,
            'author': post.author
            })

如您所见,实践的提取部分只要一行 Python 代码。在 subreddit 上运转 top 并将文章存储在 top _ post 中。

Praw 还有许多其他用例。你能够做各种疯狂的工作,比方用情绪剖析库实时剖析次级 Reddit,猜测下一个 $GME..。

总结

下面是咱们在这篇博文中评论的一切技术的一个快速回顾表。请不要犹疑,让咱们知道,假如你知道一些资源,你觉得属于这儿。

Name socket urllib3 requests scrapy selenium
易于运用 – – – + + + + + + + +
灵活性 + + + + + + + + + + + + + +
履行速度 + + + + + + + + + + +
常用事例 * 编写低级编程接口 * 需求对 HTTP (pip、 aws 客户端、恳求、流)进行精密操控的高档运用程序 * 调用 API
* 简略运用程序(根据 HTTP 需求)
* 查找重要的网站列表
* 过滤、提取和载入抓取的数据
* JS 渲染
* 抓取单页运用
* 主动化测验
* 程序化截图
了解更多 * Official documentation官方文件
* Great tutorial很棒的教程
* Official documentation
* PIP usage of urllib3Urllib3的 PIP 运用状况
* Official documentation
* Requests usage of urllib3Urllib3的恳求运用
* Official documentation
* Scrapy overviewScrapy 综述
* Official documentation
* Scraping SPA刮水疗

我希望你喜爱这篇博文!这是对最常用的用于 web 抓取的 Python 东西的简短介绍。在接下来的文章中,咱们将更深化地评论一切的东西或主题,比方 XPath 和 CSS 挑选器。

假如您想了解更多有关 Python 中 HTTP 客户端的信息,咱们刚刚发布了有关最佳 Python HTTP 客户端的指南。

Happy Scraping!