爬虫实战(三)
作者:mmseoamin日期:2023-12-25

随着互联网的不断发展,网络数据的规模和价值也不断提升。在这个大数据时代,如何从海量数据中提取有价值的信息并加以利用,成为了数据科学、商业分析、金融预测、社会研究等领域中一个重要的问题。而网络爬虫作为一种数据采集技术,为我们获取和分析网络数据提供了一种高效、灵活和精准的手段。本文将通过实例介绍三种常见的爬虫技术:单页面爬虫、多页面爬虫和分布式爬虫,并使用Python代码进行演示。

一、单页面爬虫

单页面爬虫是指只爬取单个页面的内容。通常,我们可以通过对页面的HTML代码进行解析,提取出我们需要的信息,并保存到本地文件或数据库中。下面我们将分别演示如何爬取百度搜索结果页面和知乎问题页面。

  1. 爬取百度搜索结果页面

百度搜索是一个非常常见的搜索引擎,我们可以使用Python的requests库和BeautifulSoup库来爬取百度搜索结果页面,并提取搜索结果的标题、链接和描述信息。

import requests
from bs4 import BeautifulSoup
def get_baidu_search_result(keyword):
    url = 'https://www.baidu.com/s'
    params = {'wd': keyword}
    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'}
    response = requests.get(url, params=params, headers=headers)
    soup = BeautifulSoup(response.text, 'html.parser')
    results = soup.find_all('div', class_='result')
    for result in results:
        try:
            title = result.h3.a.text
            link = result.h3.a['href']
            desc = result.find('div', class_='c-abstract').text
            print(title)
            print(link)
            print(desc)
        except:
            pass
if __name__ == '__main__':
    keyword = 'Python'
    get_baidu_search_result(keyword)

 在这个示例中,我们定义了一个get_baidu_search_result()函数,它接收一个关键字参数,表示我们要搜索的内容。我们使用requests库发送GET请求,将搜索结果页面的HTML代码下载到本地,并使用BeautifulSoup库进行解析。我们使用find_all()方法获取所有的搜索结果,并遍历每个搜索结果,提取出标题、链接和描述信息,并输出到控制台中。

        2、爬取知乎问题页面

知乎是一个非常流行的知识分享社区,其中包含了大量的高质量问题和答案。如果我们想要获取某个问题的相关信息,就可以使用Python的爬虫技术来实现。

在这里,我们将使用requests库和正则表达式来爬取知乎问题页面,并提取问题标题、回答数和回答内容。具体来说,我们将使用get请求获取页面内容,然后使用正则表达式提取需要的信息。

下面是一个简单的示例代码:

