简略概述

本系列可能是一个比较长的系列,主要是对《Python3网络爬虫开发实战》前七章的一个内容总结而且了解运用一下相关的框架与技能。

使命方针

爬取电影数据网站ssr1.scrape.center/, 此网站无反爬,数据经过服务端渲染,需求爬取的部分为列表页里面的电影数据概况。

使命方针解析

  1. 爬取ssr1.scrape.center/网站的列表页面, 经过列表页面的内容获取到需求的URL
  2. 爬取ssr1.scrape.center/detail/{id}… 网站内的数据概况,需求获取的部分有:
    1. 电影标题
    2. 电影图片的url
    3. 电影上映时间
    4. 电影分类
    5. 电影评分
    6. 剧情简介
  3. 将内容存放到需求的数据库中

技能选型与爬取

在进行过屡次爬取同一个网站内容后,运用其他的库其实更多的还是一种对库的了解与了解,因而这儿对于下面的内容经过贴代码进行简略解说的方法来介绍一下,因为在静态网页的数据中许多内容并不涉及到这些库的优势特性。

怎么爬取

抓取主函数

# 网页内容的抓取
def scrape_page(browser, url):
    logging.info('scraping %s ...', url)
    # 反常捕获操作
    try:
        browser.get(url)
        wait = WebDriverWait(browser, 10)
        wait.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, 'div#app')))
    except:
        logging.error('error occured while scraping %s', url, exc_info=True)

运用自动化库拜访网页时,需求一个浏览器目标和浏览器需求拜访的url,因而经过传入两个参数来完结咱们对网页内容的拜访,下方的wait字段则是用于等候页面恳求的完全响应,因为这个网页由vue.js进行搭建,所以咱们全体上只需求等候(By.CSS_SELECTOR, 'div#app')的部分加载完结即可。

列表页内容抓取

# 进行列表页的抓取
def scrape_index(browser, page):
    index_url = f'{BASE_URL}/page/{page}'
    return scrape_page(browser, index_url)

逻辑同之前的几个相似,这儿分析出页面的恳求逻辑后就可以完结对咱们所需求的内容进行拜访恳求。

概况页内容抓取

# 进行概况页的抓取
def scrape_detail(browser, url):
    return scrape_page(browser, url)

怎么解析

因为自动化库自带解析的功用,因而咱们直接运用自动化库自带的功用进行解析即可。

解析索引页

# 解析索引页
def parse_index(browser):
    # 获取一切超链接
    a_tags = browser.find_elements(By.CSS_SELECTOR, 'a.name')
    if not a_tags:
        return []
    for a_tag in a_tags:
        detail_url = a_tag.get_attribute('href')
        # 输出链接
        logging.info('get detail url %s', detail_url)
        # 生成器函数
        yield detail_url

自动化库的浏览器目标是直接对当时页面选项卡进行操作的,咱们当然可以经过browser.page_source的方法获取资源后调用解析器,但相同的咱们可以经过直接使用find_element()方法和find_elements()方法来完结对需求的元素进行获取。

解析概况页

# 解析概况页
def parse_detail(browser):
    # 获取标题
    name = None
    name_tag = browser.find_element(By.CSS_SELECTOR, 'h2.m-b-sm')
    if name_tag:
        name = name_tag.text
    # 获取图片
    cover = None
    cover_tag = browser.find_element(By.CSS_SELECTOR, 'img.cover')
    if cover_tag:
        cover = cover_tag.get_attribute('src')
    # 获取分类
    categories = []
    category_tags = browser.find_elements(By.CSS_SELECTOR, 'div.categories > button > span')
    if category_tags:
        categories = [category.text for category in category_tags]
    # 获取简介
    drama = None
    drama_tag = browser.find_element(By.CSS_SELECTOR, 'div.drama > p')
    if drama_tag:
        drama = drama_tag.text
    # 获取分数
    score = None
    score_tag = browser.find_element(By.CSS_SELECTOR, 'p.score')
    if score_tag:
        score = score_tag.text
    return {
        # 标题
        'name': name,
        # 图片
        'cover': cover,
        # 分数
        'score': score,
        # 分类
        'categories': categories,
        # 剧情简介
        'drama': drama
    }

概况页的解析也相同可以运用相关的选择器操作来完结,而且作用不比之前运用解析库的时分作用差,可以说做到了一个库完结了咱们所需求的一切操作。

怎么存储

