0


Python爬虫(Scrapy、Selenium、BeautifulSoup等爬虫框架的使用)

一、常见的Python爬虫库

  1. Requests:处理Http请求。

  2. lxml:HTML和XML文件解。

  3. BeautifulSoup:网络抓取框架,用于解析和提取HTML和XML数据,通常用于小数据量的处理,不支持异步操作,通常搭配lxml使用。

  4. Scrapy:比较强大的爬虫框架,适用于复杂大型任务的爬取。

  5. Selenium:模拟用户访问浏览器操作,适合处理JS渲染的网页。

  6. re:正则表达式。

二、爬虫示例 1

示例描述: 爬取自己的csdn博客,统计每篇博客的访问量,制作一个柱状图,以访问量从大到小的方式显示。

1. 从“个人主页”爬取所有所有文章的链接

1.1 查看爬取规则

    打开个人主页,右键->检查:可以看到每篇文章的链接挂在哪个标签的哪个属性下( <article>标签下的<a>标签中的href属性值即为每篇文章的链接 )

1.2 提取网页中的所有文章ip

from bs4 import BeautifulSoup  #pip3 install beautifulsoup4
from urllib.request import urlopen

homePage_url="https://blog.csdn.net/beautiful77moon?type=blog"  #你的csdn个人主页链接
homePage_html=urlopen(homePage_url).read().decode('utf-8')
soup=BeautifulSoup(homePage_html,features='lxml')

#1.查找所有的<article>标签
li_articles=soup.find_all('article')

#2.取出所有<article>标签下<a>中的href属性值
article_urls=[]
for item in li_articles:
    link=item.find_all('a')
    article_urls.append(link[0]['href'])
    print(link[0]['href'])
    当页面内容过多时,需要下拉"加载",才能显示所有内容,所以需要一个工具模拟浏览器行为,自动滚动页面以加载更多内容。urllib无法处理这种情况,所以一般不建议使用 urllib。

1.3 使用selenium模拟浏览器。

1.3.1 下载浏览器驱动(以Edge为例)
  1. 查看自己的浏览器版本(点击浏览器右上角的三个点->设置->关于 Microsoft Edge)

  2. 下载对应版本的驱动:Microsoft Edge WebDriver | Microsoft Edge Developer

  3. 解压到一个目录下(这个目录后续会用到)

1.3.2 下载关键的依赖包
  1. 浏览器模拟器selenium:pip install selenium --index-url https://pypi.tuna.tsinghua.edu.cn/simple

  2. 处理网页的beautifulsoup:pip install beautifulsoup4 --index-url https://pypi.tuna.tsinghua.edu.cn/simple

1.3.3 代码
  1. 模拟浏览器,实现“滑动鼠标”下拉页面以加载更多数据的行为

  2. 从个人主页提取所有文章的url并打印

from selenium import webdriver
from selenium.webdriver.edge.service import Service
from selenium.webdriver.edge.options import Options
from bs4 import BeautifulSoup
import time

# 设置 Edge驱动 的路径
edge_driver_path = 'E:\SoftWare_work\download\edgedriver_win64\msedgedriver.exe'  # 替换为你本地的 EdgeDriver 路径

# 配置 Edge浏览器选项
edge_options = Options()
edge_options.add_argument("--headless")  # # 无头模式。不可视化浏览器页面。如果注释掉这行,每次运行代码都会打开浏览器页面。

# 启动浏览器
service = Service(edge_driver_path)
driver = webdriver.Chrome(service=service, options=edge_options)

# 打开网页
homePage_url = "https://blog.csdn.net/beautiful77moon?type=blog"
driver.get(homePage_url)

