zgq105 / blog

2 stars 0 forks source link

Python之网络爬虫篇 #79

Open zgq105 opened 4 years ago

zgq105 commented 4 years ago

image

1. 网络爬虫?作用?

网络爬虫? 网络爬虫又称网络蜘蛛,是指按照某种规则在网络上爬取所需内容的脚本程序。众所周知,每个网页通常包含其他网页的入口,网络爬虫则通过一个网址依次进入其他网址获取所需内容。网络爬虫的关键就是通过分析网页内容、找出网页的规律,然后抓取自己所需要的内容。 作用? 网络爬虫的主要作用包括数据挖掘、搜索引擎的数据来源、行业数据的收集等。

2. 网络爬虫分类

2.1 爬静态网页

静态网页是指已经通过web服务器已经渲染生成好的静态页面,我们需要爬取的数据在服务端就已经固化在页面中,我们只需要通过浏览器查看页面源代码就能分析出所需要爬取的数据。

这里以一个小说网站爬取为例(林江顾心雨),网站地址为:链接,具体爬取的步骤如下:

使用的技术:requests+BeautifulSoup

  1. 打开网站,分析我们需要爬取的数据的规律,这里以谷歌浏览器为例,按F12打开开发者模式,选择【Sources】tab页,找到html原始页面,分析我们所需要的爬取的数据在html页面中的哪个部分,同时分析出对应的规律。在页面链接中,我们需要找出小说中每个章节的标题和链接地址,因此,我们分析出在需要的数据在class="listmain"的div内,如下图所示: image 获取每个章节标题和链接地址的的代码如下:

    
    def get_download_url(self):
        """获取下载链接
        """
        base_url = 'https://www.biqukan.com/57_57514/'
        req = requests.get(base_url)
        req.encoding = 'gb2312'
        html = req.text
        div_df = BeautifulSoup(html)
        div = div_df.find_all("div", "listmain")
        a_bf = BeautifulSoup(str(div[0]))
        a = a_bf.find_all("a")
        self.nums = len(a[12:]) #章节总数
        for each in a[12:]:
            self.names.append(each.string) #章节名称
            self.urls.append("https://www.biqukan.com/" + each.get('href')) #章节地址

