最近突发奇想想用多种代码来爬取数据做价格监控。常见的比如Python、JavaScript(Node.js)、或者Go?不过通常来说,Python应该是首选,因为它的库比较丰富,比如requests和BeautifulSoup,或者Scrapy。不过客户要求多种代码,所以我应该涵盖至少几种不同的方法。
首先,客户可能是想监控电商网站的价格,比如亚马逊、淘宝之类的。但不同网站的反爬机制不同,可能需要处理User-Agent、验证码、或者动态加载的内容。比如有些网站用JavaScript渲染内容,这时候可能需要用Selenium或者Playwright。而有些则是静态页面,用简单的HTTP请求就能获取数据。
那客户可能需要不同的方法应对不同的网站情况。比如静态页面用Python的requests+BeautifulSoup,动态页面用Selenium或者Playwright,另外可能还需要用到API的方式,如果目标网站有提供的话。
另外,价格监控可能需要定期执行,所以定时任务的部分也很重要。比如Python的APScheduler,或者Node.js的setInterval,或者cron job。这部分需要给出示例。
存储数据的话,可能需要数据库,比如SQLite、MySQL,或者简单的CSV文件。客户可能对数据库不熟悉,所以给出CSV的示例比较友好,同时也可以提到数据库的方式。
还有,客户可能需要代理IP来防止被封,或者设置请求头模拟浏览器。这些反反爬策略也是需要考虑到的。
以下是几种不同编程语言和框架实现的爬虫示例,用于价格监控场景,涵盖静态页面、动态页面及反爬处理方案:
一、Python + Requests + BeautifulSoup(静态页面)
import requests
from bs4 import BeautifulSoup
import csv
from time import sleep
def scrape_static_page(url):
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
}
try:
response = requests.get(url, headers=headers, timeout=10)
response.raise_for_status()
soup = BeautifulSoup(response.text, 'html.parser')
# 假设价格在类名为 price 的元素中
price = soup.find('span', class_='price').text.strip()
return price
except Exception as e:
print(f"Error: {e}")
return None
# 保存到CSV
def save_to_csv(data):
with open('prices.csv', 'a', newline='') as f:
writer = csv.writer(f)
writer.writerow([data['timestamp'], data['price']])
# 定时监控
if __name__ == "__main__":
target_url = "https://example-product-page.com"
while True:
current_price = scrape_static_page(target_url)
if current_price:
save_to_csv({'timestamp': datetime.now(), 'price': current_price})
sleep(3600) # 每小时执行一次
二、Python + Selenium(动态页面,如JavaScript渲染)
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
import time
def scrape_dynamic_page(url):
options = Options()
options.headless = True # 无头模式
driver = webdriver.Chrome(options=options)
driver.get(url)
time.sleep(3) # 等待页面加载
# 假设价格通过JavaScript动态加载
price_element = driver.find_element(By.CSS_SELECTOR, ".dynamic-price")
price = price_element.text
driver.quit()
return price
# 使用方式同上(可结合定时任务)
三、Scrapy 框架(高性能分布式爬虫)
# 在Scrapy项目的spiders目录下创建 price_spider.py
import scrapy
from datetime import datetime
class PriceSpider(scrapy.Spider):
name = "price_monitor"
start_urls = ["https://example-product-page.com"]
def parse(self, response):
price = response.css('span.price::text').get()
yield {
'timestamp': datetime.now().isoformat(),
'price': price.strip(),
'url': response.url
}
# 运行命令:scrapy crawl price_monitor -o prices.json
四、Node.js + Puppeteer(动态页面)
const puppeteer = require('puppeteer');
const fs = require('fs');
async function scrapePrice(url) {
const browser = await puppeteer.launch({ headless: true });
const page = await browser.newPage();
await page.goto(url, { waitUntil: 'networkidle2' });
const price = await page.$eval('.price', el => el.textContent.trim());
await browser.close();
return price;
}
// 定时任务
setInterval(async () => {
const price = await scrapePrice('https://example-product-page.com');
fs.appendFileSync('prices.csv', `${new Date().toISOString()},${price}\n`);
}, 3600 * 1000);
五、Go + Colly(高效并发爬虫)
package main
import (
"fmt"
"github.com/gocolly/colly"
"log"
"time"
)
func main() {
c := colly.NewCollector(
colly.UserAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"),
)
c.OnHTML(".price", func(e *colly.HTMLElement) {
fmt.Printf("Price: %s at %s\n", e.Text, time.Now().Format(time.RFC3339))
})
c.OnError(func(r *colly.Response, err error) {
log.Println("Request failed:", err)
})
for {
c.Visit("https://example-product-page.com")
time.Sleep(1 * time.Hour)
}
}
六、反爬策略处理
-
随机User-Agent:
from fake_useragent import UserAgent headers = {'User-Agent': UserAgent().random}
-
代理IP轮询:
proxies = [ 'http://proxy1:port', 'http://proxy2:port' ] response = requests.get(url, proxies={'http': random.choice(proxies)})
-
请求频率控制:
import random time.sleep(random.uniform(1, 3)) # 随机延迟
-
验证码处理:使用第三方服务(如2Captcha)或手动介入。
七、数据存储与分析
-
数据库存储(如MySQL):
import mysql.connector db = mysql.connector.connect(host="localhost", user="user", password="pass", database="prices") cursor = db.cursor() cursor.execute("INSERT INTO prices (timestamp, price) VALUES (%s, %s)", (datetime.now(), price)) db.commit()
-
价格波动报警:
if abs(current_price - previous_price) > threshold: send_email_alert()
总结
- 静态页面:优先使用
Requests + BeautifulSoup
(Python)或Colly
(Go)。 - 动态页面:选择
Selenium
、Playwright
或Puppeteer
(Node.js)。 - 大规模监控:使用
Scrapy
或分布式工具(如Scrapy-Redis)。 - 反爬严格网站:结合代理IP、随机UA和请求频率控制。
建议根据目标网站复杂度选择合适方案,并确保遵守 robots.txt
及法律法规。