# 滚动页面以加载更多内容
# driver.execute_script("return window.pageYOffset + window.innerHeight") 用于获取当前视口底部相较于页面顶部位置的 JavaScript 代码
# window.pageYOffset:当前视口顶部相对于页面顶部的垂直滚动距离。表示页面的顶部已经滚动了多少像素     假设为1200px
# window.innerHeight:浏览器视口的高度(即当前显示区域的高度) 假设为800px
# last_height = window.pageYOffset + window.innerHeight = 2000px
last_height = driver.execute_script("return window.pageYOffset + window.innerHeight")
while True:
    #driver.execute_script("window.scrollTo(0, document.body.scrollHeight);") #使用 JavaScript 滚动到页面底部以加载更多数据
    #模拟鼠标滚动
    #第一个参数表示水平方向不滚动
    #第二个参数表示垂直方向上滚动1000像素
    driver.execute_script(f"window.scrollBy(0, 1000);")
    time.sleep(5) #等待页面加载
    new_height = driver.execute_script("return window.pageYOffset + window.innerHeight")#driver.execute_script("return document.body.scrollHeight") #获取当前页面的高度,检测是否已加载更多内容
    if new_height == last_height:
        break
    last_height = new_height

# 获取页面源代码
page_source = driver.page_source

# 关闭浏览器
driver.quit()

# 解析页面内容
soup = BeautifulSoup(page_source, 'lxml')

# 查找所有的<article>标签
li_articles = soup.find_all('article')

# 取出所有<article>标签下<a>中的href属性值
article_urls = []
for item in li_articles:
    links = item.find_all('a')
    if links:
        article_urls.append(links[0].get('href'))
        print(links[0].get('href'))
print(len(article_urls))  #116

2. 统计每篇文章的访问量

2.1 查看爬取规则

参考 1.1

2.2 爬取数据

注意:1.3.3 代码中的 driver.quit() 需要注释掉,否则不能正常浏览其他网页,会报错

import re
#分析每篇文章的访问量,收藏量,点赞数
class Article_Detail:
    def __init__(self,article_name="",read="",collect="",like=""):
        self.article_name=article_name #文章名字
        self.read=read #阅读量
        self.collect=collect #收藏量
        self.like=like #点赞量
articles_details=[]
for item in article_urls:
    driver.get(item)
    page_source=driver.page_source
    #driver.quit()
    soup = BeautifulSoup(page_source,'lxml')
    # 阅读量、收藏量、点赞数所在标签过滤
    bar_content=Article_Detail()
    get_name=(soup.find('h1',attrs='title-article',id='articleContentId')).get_text()
    get_read=(soup.find('span','read-count')).get_text(strip=True) #strip=True去除前后空格
    get_collection=(soup.find('span','get-collection')).get_text(strip=True)
    get_like=(soup.find('span',id='blog-digg-num')).get_text(strip=True)

    #统计文章的阅读量、收藏量、点赞数
    bar_content.article_name=get_name

    match=re.search(r'\d+',get_read) #使用正则表达式匹配字符串中的一个或多个数字
    bar_content.read= match.group() if match else 0

    match = re.search(r'\d+', get_collection)  # 使用正则表达式匹配字符串中的一个或多个数字
    bar_content.collect = match.group() if match else 0

    match = re.search(r'\d+', get_like)  # 使用正则表达式匹配字符串中的一个或多个数字
    bar_content.like = match.group() if match else 0

    articles_details.append(bar_content)

for item in articles_details:
    print(item.article_name+":阅读量["+item.read+"],收藏量["+item.collect+"],点赞数["+item.like+"]")

** 运行结果:**

三、爬虫框架Scrapy

使用Scrapy框架实现"示例1"中的功能,并将爬取的结果进行保存。

1. Scrapy框架与BeautifulSoup框架的区别:

Scrapy教程

