用Python写爬虫入门篇(三)

简介

最近在学习python,这几篇博文用于个人记录总结,不正之处还望大佬指出。(适合学习过python的同学)
用Python写爬虫入门篇(一)
用Python写爬虫入门篇(二)
用Python写爬虫入门篇(三)

我的运行环境

系统版本:Windows10
Python版本:Python3.7
IDE:IDEA(因为平时主要用JAVA就没安PyCharm了)
(安装适合自己的环境即可)

动态网页问题

当我们查看源码写爬虫时,有时会发现我们网页中的数据有的并不在源代码中(点击“查看网页源代码(V)”找不到相应元素),为什么呢,因为那是动态网页。和静态网页不同,动态网页显示的内容可以随着时间、环境或者数据库操作的结果而发生改变。那么如何爬取动态网页呢。需要用到今天的新技能:
浏览器(Chrome+Chromedriver)+Selenium+Python

技能介绍

浏览器:其实主流浏览器(只要有相应driver)都能完成我们的任务(模拟正常访问),因为小编用的Chrome,所以以下面的教程就用Chrome写了,需要下载Chrome浏览器和 相应版本的driver(下载地址)
Selenium:它是一个自动化测试工具。它支持各种浏览器,包括 Chrome,Safari,Firefox 等主流界面式浏览器,可用Python驱动执行模拟正常的访问行为,我们需要安装 Python 的 Selenium 库(pip install selenium),用Selenium可执行页面交互,填充表单,Cookies处理,元素选取等一系列功能,具体功能请查看官网Selenium with Python
原理:用浏览器解析动态网页,再从相应网页提取有用数据。

爬取思路

  1. 确定爬取地址与目标数据
  2. 用(Chrome+Chromedriver)+Selenium模拟正常访问
  3. 用BeautifulSoup工具分析页面
  4. 最后将数据存入相应文件夹

爬取实例:

接下来让我们来爬一爬好看的电影吧 :
https://movie.douban.com/tag/#/?sort=S&range=0,10&tags=电影
以上述URL为例,在此网页,右键点击“查看源代码(V)”
用Python写爬虫入门篇(三)
我们再其中查找电影“霸王别姬”元素,可是查找不到,这时我们怎么查找此元素呢用Python写爬虫入门篇(三)
在原网页,右键点击“检查(N)”,然后按下(CTRL+F)在检查中查找我们想要的元素,这时就可以查找了(例如:霸王别姬)
用Python写爬虫入门篇(三)
找到动态网页中我们的目标后,我们再来找到我们想要爬取的内容(电影海报,电影名,评分)
用Python写爬虫入门篇(三)
由上图我们可知,所有的电影内容都包含在class="item"的<a>标签中,电影海报在<a>标签中的<span>的src属性中,电影名则在alt属性中,而评分在另一个<span>标签中故我们可以写出如下关键代码:

all_a = BeautifulSoup(driver.page_source,"lxml").find_all("a",class_="item")
    for a in all_a:
        movie_name = a.img["alt"]#电影名称
        movie_img_url = a.img["src"]#电影图片地址
        movie_score = a.find("span",class_="rate").string#电影评分

(更多BeautifulSoup包用法请查看 Beautiful Soup 4.4.0 文档
找到元素了,那么我们怎么实现加载更多呢?对的,没错,用Selenium模拟我们的行为,
我们用刚学会的"检查"方法查找页面的“加载更多”按键,如图:用Python写爬虫入门篇(三)同样,以下是关键代码

webelement_a = driver.find_element_by_id(id_="app").find_element_by_xpath("div/div/a")# selenium查找元素和XPath路径
    webelement_a.click()

(find_element_by_id和find_element_by_xpath只是众多查找方式中的两种,具体请查看官网Selenium with Python)

详细代码如下

(其它的就不过多解释了,也有相应注释)

from selenium import webdriver
from bs4 import BeautifulSoup
import requests
import os
import time

class MoviesCover():

        def __init__(self):
            self.web_url = "https://movie.douban.com/tag/#/?sort=S&range=0,10&tags=%E7%94%B5%E5%BD%B1"#目标网页
            self.folder_path ="D:\IMGFile" #存储数据的本地地址,改成自己的地址

        def save_img(self,url,file_name):
            img = self.request(url)
            print('开始保存图片')
            f = open(file_name,"ab")
            f.write(img.content)
            print('图片保存成功!')
            f.close()

        def scroll_down(self, driver, times):
            for i in range(times):
                print("第", str(i + 1), "次等待网页加载......")
                time.sleep(5) #根据网速决定时间,当前为5s,网速慢则等待时间长
                print("开始执行第", str(i + 1),"次加载操作")
                webelement_a = driver.find_element_by_id(id_="app").find_element_by_xpath("div/div/a")# selenium查找元素和XPath路径
                webelement_a.click()#找到对应按扭后用模拟浏览器点击它,以实现翻页(其它众多功能请查看官网)
                print("第", str(i + 1), "次下拉操作执行完毕")

        def mkdir(self,path):
            path = path.strip()
            isExists = os.path.exists(path)
            if not isExists:
                print('创建名字叫做', path, '的文件夹')
                os.makedirs(path)
                print('创建成功!')
                return True
            else:
                print(path, '文件夹已经存在了,不再创建')
                return False

        def request(self,url):
            r = requests.get(url)
            return r

        def get_files(self,path):
            pic_names = os.listdir(path)
            return pic_names

        def crawler(self):
            print("start!")
            driver = webdriver.Chrome("D:\Program Files\Python37\Tools\ChromeDriver\chromedriver.exe") #Chrome浏览器的本地驱动地址,也可以把该地址加到环境变量,改成自己的地址
            driver.get(self.web_url)
            self.mkdir(self.folder_path)  # 创建文件夹
            print('开始切换文件夹')
            os.chdir(self.folder_path)  # 切换路径至上面创建的文件夹
            self.scroll_down(driver=driver, times=10)#times是向后翻页的次数
            file_names = self.get_files(self.folder_path)
            all_a = BeautifulSoup(driver.page_source,"lxml").find_all("a",class_="item")
            for a in all_a:
                movie_name = a.img["alt"]#电影名称
                print(movie_name)
                movie_img_url = a.img["src"]#电影图片地址
                print(movie_img_url)
                movie_score = a.find("span",class_="rate").string#电影评分
                print(movie_score)
                movie_filename = movie_name + "_score_" + movie_score + ".jpg"
                movie_filename = movie_filename.replace(" ","_") #替换名称中的特殊字符为"_",不然有些不规范的名称会让程序报错
                movie_filename = movie_filename.replace("/","_")
                movie_filename = movie_filename.replace('"',"_")
                if movie_name in file_names:
                    print('电影已经存在,不再重新下载')
                else:
                    self.save_img(movie_img_url, movie_filename)

movies_cover = MoviesCover()
movies_cover.crawler()#执行


爬取结果

用Python写爬虫入门篇(三)
这几篇爬虫看完后可以自己写几个小爬虫了,但在爬取大项目时,速度会是大问题,因为BeautifulSoup是用Python编写的,本身速度会受影响,所以接下来可能会写关于Scrapy框架的内容,先这样吧,Bye~