目录
爬虫技术在大数据时代中越来越受到重视,其应用也越来越广泛。除了基础的爬虫技术外,还有许多进阶的技术可以帮助开发者更好地实现数据采集和处理。本篇文章将介绍数据存储、爬虫框架和反爬虫技术,帮助读者更好地掌握爬虫技术。
数据存储
在进行网页爬取时,通常需要将获取的数据存储下来,以便后续的分析和处理。数据存储通常分为文件存储和数据库存储两种方式。
文件存储
文件存储是指将获取的数据保存到本地文件中,常见的文件格式有文本文件、CSV文件和JSON文件等。文件存储的优点是简单易用,不需要依赖第三方库和软件,但其缺点是不适用于大规模数据的存储和查询。
以下是一个使用Python将数据存储到文本文件的示例:
import requests
url = 'https://www.baidu.com'
res = requests.get(url)
with open('baidu.html', 'w', encoding='utf-8') as f:
f.write(res.text)
这段代码将百度首页的HTML代码保存到baidu.html
文件中。文件保存过程比较简单,只需使用Python内置的open()
函数打开文件,然后使用write()
函数写入数据即可。
数据库存储
数据库存储是指将获取的数据保存到关系型数据库或非关系型数据库中,常见的数据库包括MySQL、MongoDB等。数据库存储的优点是可以方便地进行数据查询和分析,适用于大规模数据的存储和处理,但其缺点是需要依赖数据库软件和库,设置较为繁琐。
以下是一个使用Python将数据存储到MySQL数据库的示例:
import pymysql
import requests
url = 'https://www.baidu.com'
res = requests.get(url)
conn = pymysql.connect(host='localhost', port=3306, user='root', password='root', db='test', charset='utf8')
cursor = conn.cursor()
sql = "INSERT INTO baidu (content) VALUES (%s)"
cursor.execute(sql, (res.text,))
conn.commit()
cursor.close()
conn.close()
这段代码将百度首页的HTML代码保存到MySQL数据库中。首先连接到数据库,然后使用SQL语句将数据插入到表中。
爬虫框架
爬虫框架是一种帮助开发者更加高效地编写和管理爬虫程序的工具。在爬虫技术中,比较流行的爬虫框架有Scrapy、PySpider等,它们可以提供自动化爬取、数据处理和存储等功能。
Scrapy框架介绍和使用
Scrapy是一个用Python编写的开源、高层次、基于协议的可扩展爬虫框架。它可以轻松处理各种类型的数据和网站结构,提供强大的爬虫功能和高度的定制化配置,帮助开发者快速构建完整的爬虫程序。
Scrapy框架的主要组件包括:
- 引擎(Engine):负责协调各个组件之间的工作流程,例如处理URL、分配任务、启动爬虫等。
- 调度器(Scheduler):负责管理待爬取的URL队列,根据爬虫规则进行调度,将URL提交给引擎处理。
- 下载器(Downloader):负责根据URL下载网页内容,并将下载结果传递给引擎或爬虫中间件进行处理。
- 爬虫(Spider):负责解析网页内容,提取目标数据,并将数据存储到文件或数据库中。
- 爬虫中间件(Spider Middleware):负责在爬虫处理过程中,对下载器和爬虫进行拦截和处理,例如添加请求头、代理IP等。
- 下载器中间件(Downloader Middleware):负责在下载器处理过程中,对请求和响应进行拦截和处理,例如添加请求头、处理代理IP、处理Cookie等。
- 管道(Pipeline):负责对爬虫提取的数据进行处理和存储,例如存储到文件、数据库等。
以下是一个使用Scrapy框架爬取豆瓣电影TOP250的示例代码:
import scrapy
class DoubanSpider(scrapy.Spider):
name = "douban"
start_urls = [
'https://movie.douban.com/top250'
]
def parse(self, response):
for movie in response.css('div.item'):
yield {
'title': movie.css('div.info div.hd a span::text').get(),
'rating': movie.css('div.info div.bd div.star span.rating_num::text').get()
}
next_page = response.css('div.paginator a.next::attr(href)').get()
if next_page is not None:
yield response.follow(next_page, self.parse)
在这个示例中,我们定义了一个DoubanSpider
类,继承自scrapy.Spider
。我们设置了爬虫的名称和起始URL,然后在parse
方法中对每个网页进行处理,提取电影标题和评分信息,并使用yield
将结果输出。
反爬虫技术
为了防止爬虫对网站造成过大的负担,许多网站都会采用反爬虫技术来限制爬虫的访问。常见的反爬虫技术包括User-Agent和代理IP、验证码识别、动态网页爬取技术等。
User-Agent和代理IP
User-Agent是指浏览器在发送HTTP请求时所携带的用户信息,用来识别访问者的身份和设备信息。有些网站会通过检查User-Agent来识别爬虫并限制访问。为了避免被识别为爬虫,可以在爬虫代码中设置一个随机的User-Agent头。
另一种反爬虫技术是通过检测爬虫的IP地址来进行限制。为了避免被限制,可以使用代理IP来隐藏真实IP地址。代理IP是通过代理服务器获取网站内容的IP地址,用来绕过限制和防止封禁。
以下是一个使用随机User-Agent头和代理IP的示例代码:
import requests
import random
user_agents = [
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 Edge/16.16299",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.96 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.81 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 OPR/45.0.2552.888",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 Vivaldi/1.8.770.50",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.81 Safari/537.36 Edge/15.15063",
]
proxy_list = [
"http://1.1.1.1:8888",
"http://2.2.2.2:8888",
"http://3.3.3.3:8888",
]
# 随机选择一个User-Agent头
user_agent = random.choice(user_agents)
# 随机选择一个代理IP地址
proxy = random.choice(proxy_list)
# 设置请求头和代理IP
headers = {'User-Agent': user_agent}
proxies = {'http': proxy}
# 发送请求
response = requests.get('http://www.example.com', headers=headers, proxies=proxies)
print(response.text)
在这个示例中,我们定义了一个User-Agent头的列表和一个代理IP地址的列表。然后,使用random.choice()
方法从列表中随机选择一个User-Agent头和一个代理IP地址,设置请求头和代理IP,并使用requests
库发送GET请求。
需要注意的是,使用代理IP的效果并不稳定,因为有些网站会对代理IP进行监测并封禁。此外,一些网站还会通过其他手段来识别爬虫,例如检查访问频率和访问行为等。因此,为了更好地应对反爬虫技术,还需要使用其他技术手段,例如验证码识别和动态网页爬取技术。
验证码识别
验证码是一种用于区分人类和机器的技术。一些网站为了避免被爬虫爬取或恶意攻击,会在登录或注册等操作中加入验证码验证环节。为了绕过这些限制,可以使用验证码识别技术。
以下是一个使用Python实现验证码识别的示例:
import requests
from PIL import Image
import pytesseract
# 设置请求头和代理IP
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3'
}
proxies = {
'http': 'http://127.0.0.1:8888',
'https': 'https://127.0.0.1:8888',
}
# 下载验证码图片
url = 'http://www.example.com/captcha.jpg'
response = requests.get(url, headers=headers, proxies=proxies)
with open('captcha.jpg', 'wb') as f:
f.write(response.content)
# 使用PIL库打开图片并识别验证码
image = Image.open('captcha.jpg')
text = pytesseract.image_to_string(image)
print('验证码识别结果:', text)
在这个示例中,我们使用requests
库下载了一个验证码图片,并使用PIL库打开该图片。然后,我们使用pytesseract
库对图片进行识别,并输出识别结果。
需要注意的是,验证码识别技术并不是一种通用技术,其效果受验证码复杂程度、图像质量、背景干扰等因素的影响。在实际应用中,需要根据具体情况选择适合的验证码识别方法,并进行参数调优和模型训练。
动态网页爬取技术
动态网页是指通过JavaScript等脚本语言动态生成HTML页面的网页。与静态网页相比,动态网页的内容是动态生成的,不同用户看到的内容可能不同。动态网页爬取技术是指通过模拟浏览器行为来获取动态网页内容的一种技术。
以下是一个使用Selenium库获取动态网页内容的示例:
from selenium import webdriver
# 创建浏览器对象
browser = webdriver.Chrome()
# 访问豆瓣电影热门页面
url = 'https://movie.douban.com/chart'
browser.get(url)
# 获取电影排名信息
movie_list = browser.find_elements_by_xpath('//div[@class="pl2"]/a')
for i, movie in enumerate(movie_list):
print(f'{i+1}. {movie.text}')
在这个示例中,我们首先创建了一个Chrome浏览器对象,然后通过get()
方法访问豆瓣电影热门页面。接着,使用find_elements_by_xpath()
方法获取电影排名信息,最后使用循环输出电影排名和名称。
需要注意的是,使用动态网页爬取技术需要对爬虫进行一些特殊配置,例如设置浏览器的启动参数、设置等待时间、处理弹窗等。同时,使用该技术还需要考虑到效率和稳定性的问题。因此,建议在需要获取动态网页内容时再使用该技术。
除了Selenium之外,还有一些其他的动态网页爬取技术。例如,使用PhantomJS、Pyppeteer、Splash等库可以模拟浏览器的行为,获取JavaScript生成的HTML内容。
PhantomJS
PhantomJS是一个基于WebKit的无界面浏览器,可以模拟浏览器的行为,执行JavaScript脚本并获取渲染后的页面内容。可以使用Python中的selenium库来控制PhantomJS,实现动态网页的爬取。
以下是一个使用PhantomJS和selenium爬取淘宝商品信息的示例代码:
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
class TaobaoSpider(object):
def __init__(self):
self.browser = webdriver.PhantomJS()
self.wait = WebDriverWait(self.browser, 10)
def search(self, keyword):
self.browser.get('https://www.taobao.com')
input = self.wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, '#q')))
submit = self.wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, '#J_TSearchForm > div.search-button > button')))
input.send_keys(keyword)
submit.click()
self.get_products()
def get_products(self):
products = self.wait.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, '#mainsrp-itemlist .items .item')))
for product in products:
title = product.find_element_by_css_selector('.title').text
price = product.find_element_by_css_selector('.price').text
print(title, price)
if __name__ == '__main__':
spider = TaobaoSpider()
spider.search('手机')
在这个示例中,我们定义了一个TaobaoSpider
类,使用PhantomJS和selenium库模拟浏览器行为,搜索淘宝商品并提取商品标题和价格信息。需要注意的是,PhantomJS已停止更新和维护,因此建议使用更先进的技术,如Chrome Headless、Firefox Headless等。
Pyppeteer
Pyppeteer是一个Python版的无头浏览器库,基于Chromium,可以模拟浏览器行为,执行JavaScript脚本并获取渲染后的页面内容。Pyppeteer的API与Puppeteer的API基本相同,因此使用Pyppeteer可以实现与Puppeteer相同的功能。
以下是一个使用Pyppeteer爬取知乎动态页面的示例代码:
import asyncio
from pyppeteer import launch
class ZhihuSpider(object):
async def init_browser(self):
self.browser = await launch(headless=True)
self.page = await self.browser.newPage()
async def close_browser(self):
await self.browser.close()
async def get_page(self, url):
await self.page.goto(url)
await asyncio.sleep(5) # 等待页面渲染
content = await self.page.content()
return content
if __name__ == '__main__':
zhihu = ZhihuSpider()
asyncio.get_event_loop().run_until_complete(zhihu.init_browser())
content = asyncio.get_event_loop().run_until_complete(zhihu.get_page('https://www.zhihu.com/'))
print(content)
asyncio.get_event_loop().run_until_complete(zhihu.close_browser())
在这个示例中,我们使用Pyppeteer模拟了一个浏览器并打开了知乎的网页。等待页面渲染后,获取页面内容并输出。在使用Pyppeteer时,需要使用asyncio
模块协程方式异步执行任务。