# 网页内容的存储
def save_data(data_path, data):
    # 使用csv存储
    with open(data_path, 'a+', encoding='utf-8') as csv_file:
        field_name = ['name', 'cover', 'score', 'categories', 'drama']
        csv_writer = csv.DictWriter(csv_file,fieldnames=field_name)
        csv_writer.writerow(data)

这儿的网页存储运用的csv的方法,经过字典的方法直接进行写入。

源代码

import csv
import logging
from os import makedirs
from os.path import exists
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
logging.basicConfig(level=logging.INFO,
                    format='%(asctime)s - %(levelname)s: %(message)s')
# 常量值
BASE_URL = 'https://ssr1.scrape.center'
TOTAL_PAGE = 10
RESULT_DIR = 'results'
# 文件夹存在或许创立文件夹
exists(RESULT_DIR) or makedirs(RESULT_DIR)
# 网页内容的抓取
def scrape_page(browser, url):
    logging.info('scraping %s ...', url)
    # 反常捕获操作
    try:
        browser.get(url)
        wait = WebDriverWait(browser, 10)
        wait.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, 'div#app')))
    except:
        logging.error('error occured while scraping %s', url, exc_info=True)
# 进行列表页的抓取
def scrape_index(browser, page):
    index_url = f'{BASE_URL}/page/{page}'
    return scrape_page(browser, index_url)
# 进行概况页的抓取
def scrape_detail(browser, url):
    return scrape_page(browser, url)
# 进行网页内容的获取
# 解析索引页
def parse_index(browser):
    # 获取一切超链接
    a_tags = browser.find_elements(By.CSS_SELECTOR, 'a.name')
    if not a_tags:
        return []
    for a_tag in a_tags:
        detail_url = a_tag.get_attribute('href')
        # 输出链接
        logging.info('get detail url %s', detail_url)
        # 生成器函数
        yield detail_url
# 解析概况页
def parse_detail(browser):
    # 获取标题
    name = None
    name_tag = browser.find_element(By.CSS_SELECTOR, 'h2.m-b-sm')
    if name_tag:
        name = name_tag.text
    # 获取图片
    cover = None
    cover_tag = browser.find_element(By.CSS_SELECTOR, 'img.cover')
    if cover_tag:
        cover = cover_tag.get_attribute('src')
    # 获取分类
    categories = []
    category_tags = browser.find_elements(By.CSS_SELECTOR, 'div.categories > button > span')
    if category_tags:
        categories = [category.text for category in category_tags]
    # 获取简介
    drama = None
    drama_tag = browser.find_element(By.CSS_SELECTOR, 'div.drama > p')
    if drama_tag:
        drama = drama_tag.text
    # 获取分数
    score = None
    score_tag = browser.find_element(By.CSS_SELECTOR, 'p.score')
    if score_tag:
        score = score_tag.text
    return {
        # 标题
        'name': name,
        # 图片
        'cover': cover,
        # 分数
        'score': score,
        # 分类
        'categories': categories,
        # 剧情简介
        'drama': drama
    }
# 网页内容的存储
def save_data(data_path, data):
    # 使用csv存储
    with open(data_path, 'a+', encoding='utf-8') as csv_file:
        field_name = ['name', 'cover', 'score', 'categories', 'drama']
        csv_writer = csv.DictWriter(csv_file,fieldnames=field_name)
        csv_writer.writerow(data)
# 输出获取的网页内容
def main():
    options = webdriver.ChromeOptions()
    options.add_argument('--headless')
    browser = webdriver.Chrome(options=options)
    data_path = '{0}/movies.csv'.format(RESULT_DIR)
    with open(data_path, 'w', encoding='utf-8') as csv_file:
        field_name = ['name', 'cover', 'score', 'categories', 'drama']
        csv_writer = csv.DictWriter(csv_file, fieldnames=field_name)
        csv_writer.writeheader()
    try:
        for page in range(1, TOTAL_PAGE + 1):
            # 进入列表页
            scrape_index(browser, page)
            # 解析索引页
            detail_urls = list(parse_index(browser))
            for detail_url in detail_urls:
                scrape_detail(browser, detail_url)
                data = parse_detail(browser)
                logging.info('get data %s', data)
                save_data(data_path, data)
    finally:
        browser.close()
if __name__ == '__main__':
    main()

版权信息

本文由PorterZhang整理或写作完结
本人的Github: PorterZhang2021
本人的博客地址:PorterZhang