2. 在上一步中我们已经获取到了每个章节的名称和地址,接下来就是分析具体章节的内容信息,以第一个章节为例([链接](https://www.biqukan.com/57_57514/14586475.html)),分析出我们需要爬取的数据在class="showtxt"的div中,如下图所示:
![image](https://user-images.githubusercontent.com/17380142/73825958-e1fbd400-4837-11ea-84cc-5b57a6e8bd9d.png)
获取章节内容的代码如下:

def get_content(self, url): """获取文本内容 :param url: 地址 :return: """ req = requests.get(url) req.encoding = 'gb2312' html = req.text bf = BeautifulSoup(html) texts = bf.find_all("div", "showtxt") content = texts[0].text.replace('\xa0' * 8, '\n\n') # 将空格替换成换行符 return content

3. 接下来就是将爬取的数据写入文件中,具体代码如下:

def writer(self, name, path, text): """写入文件 :param name: :param path: :param text: """ with open(path, 'a', encoding='utf-8') as f: f.write(name + '\n') # 写入每个章节标题 f.writelines(text) # 写入内容 f.write('\n\n') # 结尾写入换行

4.通过以上几个步骤,简单爬取静态网页数据的流程就走完了,完整代码如下:

import sys

import requests import math

from bs4 import BeautifulSoup

''' 小说下载器 '''

class downloader:

def __init__(self):
    self.urls = []  # 章节链接
    self.nums = []  # 章节总数
    self.names = []  # 章节名称

def get_download_url(self):
    """获取下载链接

    """
    base_url = 'https://www.biqukan.com/57_57514/'
    req = requests.get(base_url)
    req.encoding = 'gb2312'
    html = req.text
    div_df = BeautifulSoup(html)
    div = div_df.find_all("div", "listmain")
    a_bf = BeautifulSoup(str(div[0]))
    a = a_bf.find_all("a")
    self.nums = len(a[12:])
    for each in a[12:]:
        self.names.append(each.string)
        self.urls.append("https://www.biqukan.com/" + each.get('href'))

def get_content(self, url):
    """获取文本内容
    :param url: 地址
    :return:
    """
    req = requests.get(url)
    req.encoding = 'gb2312'
    html = req.text
    bf = BeautifulSoup(html)
    texts = bf.find_all("div", "showtxt")
    content = texts[0].text.replace('\xa0' * 8, '\n\n')  # 将空格替换成换行符
    return content

def writer(self, name, path, text):
    """写入文件
    :param name:
    :param path:
    :param text:
    """
    with open(path, 'a', encoding='utf-8') as f:
        f.write(name + '\n')  # 写入每个章节标题
        f.writelines(text)  # 写入内容
        f.write('\n\n')  # 结尾写入换行

if name == 'main': downloader = downloader() downloader.get_download_url() print('开始下载:') for i in range(downloader.nums): content = downloader.get_content(downloader.urls[i]) name = downloader.names[i] downloader.writer(name, '林江顾心雨.txt', content) sys.stdout.write(" 已下载:%.3f%%" % float(i / downloader.nums) + '\r') sys.stdout.flush() print("end")


## 2.2 爬动态网页
动态网页是指我们需要爬取的数据在服务端给到前端的原始页面中不存在我们需要抓取的数据,需要通过浏览器解析、执行才能获取完整的数据;也就是常常说的异步加载的网页,需要通过ajax技术动态加载数据再渲染。

这里以一个百度图片网站爬取为例,网站地址为:[链接](https://image.baidu.com/),具体爬取的步骤如下:

**使用的技术:requests+BeautifulSoup+selenium**

1. 通过打开网页([链接](https://image.baidu.com/))分析出,我们需要抓取的图片在class="imgrow"内容中,如下图所示:
![image](https://user-images.githubusercontent.com/17380142/73827588-c9d98400-483a-11ea-88b5-c779dde3d15b.png)

**说明:上图是在浏览器执行完之后的结果。**

因此,我们获取图片内容的代码如下:

def get_img_url(self): """ 获取图片地址

    """
    url = "https://image.baidu.com/"
    # 打开浏览器
    driver = webdriver.Chrome(executable_path='E:\Program Files\Python\Python38\chromedriver.exe')
    # 打开网站
    driver.get(url)
    div_bf = BeautifulSoup(driver.page_source, "html.parser")
    imglist_div = div_bf.find_all("div", "imgrow")
    for item in imglist_div:
        img_bf = BeautifulSoup(str(item), "html.parser")
        imglist = img_bf.find_all("img");
        for img in imglist:
            self.img_urls.append(img["src"])

**说明:这里使用的是谷歌浏览器驱动,下载地址:[链接](http://chromedriver.storage.googleapis.com/index.html)**

2. 接下来就是写下载图片的代码,具体如下:

def download_img(self): """下载图片

    """
    path = "E:\\python_project\\reptile\\reptile1\img\\"
    seed = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
    for url in self.img_urls:
        res = requests.get(url)
        name = "";
        name_aar = random.sample(seed, 10);
        for item in name_aar:
            name += item;
        file = open(path + name + ".webp", mode='wb+')
        file.write(res.content)
        file.flush()
        file.close()

3. 完整代码如下:

import random

import requests from bs4 import BeautifulSoup from selenium import webdriver

''' 图片下载器 '''

class image_downloader:

def __init__(self):
    self.img_urls = []

def get_img_url(self):
    """ 获取图片地址

    """
    url = "https://image.baidu.com/"
    # 打开浏览器
    driver = webdriver.Chrome(executable_path='E:\Program Files\Python\Python38\chromedriver.exe')
    # 打开网站
    driver.get(url)
    div_bf = BeautifulSoup(driver.page_source, "html.parser")
    imglist_div = div_bf.find_all("div", "imgrow")
    for item in imglist_div:
        img_bf = BeautifulSoup(str(item), "html.parser")
        imglist = img_bf.find_all("img");
        for img in imglist:
            self.img_urls.append(img["src"])

def download_img(self):
    """下载图片

    """
    path = "E:\\python_project\\reptile\\reptile1\img\\"
    seed = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
    for url in self.img_urls:
        res = requests.get(url)
        name = "";
        name_aar = random.sample(seed, 10);
        for item in name_aar:
            name += item;
        file = open(path + name + ".webp", mode='wb+')
        file.write(res.content)
        file.flush()
        file.close()

if name == 'main': img_dl = image_downloader(); img_dl.get_img_url(); print("start") img_dl.download_img() print("end")



# 3. 小结

- requests是python网络请求框架,相关介绍[requests](https://requests.readthedocs.io/zh_CN/latest/)
- BeautifulSoup是一个可以从HTML或XML文件中提取数据的Python库,相关介绍参考[BeautifulSoup](https://www.crummy.com/software/BeautifulSoup/bs4/doc/index.zh.html)
- selenium是一个动态网页爬虫框架,相关介绍参考[selenium](https://selenium-python-zh.readthedocs.io/en/latest/index.html)