[功能方面]

  • Scrapy:- 数据类型:可以处理各种类型的数据。- 功能方面:包括请求管理、数据解析/提取、数据存储(JSON、CSV、XML)等。- 请求方式:使用异步 I/O,使其能够高效地处理大量请求。- 支持的特性:支持中间件、管道、爬虫调度等功能,适合大规模的抓取项目。- 自动处理:能够自动处理重定向、用户代理、更换IP等。
  • **BeautifulSoup: ** - 数据类型:是一个用于解析 HTML 和 XML 的库,主要用于提取网页内容。- 功能方面:只解析和提取数据,不包括请求管理和数据存储。- 请求方式:同步I/O操作,通常与requests等库配合使用。

[性能方面]

  • Scrapy:- 性能高:因其异步I/O和内置的请求调度功能,适合大规模抓取。- 扩展性强:可以通过中间件和扩展进行功能扩展,如处理JavaScript渲染内容等。
  • BeautifulSoup:- 性能较低:通常用于小规模数据抓取,不支持异步操作。- 扩展性有限,主要集中与数据解析,需要与其他工具组合使用。

[适用场景]

  • Scrapy:- 大规模爬取:适合需要高效处理大量数据的项目。- 复杂任务抓取:适用于抓取并处理多个页面、分页、异步请求等复杂任务。
  • BeautifulSoup:- 小型抓取:适合简单的数据提取任务。- 数据解析:已经知道了html内容,只需要解析和提取数据时。

2. Scrapy框架使用步骤

  1. 命令行创建一个爬虫项目:scrapy startproject csdn_blog

  2. 进入项目目录:cd csdn_blog

  3. 创建爬虫(scrapy genspider+爬虫文件名+爬取网页网址):scrapy genspider csdn_spider https://blog.csdn.net/beautiful77moon?type=blog

  4. 打开items.py定义item容器

import scrapy

class CsdnBlogItem(scrapy.Item):
    # define the fields for your item here like:
    title=scrapy.Field()
    read=scrapy.Field()
    collect=scrapy.Field()
    like=scrapy.Field()
  1. 进入 csdn_spider.py编写爬虫代码
import re
import scrapy

class CsdnSpiderSpider(scrapy.Spider):
    name = "csdn_spider"
    allowed_domains = ["blog.csdn.net"]
    start_urls = ["https://blog.csdn.net/beautiful77moon?type=blog"]

    def parse(self, response):
        #提取文章链接
        article_urls=response.css('article a::attr(href)').getall()  # ::attr(href) 提取href属性的值
        article_urls=[url for url in article_urls if url.startswith("https://")]

        #分析所有链接
        for url in article_urls:

            yield scrapy.Request(url,callback=self.parse_article)

    #提取每篇文章的数据
    def parse_article(self,response):
        title=response.css('h1.title-article::text').get(default='N/A').strip() #::text 提取文本内容
        read=self.extract_number(response.css('span.read-count::text').get(default='0').strip()) #
        collect=self.extract_number(response.css('span.get-collection::text').get(default='0').strip()) # '.':class
        like=self.extract_number(response.css('span#blog-digg-num::text').get(default='0').strip()) # '#':id

        yield {
            'title':title,
            'read' : read,
            'collect' : collect,
            'like' : like
        }

    def extract_number(self,text):
        match=re.search(r"\d+",text)
        return match.group() if match else '0'
  1. 运行: scrapy crawl csdn_spider -o articles.json (将爬取的内容输出到articles.json)

注意: 运行时会报错:Forbidden by robots.txt: <GET https://blog.csdn.net/beautiful77moon?type=blog>

网站的robots.txt文件阻止了 Scrapy 访问该页面,可以修改settings.py中的ROBOTSTXT_OBEY = False配置:来忽略robots.txt规则。(谨慎使用)

    7. 运行结果如下:

四、使用Jupyter对结果进行可视化

未完结


本文转载自: https://blog.csdn.net/beautiful77moon/article/details/141370356
版权归原作者 赵 XiaoQin 所有, 如有侵权,请联系我们删除。

“Python爬虫(Scrapy、Selenium、BeautifulSoup等爬虫框架的使用)”的评论:

还没有评论