爬虫技术进阶(二)

爬虫技术在大数据时代中越来越受到重视,其应用也越来越广泛。除了基础的爬虫技术外,还有许多进阶的技术可以帮助开发者更好地实现数据采集和处理。本篇文章将介绍数据存储、爬虫框架和爬虫反爬技术,帮助读者更好地掌握爬虫技术。

2.1 数据存储

在进行网页爬取时,通常需要将获取的数据存储下来,以便后续的分析和处理。数据存储通常分为文件存储和数据库存储两种方式。

2.1.1 文件存储

文件存储是指将获取的数据保存到本地文件中,常见的文件格式有文本文件、CSV文件和JSON文件等。文件存储的优点是简单易用,不需要依赖第三方库和软件,但其缺点是不适用于大规模数据的存储和查询。

下面是一个使用Python将数据存储到文本文件的示例:

# -*- coding: utf-8 -*-

import requests

url = 'https://www.baidu.com'
res = requests.get(url)

with open('baidu.html', 'w') as f:
    f.write(res.text)

 

这段代码将百度首页的HTML代码保存到了baidu.html文件中。文件保存的过程比较简单,只需要使用Python内置的open()函数打开文件,然后使用write()函数写入数据即可。

2.1.2 数据库存储

数据库存储是指将获取的数据保存到关系型数据库或非关系型数据库中,常见的数据库包括MySQL、MongoDB等。数据库存储的优点是可以方便地进行数据查询和分析,适用于大规模数据的存储和处理,但其缺点是需要依赖数据库软件和库,设置较为繁琐。

下面是一个使用Python将数据存储到MySQL数据库的示例:

# -*- coding: utf-8 -*-

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')" % (res.text)
cursor.execute(sql)
conn.commit()

cursor.close()
conn.close()

 

这段代码将百度首页的HTML代码保存到了MySQL数据库中,需要先连接到数据库,然后使用SQL语句将数据插入到表中。

2.2 爬虫框架

爬虫框架是一种帮助开发者更加高效地编写和管理爬虫程序的工具。在爬虫技术中,比较流行

的爬虫框架有Scrapy、PySpider等,它们可以提供自动化爬取、数据处理和存储等功能。

2.2.1 Scrapy框架介绍和使用

Scrapy是Python编写的一个开源的、高层次的、基于协议的、可扩展的爬虫框架。它可以轻松地处理各种类型的数据和网站结构,提供了强大的爬虫功能和高度的定制化配置,可以帮助开发者快速构建一个完整的爬虫程序。

Scrapy框架的主要组件包括:

1.引擎(Engine):负责协调各个组件之间的工作流程,例如处理URL、分配任务、启动爬虫等。

2.调度器(Scheduler):负责管理待爬取的URL队列,根据爬虫规则进行调度,将URL提交给引擎处理。

3.下载器(Downloader):负责根据URL下载网页内容,并将下载结果传递给引擎或者爬虫中间件进行处理。

4.爬虫(Spider):负责解析网页内容,提取目标数据,并将数据存储到文件或数据库中。

5.爬虫中间件(Spider Middleware):负责在爬虫处理过程中,对下载器和爬虫进行拦截和处理,例如添加请求头、代理IP等。

6.下载器中间件(Downloader Middleware):负责在下载器处理过程中,对请求和响应进行拦截和处理,例如添加请求头、处理代理IP、处理Cookie等。

