爬虫实战(多协程+队列)

该博客详细介绍了如何使用Python爬虫技术爬取时光网电视剧TOP100的剧名、导演、主演和简介信息,并利用CSV存储。首先分析页面结构,发现信息在JSON中,通过requests和BeautifulSoup获取基本信息,然后利用Selenium获取剧情简介。通过队列和gevent实现异步爬取,提高效率。最后将基本信息和剧情简介整合存入CSV文件。
摘要由CSDN通过智能技术生成

实战任务:爬取时光网电视剧TOP100的数据(剧名、导演、主演和简介),并利用CSV存储数据

  1. 爬虫最主要的是对于页面的解析,所以在写代码之前需要先研究页面,寻找需要爬取的信息所在的位置。
  • 看一下页面是传统页面(可直接获取到信息)还是填充式的页面(需要通过JSON或者Selenium的方式爬取):

查看页面network的ALL部分中的第0个请求响应的preview,可以看到页面内的信息并没有直接放进页面,而是只有一个框架,所以直接利用requests请求,beautifulsoup解析elements,是无法得到我们想要的信息的。
在这里插入图片描述
所以我们选择利用json部分的信息对页面进行爬取,先在XHR部分找到包含我们想要爬取的信息的json位置,再定位具体信息。
1
观察JSON中的信息可以发现,100部电视剧信息是全部存放在该JSON中的,页面需要换页面看到的排名靠后的电视剧信息均在这个请求响应里面。
在这里插入图片描述
定位要爬取的剧名、导演、主演部分:
在这里插入图片描述
通过json爬取信息需要获取request URL,是带参数的url,不能直接用上面普通的url,所以需要在Headers里面的General部分找到页面的request URL。找到的request URL为

“http://front-gateway.mtime.com/community/top_list/query.api?tt=1617091032101&type=2&pageIndex=1&pageSize=10

在这里插入图片描述
还需要找到的是剧情简介部分,在刚刚的页面中是没有剧情简介的部分的,但进入具体电视剧后,可以看到剧情简介部分(有些剧有,有些则没有)
在这里插入图片描述
在这里插入图片描述
找到剧情简介部分后,通过观察可发现含有简介的网页URL最后的数字为字段movieId部分的信息。
在这里插入图片描述
在这里插入图片描述
所以可以先获得前一个页面中所有电视剧的movieId的信息存储下来,再遍历每一个ID对应的URL,进入页面获取简介信息。
分析简介页面信息,和前一个页面一样elements信息是填充进入的,获取到的只有页面框架信息,不能直接requests,可以利用json信息获取简介部分,但经分析发现,各页面中的request URL没有较好识别的规律,主要表现为“tt”参数无法确定,所以选择了使用Selenium获取页面elements信息进行页面的自动爬取。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
确定爬取方式后找到elements中简介所在位置。
在这里插入图片描述

  1. 确定了信息所在具体位置后,即可开始利用代码实现爬虫了

整体信息爬取思路:通过第一个页面获取的ID信息可以得到每部剧的简介页面的URL,也就是需要进入100个页面进行爬虫爬取信息,这样的访问次数太高了,很慢也不容易爬取,所以可以利用协程,实现异步爬取,再利用队列为爬虫分配网页,减少访问频率,提高爬取信息速度。这里我用了10只爬虫,也就是创建了10个任务,对队列中的100个网页进行异步爬取。

  • 相关库引入
import time
import requests
import pandas as pd
import gevent

from bs4 import BeautifulSoup
from selenium import webdriver
from gevent.queue import Queue
from gevent import monkey

monkey.patch_all()
# 把程序变成协作式运行,帮助程序实现异步
  • 初始化信息
# 初始化存放爬取信息的变量
name = []  # 剧名
director = []  # 导演
actors = []  # 演员
ID = []  # 电视剧ID,链接具体电视剧页面URL
introduction = {'ID': [], 'brief': []}  # 电视剧剧情简介
  • 获取电视剧基本信息函数
# 获取电视剧的基本信息:剧名、导演、演员、ID
def getInfo(URL):
    res = requests.get(URL)  # 获取页面
    json_movies = res.json()  # 获取页面json信息
    time100_movies = json_movies['data']['items'][2]['items']  # 定位到具体信息所在之处
    # 循环电视剧信息获取具体信息
    for movies in time100_movies:
        movies = movies['movieInfo']
        name.append(movies['movieName'])
        director.append(movies['director'])
        actors.append((movies['actors']))
        ID.append(movies['movieId'])
  • 启动引擎
# 启动引擎,自动打开指定网页
def startEngine(URL):
    # 指定驱动器路径
    chrome_driver = r'C:\Program Files\Google\Chrome\Application\chromedriver.exe'
    # 打开浏览器
    driver = webdriver.Chrome(executable_path=chrome_driver)
    # 获取网页
    driver.get(URL)
    # 返回网页信息
    return driver
  • 获取剧情简介函数
