网页抓取 被广泛应用于从网站收集数据的各种应用中。作为网页抓取过程的一部分,您需要创建脚本,自动从网页收集和处理数据以用于不同的目的,例如市场研究或价格比较。
JavaScript 和 Python 是最广泛使用的两种编程语言。本文根据它们的易用性、效率、可用库和生态系统、社区支持和资源以及动态内容处理来比较这两种语言。文章中提供的代码片段展示了这些比较点。
易用性
JavaScript 是网页开发中最流行的语言,适合于网页抓取,因为它可以使用Puppeteer 和 Cheerio有效地与动态网页交互并进行操作。如果您已经会使用 JavaScript 开发客户端应用,那么您也可以使用 Node.js 在服务器端进行开发,简化开发过程。
以下 JavaScript 代码使用 HTTP 客户端 Axios 获取 https://example.com
页面上的 HTML,然后使用正则表达式查找标题并提取其内容:
import fetch from 'node-fetch';
httpRequest('https://samplewebsite.com')
.then(rawData => rawData.text()) .then(pageData => {
const documentHTML = pageData;
const h1Finder = /<h1>(.*?)<\/h1>/; // Searching for <h1> elements
const foundH1 = documentHTML.match(h1Finder);
if (foundH1 && foundH1.length > 1) {
const extractedHeader = foundH1[1];
console.log(`Extracted Header: ${extractedHeader}`); // Logging the found header
} else {
console.log('Header missing or not found.');
}
})
.catch(fetchError => {
console.error('Fetching error:', fetchError);
});
这段代码涉及多个步骤和错误处理,使其显得更加复杂。您还需要使用 catch
处理错误,这增加了 promise 结构的复杂性。
相比之下,Python 以其简单的语法和易用性著称,非常适合没有太多编程经验的人。
以下代码使用 Requests 库加载 https://samplewebsite.com
网页。然后,使用正则表达式查找 HTML 内容中的 title
标签:
import urllib.request
import re
web_address = 'https://samplewebsite.com'
web_request = urllib.request.Request(web_address, headers={'User-Agent': 'Mozilla/5.0'})
# Opening the URL and retrieving the HTML content
with urllib.request.urlopen(web_request) as web_response:
web_html = web_response.read().decode('utf-8')
h2_regex = re.compile('<h2>(.*?)</h2>', re.IGNORECASE)
h2_search = h2_regex.search(web_html)
if h2_search:
extracted_title = h2_search.group(1)
print(f"Extracted H2 Title: {extracted_title}")
else:
print("H2 title not detected on the webpage.")
这段代码使用 with
语句确保任何异常都由 HTTP 上下文处理,简化了错误处理。
这两种语言都非常适合您的网页抓取项目。如果您有网页开发背景,那么 JavaScript 可能更适合您。而 Python 的简单语法和大量的库更具吸引力,尤其是对于初学者来说,如果您刚开始抓取网页,那么 Python 是一个不错的选择。
效率
比较网页抓取工具的效率时,您需要了解每种语言如何处理问题,例如并发请求的数量和处理数据的能力。工具在这些场景下的性能决定了其数据提取效率,尤其是在从大数据集提取数据或同时从多个来源获取数据时。
您可以使用 Node.js 提高 JavaScript 网页抓取任务的性能。Node.js 使用一种非阻塞 I/O 模型。这种模型允许 JavaScript 同时执行多个抓取任务,因此 JavaScript 代码无需等待每个 I/O 操作完成。在这种情况下,并行处理功能允许您同时从多个来源抓取数据。
这段 JavaScript 代码使用 Axios 并行/并发地向定义在数组 urls
中的不同网页 URL 发送 HTTP GET 请求:
import fetch from 'node-fetch';
const targetURLs = ['https://samplewebsite1.com', 'https://samplewebsite2.org', 'https://samplewebsite3.net'];
targetURLs.forEach(async (endpoint) => {
try {
const fetchResponse = await fetch(endpoint);
const webpageText = await fetchResponse.text();
console.log(`Received data from ${endpoint}:`, webpageText);
} catch (fetchIssue) {
console.error(`Problem retrieving data from ${endpoint}:`, fetchIssue);
}
});
该代码对多个 URL 执行并发 HTTP GET 请求,并使用 Node.js 异步处理它们的响应。
Python 没有内置的非阻塞 I/O 操作支持,但您可以使用像 Scrapy 这样的框架进行异步处理。Scrapy 框架使用一个叫做 Twisted 的事件驱动网络引擎来处理并发请求,类似于 Node.js 在 JavaScript 中的工作方式。
以下 Python 代码使用 aiohttp 和 asyncio 异步收集数据:
import aiohttp
import asyncio
async def retrieve_web_content(endpoint, client):
async with client.get(endpoint) as response:
content = await response.text()
print(f"Preview from {endpoint}: {content[:100]}") # Displaying the first 100 characters of the content
async def execute():
target_sites = ['https://samplewebsite1.com', 'https://samplewebsite2.org', 'https://samplewebsite3.net']
async with aiohttp.ClientSession() as client_session:
tasks = [retrieve_web_content(site, client_session) for site in target_sites]
await asyncio.gather(*tasks)
asyncio.run(execute())
fetch_data()
函数对指定的 URL 进行异步请求。asyncio.gather
同时运行所有这些任务。该代码对多个站点执行并发请求并异步处理响应。
乍一看,JavaScript 似乎表现更好,因为它本质上是非阻塞的,特别是在 I/O 密集型活动中。然而,使用像 Scrapy 这样的框架,Python 可以达到与 JavaScript 相当的性能。无论您喜欢 JavaScript 的内置异步操作还是 Python 的显式异步编程模型,这两种环境都有优化您的网页抓取操作性能的解决方案。
库和生态系统
在构建网页抓取解决方案时,JavaScript 和 Python 都提供了强大的生态系统,拥有各种专为网页抓取设计的库,从处理 HTTP 请求到解析 HTML 和管理浏览器自动化。
JavaScript 生态系统提供了几个非常适合网页抓取任务的库。以下是其中最流行的两个库:
- Puppeteer: 该库提供了一个高级 API 来管理无头 Chromium 或 Chrome 通过 DevTools 协议。它非常适用于抓取由 JavaScript 生成的动态内容,因为它可以自动化与网站的交互,例如表单提交或按钮点击。您将在下一节动态内容相关的部分中了解更多内容。
- Cheerio: Cheerio 非常适合快速有效地抓取静态 HTML 页面。Cheerio 解析标记并提供一个 API,可用于遍历和操作生成的数据结构,类似于 jQuery。
该代码使用 Axios 从 https://example.com
页面获取 HTML,然后 Cheerio 解析 HTML 内容并提取标题:
const axios = require('axios');
const cheerio = require('cheerio');
axios.get('https://example.com')
.then(result => {
const loadedHTML = cheerio.load(result.data);
const websiteTitle = loadedHTML('title').text();
console.log(`Webpage Title: ${websiteTitle}`);
})
.catch(fetchError => {
console.error(`Failed to fetch page: ${fetchError}`);
});
与此同时,Python 有各种抓取库可供使用,具体取决于您的需求,从抓取简单的静态页面到复杂的 web 应用程序。以下是两种最流行的 Python 抓取库:
- Beautiful Soup: Beautiful Soup 提供快速的HTML 和 XML 解析,因为它易于使用。对于初学者来说,它是一个不错的选择,因为它简单明了,能够轻松管理大多数抓取任务。
- Scrapy: 这是一个功能强大的框架,能够快速提取大量数据。Scrapy 具有一个异步网络框架,使您能够同时处理多个请求。
以下示例演示了如何使用 Beautiful Soup 抓取数据:
import requests
from bs4 import BeautifulSoup as Soup
# Requesting the web page
page_response = requests.get('https://example.com')
page_soup = Soup(page_response.text, 'html.parser')
# Finding the title of the webpage
page_headline = page_soup.select_one('title').text
# Outputting the webpage title
print(f"Webpage Title: {page_headline}")
在这段代码中,Requests 库加载 https://example.com
网页,Beautiful Soup 解析 HTML 内容,然后 select_one
方法提取页面标题并打印标题。
以下示例演示了如何使用 Scrapy 抓取数据:
import scrapy
from scrapy.crawler import CrawlerProcess
class WebsiteTitleSpider(scrapy.Spider):
name = 'title_spider'
allowed_domains = ['example.com']
start_urls = ['https://example.com']
def parse(self, response):
extracted_title = response.xpath('//title/text()').get()
print(f"Webpage Title Extracted: {extracted_title}")
def main():
process = CrawlerProcess()
process.crawl(WebsiteTitleSpider)
process.start()
if __name__ == '__main__':
main()
该代码使用 scrapy
定义了一个简单的蜘蛛,从 https://example.com
网页中提取标题。
在库和框架方面,选择 Python 或 JavaScript 主要取决于您的项目需求、个人或团队的能力以及要抓取的内容。对于动态内容以及浏览器自动化,JavaScript 库如 Puppeteer 可能更适用。对于多步网页抓取,您希望进行高级数据处理和分析,或构建具有异步请求的机器学习模型,那么 Python 是更好的选择。
动态内容处理
动态内容使得网页抓取变得更加困难,因为传统的抓取工具无法捕获由 JavaScript 加载的数据。然而,JavaScript 和 Python 都有特定的库,可以像用户一样在浏览器中操作,从而抓取动态生成的内容。在这种情况下,网页完全渲染以执行 JavaScript 生成的内容,然后异步抓取数据。
在 JavaScript 中,Puppeteer 和 Selenium 是两个可以处理动态内容的库:
- Puppeteer: 该库直接控制 ChromeDriver,非常适合需要与 JavaScript 重度使用的站点交互的任务。
- Selenium: 另一个用于 JavaScript 执行的强大工具,Selenium WebDriver 可以本地或远程驱动浏览器,实时处理复杂场景。
以下示例演示了如何使用 Puppeteer 抓取动态内容:
const puppeteer = require('puppeteer');
async function extractPageTitle() {
const navigator = await puppeteer.launch();
const explorer = await navigator.newPage();
await explorer.goto('https://example.com');
const documentTitle = await explorer.evaluate(() => document.title);
console.log(`Extracted Document Title: ${documentTitle}`);
await navigator.close();
}
extractPageTitle();
该代码使用 puppeteer
启动一个浏览器实例,访问 https://example.com
页面,检索标题并在控制台中打印。最后,代码执行完成后关闭浏览器。
以下示例演示了如何使用 Selenium 抓取动态内容:
const {Builder, By} = require('selenium-webdriver');
async function scrapeDynamicContent(siteUrl) {
let browser = await new Builder().forBrowser('chrome').build();
try {
await browser.get(siteUrl);
let targetElement = await browser.findElement(By.id('dynamic-element'));
let contentOfElement = await targetElement.getText();
console.log(`Extracted Content: ${contentOfElement}`);
} finally {
await browser.quit();
}
}
scrapeDynamicContent('https://example.com');
这段代码使用 Selenium
网络驱动程序打开 https://example.com
网页,并使用 findElement
方法获取动态内容。最后,代码打印内容并关闭浏览器。
Python 抓取动态内容的方法涉及使用 Selenium 和 pyppeteer(基本上是 Puppeteer 的一个移植,提供类似的功能,如浏览器自动化,以处理 JavaScript 渲染的页面)等类似策略。
以下示例演示了如何使用 Selenium 抓取动态内容:
from selenium import webdriver
from selenium.webdriver.common.by import By
navigator = webdriver.Chrome()
navigator.get('https://example.com')
try:
activeElement = navigator.find_element(By.ID, 'dynamic-content')
print(activeElement.text) # Outputs the text of the dynamic element
finally:
navigator.quit() # Ensures the browser closes after the script runs
这段代码使用 Selenium
和 ChromeDriver 打开 https://example.com
网页,并使用 find_element
方法获取动态内容并打印。
以下示例演示了如何使用 pyppeteer 抓取动态内容:
import asyncio
from pyppeteer import launch
async def extractContent():
client = await launch(headless=True) # Launch browser
tab = await client.newPage() # Open a new tab
await tab.goto('http://books.toscrape.com/')
# Wait for the product pods to appear
await tab.waitForSelector('.product_pod', {'timeout': 10000}) # Wait for a maximum of 10 seconds
# Extract book titles
book_titles = await tab.evaluate('''() => {
const titles = [];
document.querySelectorAll('.product_pod h3 a').forEach(element => {
titles.push(element.getAttribute('title'));
});
return titles;
}''')
print(book_titles) # Display the extracted book titles
await client.close() # Close the browser
asyncio.get_event_loop().run_until_complete(extractContent())
这段代码使用 pyppeteer 从 http://books.toscrape.com/
页面抓取动态内容。代码首先启动浏览器,打开 http://books.toscrape.com/
页面,然后使用 querySelectorAll 获取动态内容。最后,代码打印内容并关闭浏览器。
无论使用 JavaScript 还是 Python,这两种语言都允许您抓取动态网页内容。选择哪种语言取决于您的项目的具体要求、您对语言的掌握程度或抓取任务的具体特点。例如,对于大规模数据提取和处理以及构建具有异步请求的机器学习模型,Python 是最佳语言;而 JavaScript 则非常适合从 JavaScript 重度使用的站点抓取动态内容,并使用 Puppeteer 之类的工具进行网页交互自动化。
结论
选择 JavaScript 或 Python 进行网页抓取主要取决于您的项目要求和您最熟悉的语言。如果您是一名网页开发者,或者需要高性能来处理多个操作,那么 JavaScript 是一个极好的选择。如果您重视简洁性和可读性,那么您应该选择 Python。
即使您有合适的工具,网页抓取仍然会遇到挑战,例如 IP 阻止和 CAPTCHA。Bright Data 提供了各种服务,如代理服务、Web 解锁器、IP 轮换、网页抓取 API 和数据集,确保您的抓取活动有效且顺利进行。
要了解更多关于使用 Python 或 JavaScript 进行网页抓取的信息,请查看 Bright Data 的指南 使用 Python 进行网页抓取 和 使用 JavaScript 和 Node.js 进行网页抓取。想跳过手动抓取?试试我们的网页抓取 API 或数据集!