7.管道(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将结果输出。

2.3 数据存储

在爬虫中,获取到的数据需要进行存储和管理,常用的数据存储方式包括文件存储和数据库存储。

2.3.1 文件存储

文件存储是最简单的数据存储方式之一,它可以将爬取到的数据以文本或二进制文件的形式保存在本地磁盘上。常见的文件存储格式包括txt、csv、json等。

以下是一个将爬取到的数据保存为txt文件的示例代码:

import requests

# 爬取网页数据
response = requests.get('https://www.baidu.com/')
html = response.text

# 将数据保存为txt文件
with open('baidu.html', 'w', encoding='utf-8') as f:
    f.write(html)

2.3.2 数据库存储

数据库存储是一种结构化的数据存储方式,它可以将爬取到的数据存储到关系型数据库或非关系型数据库中,以便进行后续的查询和分析。常见的关系型数据库包括MySQL、PostgreSQL等,常见的非关系型数据库包括MongoDB、Redis等。

以下是一个将爬取到的数据保存到MySQL数据库中的示例代码:

import pymysql

# 连接MySQL数据库
conn = pymysql.connect(host='localhost', user='root', password='123456', database='testdb', charset='utf8mb4')
cursor = conn.cursor()

# 创建数据表
cursor.execute('CREATE TABLE IF NOT EXISTS `books` (`id` INT(11) NOT NULL AUTO_INCREMENT, `title` VARCHAR(255) NOT NULL, `author` VARCHAR(255) NOT NULL, `price` FLOAT NOT NULL, PRIMARY KEY (`id`))')

# 插入数据
cursor.execute('INSERT INTO `books` (`title`, `author`, `price`) VALUES (%s, %s, %s)', ('Python入门教程', '张三', 29.9))

# 提交事务并关闭连接
conn.commit()
cursor.close()
conn.close()

2.4 爬虫反爬技术

为了防止爬虫对网站造成过大的负担,许多网站都会采用反爬虫技术来限制爬虫的访问。常见的反爬虫技术包括User-Agent和代理IP、验证码识别、动态网页爬取技术等。

2.4.1 User-Agent和代理IP

User-Agent是指浏览器在发送HTTP请求时所携带的用户信息,它可以用来识别访问者的身份和所使用的设备信息。有些网站会通过检查User-Agent来识别爬虫并限制访问。为了避免被识别为爬虫,我们可以在爬虫代码中设置一个随机的User-Agent头。

另一种反爬虫技术是通过检测爬虫的IP地址来进行限制。为了避

免被限制,我们可以使用代理IP来隐藏自己的真实IP地址。代理IP是指通过代理服务器来获取网站内容的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的效果并不稳定,因为有些网站会对代理IP进行监测并进行封禁。此外,一些网站还会通过其他手段来识别爬虫,例如检查访问频率和访问行为等。因此,为了更好地应对反爬虫技术,我们还需要使用其他的技术手段,例如验证码识别和动态网页爬取技术。

2.4.2 验证码识别

验证码是一种用于识别人类和机器之间的区别的技术。一些网站为了避免被爬虫爬取或恶意攻击,会在登录或注册等操作中加入验证码验证环节。为了绕过这些验证码的限制,我们需要使用验证码识别技术。

验证码识别的基本思路是通过计算机视觉技术对验证码图像进行处理和分析,提取其中的文字信息,并将其转化为计算机可识别的文本形式。常用的验证码识别技术包括图像处理和机器学习等方法。

下面是一个使用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库对图片进行识别,并输出识别结果。

需要注意的是,验证码识别技术并不是一种通用的技术,它的效果受到验证码的复杂程度、图像质量、背景干扰等因素的影响。因此,在实际应用中,我们需要根据具体情况选择适合的验证码识别方法,并进行参数调优和模型训练等操作。

2.4.3 动态网页爬取技术

动态网页是指通过JavaScript等脚本语言动态生成HTML页面的网页。与静态网页相比,动态网页的内容是动态生成的,不同用户看到的内容可能不同。因此,在

动态网页爬取技术是指通过模拟浏览器行为来获取动态网页内容的一种技术。由于动态网页的内容是通过JavaScript动态生成的,爬虫在获取源代码时只能获取到未经渲染的HTML代码,无法获取到动态生成的内容。因此,我们需要使用一些工具或库来模拟浏览器的行为,例如使用Selenium或者Pyppeteer库。

下面是一个使用Selenium库获取动态网页内容的示例。假设我们要爬取豆瓣电影的热门电影列表,但是该页面的电影排名是通过JavaScript动态生成的。我们可以使用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内容。下面,我们将介绍一些常用的动态网页爬取技术。

2.4.3.1 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等。

2.4.3.2 Pyppeteer

Pyppeteer是一个Python版的无头浏览器库,它基于Chromium,可以模拟浏览器的行为,执行JavaScript脚本并获取渲染后的页面内容。Pyppeteer的API与Puppeteer的API基本相同,因此使用Pyppeteer可以实现与Puppeteer相同的功能。

以下是一个使用Pyppeteer爬取知乎动态页面的示例代码:

import asyncio
from pyppeteer import launch

class ZhihuSpider(object):
    def init(self):
        self.browser = None
        self.page = None

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模块协程的方式来异步执行任务。

你可能感兴趣的:(爬虫,python,开发语言)