# 获取每部剧的剧情简介
def getIntroduction():
    # 先查看队列 是否为空
    while not work.empty():
        # 队列非空则获取URL
        URL = work.get_nowait()
        # 打开引擎
        driver = startEngine(URL)
        time.sleep(1)
        # 获取页面elements
        pageSource = driver.page_source
        # 用html解析elements
        soup = BeautifulSoup(pageSource, 'html.parser')
        # 获取剧情简介部分
        story = soup.find('p', class_='mt6 moreEllipsis')
        # 无剧情简介部分则记为空字符串
        if story is None:
            story = ""
        else:
            story = story.text.strip()
        # 获取URL对应的ID,以记录对应电视剧信息
        introduction['ID'].append(URL.split('/')[-2])
        # 记录剧情信息
        introduction['brief'].append(story)
        # 关闭引擎
        driver.close()
  • 信息存储函数
# 存储基本信息
def reserveFile():
    # 利用爬取到的信息创建DataFrame
    df = pd.DataFrame({
        'ID': ID,
        'tv_name': name,
        'director': director,
        'actors': actors,
    })
    # 写入csv文件
    df.to_csv('time100.csv', index=False)
  • 主函数部分实现
# 任务列表创建
task_list = []
url = 'http://front-gateway.mtime.com/community/top_list/query.api?tt=1617024054427&type=2&pageIndex=1&pageSize=10'
task1 = gevent.spawn(getInfo, url)  # 创建任务
task_list.append(task1)
gevent.joinall(task_list)  # 执行任务

reserveFile()  # 存储基本信息

# 获取ID信息
DF = pd.read_csv('time100.csv')
work = Queue()
for i in DF['ID']:
    url = 'http://movie.mtime.com/' + str(i) + '/'  # 电视剧具体页面的URL
    work.put_nowait(url)  # 将网页URL放入队列
# 创建10只爬虫,每只爬虫爬取队列中的10个页面
for i in range(10):
    task = gevent.spawn(getIntroduction)  # 创建任务
    task_list.append(task)  # 添加任务
gevent.joinall(task_list)  # 执行任务
# 利用得到的简介信息字典创建DataFrame
DF = pd.DataFrame(introduction)
# 存入csv文件
DF.to_csv('brief.csv', index=False)
  • 实现简介信息和详情信息合并,存入一个csv文件
import pandas as pd


# 读取存有电视剧基本信息和剧情简介的csv文件
df1 = pd.read_csv('brief.csv')
df2 = pd.read_csv('time100.csv')
# 以ID为公共属性将两个DataFrame进行内连接形成一个含有电视剧完整信息的DataFrame
df3 = pd.merge(df2, df1, on='ID')

print(df3.head(10))  # 查看前10条信息
df3.to_csv('time100')  # 存入文件

得到的文件情况:
在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个基于Python 3的多协程以及队列爬取时光电视剧top100的示例代码: ```python import requests from bs4 import BeautifulSoup import asyncio import aiohttp import time from queue import Queue async def fetch(session, url): async with session.get(url) as response: return await response.text() async def parse(html): soup = BeautifulSoup(html, 'html.parser') for item in soup.select('div[class="mov_con"] ul li'): rank = item.find('span', class_='top_num').text name = item.find('span', class_='mov_title').text score = item.find('span', class_='total_score').text print(rank, name, score) async def worker(session, queue): while not queue.empty(): url = queue.get() html = await fetch(session, url) await parse(html) async def main(): urls = [f'http://www.mtime.com/top/tv/top100/index-{i+1}.html' for i in range(10)] queue = Queue() for url in urls: queue.put(url) async with aiohttp.ClientSession() as session: tasks = [asyncio.create_task(worker(session, queue)) for _ in range(10)] await asyncio.gather(*tasks) if __name__ == '__main__': start_time = time.time() asyncio.run(main()) end_time = time.time() print(f'Time used: {end_time - start_time} seconds') ``` 这段代码使用了Python的asyncio库和aiohttp库来实现多协程异步爬取页,使用了Python的queue模块来实现任务队列。首先,我们定义了`fetch`函数来异步获取页内容,其返回值为响应的文本内容。然后,我们定义了`parse`函数来解析页内容,提取出电视剧的排名、名称和评分,并输出到控制台。接着,我们定义了`worker`函数来作为协程的工作函数,从任务队列中取出一个URL并异步地解析该URL对应的页。最后,我们定义了`main`函数来创建任务队列,创建异步协程,以及启动异步任务。在`main`函数中,我们先创建了10个URL,然后将这些URL放入任务队列中。接着,我们使用`async with`语句创建一个异步会话,并使用`create_task`函数创建10个异步协程,每个协程都调用`worker`函数,从任务队列中取出一个URL,并异步地解析对应的页。最后,我们使用`asyncio.gather`函数等待所有的异步协程执行完毕。在程序执行结束后,我们还输出了程序的执行时间。 需要注意的是,由于时光在一定时间内会对IP进行限制,如果爬虫速度过快可能会被封禁IP,因此我们在程序中设置了一个1秒钟的延时,以避免被封禁。如果您需要更高的爬取速度,请自行调整代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值