import requests
import re
def get_zhihu_question(question_id):
    url = f'https://www.zhihu.com/question/{question_id}'
    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'}
    r = requests.get(url, headers=headers)
    if r.status_code == 200:
        pattern = re.compile('

(.*?)

.*?

在这个示例中,我们爬取了豆瓣电影TOP250页面的多个页面,并提取了每个电影的标题、评分和简介。

需要注意的是,爬取多个页面时,我们需要使用循环来遍历每个页面,并将每个页面的内容合并到同一个列表中。同时,我们需要使用正则表达式来提取每个页面的内容。在使用正则表达式时,我们需要注意页面结构的变化,以免正则表达式失效。

        4、 爬取豆瓣电影页面

豆瓣是一个广受欢迎的电影、图书、音乐等领域的评分、评论、推荐社区。在这里,我们将使用Python的requests库和BeautifulSoup库来爬取豆瓣电影页面,并提取电影名称、评分和评价人数等信息。

首先,我们需要分析豆瓣电影页面的结构。在浏览器中打开豆瓣电影页面(https://movie.douban.com/top250),可以看到如下的页面:

在这个页面中,每部电影都有一个包含电影名称、评分、评价人数等信息的元素。我们可以使用BeautifulSoup库来解析这些元素,并提取所需的信息。

下面是一个使用Python代码爬取豆瓣电影页面的示例:

import requests
from bs4 import BeautifulSoup
url = 'https://movie.douban.com/top250'
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'}
# 发送请求并获取页面内容
response = requests.get(url, headers=headers)
html = response.text
# 使用BeautifulSoup解析页面内容
soup = BeautifulSoup(html, 'html.parser')
movies = soup.select('.item')
# 遍历电影元素并输出电影名称、评分和评价人数等信息
for movie in movies:
    title = movie.select_one('.title').text.strip()
    rating = movie.select_one('.rating_num').text.strip()
    votes = movie.select_one('.star span:nth-of-type(4)').text.strip()
    print(f'{title} {rating} {votes}人评价')

在这个示例中,我们使用requests库发送请求,并将响应内容保存到一个变量中。然后,我们使用BeautifulSoup库解析页面内容,并使用CSS选择器选择电影元素。最后,我们遍历电影元素,并使用CSS选择器选择电影名称、评分和评价人数等信息,并输出这些信息。

需要注意的是,豆瓣电影页面的结构可能会随时更改,因此我们需要随时更新CSS选择器。另外,爬取豆瓣页面时需要注意反爬虫机制,避免频繁请求。

5、 爬取淘宝商品页面

Python爬取淘宝商品页面需要通过以下步骤实现:

  1. 构造请求URL并发送请求,可以通过浏览器的开发者工具查看请求的URL及参数。
  2. 解析HTML页面,获取商品列表信息。
  3. 遍历商品列表,提取每个商品的信息,例如商品名称、价格、销量等。

需要注意的是,爬取淘宝页面同样需要注意反爬虫机制,可以通过设置headers、使用代理IP等方式来减少被封禁的风险。

以下是一个爬取淘宝商品页面的示例代码:

import requests
import re
def get_taobao_products(keyword, pages):
    url_template = 'https://s.taobao.com/search?q={}&s={}'
    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'}
    products = []
    for page in range(pages):
        s = page * 44
        url = url_template.format(keyword, s)
        response = requests.get(url, headers=headers)
        if response.status_code == 200:
            html = response.text
            pattern = r'g_page_config = ({.*?});'
            match = re.search(pattern, html, re.S)
            if match:
                data = match.group(1)
                products_data = re.findall(r'"raw_title":"(.*?)".*?"view_price":"(.*?)".*?"view_sales":"(.*?)".*?"nick":"(.*?)"', data, re.S)
                products += [{'title': d[0], 'price': d[1], 'sales': d[2], 'seller': d[3]} for d in products_data]
    return products

在这个示例中,我们定义了一个名为get_taobao_products的函数,用于爬取淘宝商品页面并提取商品信息。该函数接受两个参数,分别为关键词和要爬取的页面数。

在函数内部,我们首先根据关键词和页面数构造了请求URL,并发送了请求。我们设置了一个headers参数,模拟了一个浏览器访问,以避免被淘宝反爬虫机制封禁。

然后,我们解析了HTML页面,使用正则表达式提取了商品列表信息。我们使用re.findall函数提取了商品名称、价格、销量和卖家等信息,并将这些信息存储在一个字典列表中。

最后,我们返回了所有商品的信息。

可以使用以下代码来测试get_taobao_products函数:

products = get_taobao_products('iphone', 5)
for product in products:
    print(product)

这个示例将爬取淘宝上关于iphone的前5页商品信息,并输出商品名称、价格、销量和卖家等信息。

需要注意的是,淘宝的页面结构可能会随时更改,需要随时更新正则表达式。同时,淘宝的反爬虫机制也比较严格,需要注意使用。

        6、分布式爬虫

随着互联网的发展,数据量的爆炸式增长,单机爬虫已经无法满足大规模数据爬取的需求,分布式爬虫成为了一种常见的解决方案。分布式爬虫将任务分散到多个节点上执行,可以大幅提高爬取效率和稳定性。

Scrapy是一个强大的Python爬虫框架,可以很容易地实现分布式爬虫。Scrapy-Redis是Scrapy的一个扩展,提供了对Redis数据库的支持,可以实现Scrapy的分布式爬虫功能。

在使用Scrapy-Redis进行分布式爬虫前,我们需要安装Redis和Scrapy-Redis库。Redis是一种开源的内存数据结构存储系统,可以用来实现分布式爬虫的任务队列。Scrapy-Redis库提供了与Redis数据库交互的API。

                6.1 Scrapy-Redis使用示例

以下是一个使用Scrapy-Redis进行分布式爬虫的示例代码:

import scrapy
from scrapy_redis.spiders import RedisSpider
class MySpider(RedisSpider):
    name = 'myspider'
    redis_key = 'myspider:start_urls'
    
    def parse(self, response):
        # 解析爬取的数据
        pass

在这个示例中,我们定义了一个名为MySpider的Spider,并继承了Scrapy-Redis库提供的RedisSpider类。我们还定义了redis_key属性,用于指定Redis数据库中存储起始URL的键名。在parse()方法中,我们可以编写解析爬取的数据的逻辑。

        6.2 分布式爬虫的架构

Scrapy-Redis的分布式爬虫架构主要由以下四个部分组成:

  1. Redis数据库:存储爬虫任务队列和已爬取的URL集合。
  2. Master节点:负责向Redis数据库中写入起始URL,然后将任务分配给Slave节点执行,并接收Slave节点的爬取结果。
  3. Slave节点:从Redis数据库中读取任务,执行爬取任务并将结果返回给Master节点。
  4. Scrapy-Redis:提供与Redis数据库交互的API。

以下是一个简单的分布式爬虫架构示意图:

+---------------------+
|     Redis数据库      |
|                     |
| 任务队列,已爬取URL集合 |
+---------------------+
            |
            v
+---------------------+
|      Master节点      |
|                     |
| 写入起始URL,分配任务给Slave节点 |
+---------------------+
            |
            v
+---------------------+
|      Slave节点       |
|                     |
| 从Redis数据库中读取任务,执行爬取任务并返回结果 |
+---------------------+
            |
            v
+---------------------+
|      Scrapy-Redis     |
|                     |
| 提供与Redis数据库交互的API |

接下来我们将使用scrapy-redis来实现分布式爬虫。scrapy-redis是scrapy框架的一个扩展,可以将多个爬虫进程之间的URL去重和任务分配等工作交给Redis,从而实现分布式爬虫。

首先,我们需要在本地安装Redis并启动服务。然后,在终端中使用pip安装scrapy-redis库。

pip install scrapy-redis

 接下来,我们需要在爬虫项目的settings.py文件中添加以下配置:

# 设置使用scrapy-redis的去重组件,替代Scrapy默认的去重组件
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
# 设置使用scrapy-redis的调度器组件,替代Scrapy默认的调度器组件
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
# 设置爬虫的起始URL队列类型
SCHEDULER_QUEUE_CLASS = "scrapy_redis.queue.SpiderPriorityQueue"
# 设置爬虫的去重规则,必须使用Redis的hashes(默认)
REDIS_ITEMS_KEY = '%(spider)s:items'
# 设置Redis服务器的地址和端口号
REDIS_HOST = 'localhost'
REDIS_PORT = 6379
# 设置Redis连接密码,如果Redis服务器没有设置密码可以不填写
# REDIS_PARAMS = {'password': 'yourpassword'}

接下来,在我们的爬虫代码中,我们需要继承scrapy_redis库中的RedisSpider类,来实现分布式爬虫。

import scrapy
from scrapy_redis.spiders import RedisSpider
class MySpider(RedisSpider):
    name = 'myspider'
    redis_key = 'myspider:start_urls'
    def parse(self, response):
        # 爬虫逻辑
        pass

在这个示例中,我们使用RedisSpider类来定义我们的爬虫。我们指定了爬虫名称为'myspider',起始URL的Redis键为'myspider:start_urls'。在parse方法中编写爬虫的逻辑代码。

现在,我们需要将起始URL放入Redis队列中,以便爬虫可以从中获取URL并开始抓取页面。可以使用Redis的命令行工具或者Python的Redis库来完成这个任务。

import redis
r = redis.Redis(host='localhost', port=6379)
r.lpush('myspider:start_urls', 'http://www.example.com')

在这个示例中,我们使用Redis的lpush命令将起始URL'http://www.example.com'放入'myspider:start_urls'队列中。

现在,我们可以在终端中运行爬虫了。首先,我们需要启动Redis服务。然后,在终端中使用以下命令启动爬虫:

scrapy runspider myspider.py

 

现在,我们已经成功地实现了一个分布式爬虫。

接下来,我们将介绍如何爬取某社交网站的用户信息并进行分析。

7、爬取某社交网站用户信息并进行分析

在这个示例中,我们将以Twitter为例,介绍如何爬取用户信息并进行分析。

Twitter是一个非常流行的社交媒体平台,用户可以在上面发布消息(称为推文),也可以关注其他用户的推文。每个用户都有自己的资料页面,其中包含了一些基本信息,例如姓名、头像、简介、关注数和粉丝数等。我们可以通过爬取用户的资料页面来获取这些信息,并进行分析。

爬取Twitter用户信息

首先,我们需要获取Twitter用户资料页面的URL。在Twitter上,每个用户都有一个唯一的用户名(例如@realDonaldTrump),我们可以将其拼接在https://twitter.com/的后面,就可以得到用户资料页面的URL。

接下来,我们可以使用Python的requests库和正则表达式来爬取用户资料页面,并提取用户的姓名、头像、简介、关注数和粉丝数等信息。

以下是一个爬取Twitter用户信息的示例代码:

import tweepy
import pandas as pd
# 设置API访问凭据
consumer_key = 'your_consumer_key'
consumer_secret = 'your_consumer_secret'
access_token = 'your_access_token'
access_token_secret = 'your_access_token_secret'
# 认证API访问凭据
auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_token, access_token_secret)
# 创建API对象
api = tweepy.API(auth)
# 获取用户信息
user = api.get_user('twitter_username')
# 输出用户信息
print(f'用户ID:{user.id_str}')
print(f'用户名:{user.screen_name}')
print(f'个人简介:{user.description}')
print(f'位置:{user.location}')
print(f'被关注数:{user.followers_count}')
print(f'关注数:{user.friends_count}')
print(f'推文数:{user.statuses_count}')
# 获取用户的推文
tweets = api.user_timeline(screen_name='twitter_username', count=100, tweet_mode='extended')
# 输出每条推文的内容
for tweet in tweets:
    print(tweet.full_text)

需要注意的是,Twitter API的使用需要遵守Twitter的API政策和限制。具体来说,需要注意以下几点:

  1. 请求速率限制:Twitter API对请求速率有限制,需要控制请求频率,避免频繁请求导致API被封禁。

  2. 返回数据的格式:Twitter API返回的数据格式是JSON格式,需要使用Python的json模块进行解析。

  3. API政策和限制:Twitter API有一些政策和限制,如限制查询时间范围、限制查询结果数量等,需要遵守。

总之,使用Twitter API获取用户信息需要遵守相关政策和限制,同时需要掌握Python的json模块的使用,才能进行数据分析和可视化等后续处理。