• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

python爬虫基础和初识scrapy

武飞扬头像
Blovice
帮助1

数据获取方法与实践

  • 数据的价值
  • 爬虫基础
  • 实战案例
  • 思路启发

1. 数据的价值

  • 数据分析
  • 推荐系统
  • 人工智能、深度学习 Garbage in, garbage out!

2. 爬虫基础

2.1 HTTP

URI :Uniform Resource Identifier,统一资源标志符,类似于人的指纹,用于唯一标识某一资源。

URL :Uniform Resource Locator,统一资源定位符,是URI的一种,它指定了资源的位置,通过URL就可以访问该资源。

URN:Uniform Resource Name,统一资源名称,如某一本书的ISBN号,只知道这是哪本书,不知道书在哪里。
学新通
HTTP: 超文本传输协议(Hyper Text Transfer Protocol)是一个简单的请求-响应协议,它通常运行在TCP之上。它指定了客户端可能发送给服务器什么样的消息以及得到什么样的响应。

HTTPS: HTTP的加密版本,更安全。Secure Socket Layer
学新通
请求:包含请求URL、请求方法、请求头、请求体。浏览器打开任一网址,鼠标右键,选择”检查“打开浏览器调试模式,就可以看到网页源码。调试模式-网络选项卡可以查看各个请求的详情,如请求头中的User-Agent和Cookie

请求方法:GETPOST

  • GET请求中的参数包含在URL中,POST请求则通过表单形式传输,存放在请求体中。
  • GET请求提交数据最多只有1024个字节,而POST没有限制。

Cookie: 服务器端生成的并发送给用户的特殊字符串,用于辨别用户。客户端会在本地存储服务器发送的Cookie,每次请求时又会将Cookie发送到服务器,以便服务器校对身份。例如当你第一次登录某网站,随后再次访问的时候不需要再输入账号密码就已经是登录状态,这正是Cookie在发挥作用。

User-Agent: 标识客户端的操作系统、浏览器、内核版本等信息。编写爬虫时加上该字段,可以伪装成浏览器进行请求。

响应: 响应状态码、响应头、响应体

状态码: 标识此次通信的状态,是成功还是失败,以及失败的原因。

  • 200,请求成功,无异常。

  • 302,临时重定向。

  • 404,Not found,哦豁,请求的页面不见了。请求的资源不存在。

    状态码详解参考文章:https://www.cnblogs.com/xflonga/p/9368993.html

响应体: 请求到的资源,如HTML文档、JSON文档、图片的二进制数据等等。爬虫正是通过解析响应体,获取所需要的内容。

2.2 网页基础

一个网页由HTML、CSS、JavaScript三部分组成。如果把网页比作一个人,HTML相当于骨架,JavaScript相当于肌肉,CSS相当于皮肤,三者结合形成一个完善的网页。

HTML:超文本标记语言(Hyper Text Markup Language),其使用不同的标签代表网页中不同的元素,如文字、按钮、图片。在HTML中所有标签定义的内容都是节点,它们构成一个HTML DOM树,即Doctument Object Model 文档对象

示例:http://example.com/

<!doctype html>
<html>
<head>
    <title>Example Domain</title>
    <meta charset="utf-8" />
    <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <style type="text/css">
    </style>    
</head>

<body>
<div>
    <h1>Example Domain</h1>
    <p>This domain is for use in illustrative examples in documents. You may use this
    domain in literature without prior coordination or asking for permission.</p>
    <p><a href="https://www.iana.org/domains/example">More information...</a></p>
</div>
</body>
</html>
学新通

学新通

HTML文档节点树示例
2.3 requests的使用

python标准库提供了urllib3、httplib等模块以供Http请求,但是API复杂,使用不便。而requests第三方库解决了标准库的痛点,成为了python流行的HTTP请求库。Requests官方中文文档地址:https://docs.python-requests.org/zh_CN/latest/

基本用法:使用requests.get()方法发起GET请求,代码如下。

import requests
百度 = 'https://www.百度.com'
response = requests.get(百度)           # 发起get请求,获得一个Response对象
print('response类型:',type(response))
print('状态码:',response.status_code)    # 通过Response对象的status_code属性,获取响应状态码
print('url:',response.url)              # 获取请求url
print('请求头',response.request.headers)  # 获取发起请求时request的headers,即请求头
print('html:',response.text)            # 通过Response对象的text属性,获取html

添加User-Agent: 有时候,由于网站的限制,通过简单的requests.get方法并不能得到我们想要的结果。这时需要添加User-Agent伪装成浏览器才能正常访问网站,因此添加在请求头中添加User-Agent是爬虫的一种基本操作。

amazon = 'https://www.amazon.cn/'
# 不加User-Agent
amazon_response = requests.get(amazon)
print('Before:', amazon_response.status_code) # 结果是503
# 添加User-Agent
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36'}
amazon_response = requests.get(amazon, headers=headers)
print('After:',amazon_response.status_code)  # 结果是200

添加Cookie: 有的网页需要登录才能访问,因此使用requests发起请求是需要添加cookie,否则请求会被重定向到登录页。

weibo = 'https://weibo.com/u/7361031918?refer_flag=0000015010_&from=feed&loc=avatar&is_all=1'
# 默认允许重定向
weibo_response = requests.get(url=weibo)  
print(weibo_response.status_code)
print(weibo_response.url)  # 此时response对应的url发生改变,已不是原来的url。
print('禁止重定向=======')
# allow_redirects 默认为True,即允许重定向,若求情发生重定向,则会自动请求重定向连接。
# 这里手动设置为Flase,查看其状态码
weibo_response = requests.get(url=weibo, allow_redirects=False)  
print(weibo_response.status_code)  # 此使状态码为302, 临时重定向
print(weibo_response.url)  # url未发生改变
2.4 CSS选择器的使用

针对响应正文为HTML文档的请求,Python中有许多与HTML相关的解析库,比如lxmlBeautifulSoupPyQuery等,这些库使得我们能够使用XPATH语法或CSS语法对HTML文档中对任一地方进行定位,并提取其中的内容。

CSS选择器分为类别选择器、ID选择器、标签选择器、属性选择器等等,具体语法规则如下表。

加一个比较重要的规则"div.quote", 这个需要逆序看,即选择class=“quote”的div标签。与实战案例中的".quote"等效,因为案例中的html页面class=“quote”的标签只有div标签。等看完实战后,再返回来看这里,应该就懂了。

学新通

示例:example.com

<!doctype html>
<html>
<head>
    <title>Example Domain</title>
</head>
<body>
<div>
    <h1>Example Domain</h1>
    <p>This domain is for use in illustrative examples in documents. You may use this
    domain in literature without prior coordination or asking for permission.</p>
    <p><a href="https://www.iana.org/domains/example">More information...</a></p>
</div>
</body>
</html>
import requests
from parsel import Selector
url = 'http://example.com/'
response = requsets.get(url)
html = response.text
sel = Selector(html)  
# 提取title
title = sel.css("title")
# 提取h1
title = sel.css("h1")
# 提取p标签
p = sel.css("p")
# 提取第一个p标签
p1 = sel.css("p")[0]

# "::text",剔除html</>标签,提取其中的文本
title = sel.css("title::text")
print(f'类型:{type(title)}')  # 查看类型
print(title)
# extract(),提取选择器中的内容,并以列表形式返回,与getall()等效
title_extract = sel.css("title::text").extract()
print(f'类型:{type(title_extract)}',title_extract)
# extract_first()提取选择器内容中的第一个元素,与get()等效
title_extract_first = sel.css("title::text").extract_first()
print(f'类型:{type(title_extract_first)}',title_extract_first)
学新通

3. 实战案例

编写一个爬虫程序的基本步骤包括:

(1)确定目标网站。

(2)明确要爬取的内容,分析网页结构以确定爬取逻辑。

(3)编写目标内容解析规则(CSS,Xpath, 正则均可)

(4)编写程序

案例1:爬取名言警句

目标网站: http://quotes.toscrape.com/

爬取内容: 名言、作者、标签
学新通

解析规则: 编写并检验CSS表达式。

# quotes列表
quotes = response.css('.quote') # 返回SelectorList
for quote in quotes: # 遍历SelectorList中的Selector,进一步解析。
    text = quote.css('.text::text').extract_first()
    author = quote.css('.author::text').extract_first()
    tags = quote.css('.tags .tag::text').extract() # 注意.tags 与.tag之间有个空格

学新通

编写程序:

quotes.py

base_url = 'http://quotes.toscrape.com/'
# page = 2
# 构造请求头字典,这里只添加了User-Agent,没设置Cookie
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36 Edg/97.0.1072.55'}
response = requests.get(url=base_url, headers=headers)
# 将html传入Selector类,生成选择器对象sel
sel = Selector(response.text)
# 获取所有的名言”块“
quotes = sel.css('.quote')
for quote in quotes:
    text = quote.css('.text::text').extract_first()
    author = quote.css('.author::text').extract_first()
    tags = quote.css('.tags .tag').extract()
    # 转为字符串,用/拼接各个标签
    tags = '/'.join(tags)
    result = [author, tags, text]
    print(result)
学新通

quotes1.py

import requests
from parsel import Selector

def parse(html):
    """
    解析html,提取想要的数据
    """
    results = []
    sel = Selector(html)
    quotes = sel.css('.quote')
    for quote in quotes:
        text = quote.css('.text::text').extract_first()
        author = quote.css('.author::text').extract_first()
        tags = quote.css('.tags .tag::text').extract()
        # 转为字符串,用/拼接各个标签
        tags = '/'.join(tags)
        result = ','.join([author, text, tags])   '\n'
        results.append(result)
    return results

def save_results(results, path):
    """
    保存parse函数解析出来的results至csv文件中
    """
    with open(path, mode='a', encoding='utf-8') as f:
        f.writelines(results)

if __name__ == '__main__':
    base_url = 'http://quotes.toscrape.com/'
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36 Edg/97.0.1072.55'}
    for page_index in range(1, 11): # 该网站最多只有10页
        # 第一页没有page路径后缀
        if page_index == 1:
            url = base_url
        else:
            url = base_url   'page/'   str(page_index)  # 末尾的斜杠/不加也不影响
        response = requests.get(url=base_url, headers=headers)
        print(f'抓取第 {page_index} 页的内容')
        results = parse(html=response.text)  # results:["quote1", "quote2",... ""]
        save_results(results, path='results.csv')
学新通

案例2:Scrapy初体验

为什么要用Scrapy?

(1)爬虫框架化:借助案例1,我们将一个爬虫程序的四个基本部分——请求,响应,解析,存储都走了一遍,形成了一个小爬虫,爬虫虽小但五脏俱全。但是这只小爬虫只是在比较理想的情况下,它能顺利爬取数据,如果发生异常,则程序停止。下图中①②③④任意一个过程都可能发生异常情况。爬虫框架化后能够很方便的处理各部分的问题,并且易于扩展实现自定义功能。
学新通

①:比如网络有问题时,爬虫程序不能成功发起请求

②:比如服务器端识别你为爬虫,响应状态码不为200,返回的页面不是我们所预期的。

③:解析规则不能成功解析页面,报错。

④:存储过程发生错误。

**(2)提高爬取速度:**借助scrapy可以轻松实现高并发,以及分布式爬虫

Scrapy是什么

一个用于从网站提取所需数据的开源协作框架。它快速、简单、可扩展。基于twitsted,Scrapy使用了一种非阻塞(又名异步)的编程思想,实现高并发高效率。

Scrapy数据流(架构概览)

学新通

  • Scrapy Engine:核心引擎,负责控制和调度各个组件,保证数据流转;
  • Scheduler:负责管理请求、过滤请求、输出请求的调度器。1. 指定请求输出顺序;2. 过滤可能存在的重复请求
  • Downloader:下载器,负责在网络上下载数据,输入待下载的 URL,输出下载结果;
  • Spiders:一个编写自己的爬虫逻辑,定义抓取意图的类;
  • Item Pipeline:负责输出结构化数据,可自定义格式和输出的位置;

如果你观察地比较仔细的话,可以看到还有两个模块:

  • Downloader middlewares:介于引擎和下载器之间,可以在网页在下载前、后进行相应处理,比如下载前给Request添加请求头,cookie,代理等;
  • Spider middlewares:介于引擎和爬虫之间,在向爬虫输入下载结果前,和爬虫输出请求 / 数据后进行逻辑处理;

用scrapy实现案例1

  • 创建scrapy工程

    scrapy startproject tutorial
    

    工程文件目录结构如图,scrapy.cfg是

    tutorial
    |
    |---scrapy.cfg             # 部署配置文件
    |---tutorial               # python模块,所需要的__init__.py,有它才能正常import
        |--- __init__.py
        |--- items.py          # 定义数据结构的文件
        |--- middlewares.py    # 定义爬虫中间件的文件
        |--- pipelines.py      # 定义处理数据的管道的文件
        |--- settings.py       # 工程设置文件
        |--- spiders           # 在改文件夹下,编写自己的爬虫名.py文件,该爬虫名.py文件定义爬取逻辑和解析规则
             |--- __init__.py
    
  • 进入工程目录第一个tutorial,创建爬虫程序, quotes是爬虫名,quotes.toscrape.com要爬取链接的域名。命令行运行这两条指令后,spiders文件夹下会自动生成一个quotes.py文件,如下图,QuotesSpider类则正是我们编写爬虫逻辑和解析规则的地方。

    cd tutorial 
    scrapy genspider quotes quotes.toscrape.com
    

学新通

  • name: 爬虫名称,同一个工程下,爬虫名称唯一。

  • allow_domains: 准许的域名列表,属于这个列表内域名下的链接会被丢忽略。

  • start_urls: 设置起始连接,即爬虫的入口,从哪些网页开始爬。

  • parse(): 解析规则就写在这个函数里,用于解析响应,Response对象。

  • item.py文件定义Items类,添加我们想要提取数据的字段,规范数据格式。

    import scrapy
    
    class QuoteItem(scrapy.Item):
        text = scrapy.Field()
        author = scrapy.Field()
        tags = scrapy.Field()
    
  • 编写parse()解析函数,使用Item

        def parse(self, response):
            quotes = response.css('.quote')
            for quote in quotes:
                item = QuoteItem()
                # ::text 代表获取正文(去除标签),返回值是选择器对象
                text = quote.css('.text::text').extract_first()
                # extract_first() 提取选择器对象中的第一个数据。
                author = quote.css('.author::text').extract_first()
                # 一个tags下有多个tag, extract()返回全部tag组成的列表。
                tags = quote.css('.tags .tag::text').extract()  
                tags = '/'.join(tags)
                item['text'] = text
                item['author'] = author
                item['tags'] = tags
                yield item
            # 这里.pager .next 中间有个空格, 讲课时候的程序因为没有空格,
            # 所以没有匹配到下一页链接的后缀,即/page/2/ 这样的后缀,导致只爬取了第一页
            next = response.css('.pager .next a::attr("href")').extract_first()
            # 这里将提取到的下一页后缀'/page/2/'与当前页url融合,组成下页请求连接,
            url = response.urljoin(next)
            # callback指定这个请求用哪个函数来解析
            yield scrapy.Request(url=url, callback=self.parse)
    
    学新通
  • 命令行运行爬虫

    scrapy crawl quotes
    
  • 命令行运行爬虫,并将记过保存到csv文件

    scrapy crawl quotes -o quotes.csv
    

    学新通

4. 思路启发

你能否做一个程序,甚至是带GUI的应用或者微信小程序后搭建一个网页,输入商品名字(如某某型号的手机),得到该各大电商平台的价格,并给出给用户一个最低价商品的的链接。感兴趣的同学可以试试看,用scrapy实现。

5. 参考资料

优质学习资料的重要性不言而喻,现在做如下推荐,我基本都看过,都很棒。

推荐书籍

  • 《Python3网络爬虫开发实战》,崔庆才著,2018

    #这本比较详细和全面,通俗易懂,培训笔记也主要参考了这本书籍,跟着案例一个个都走一遍.
    这篇文章大多数内容都参考了这本书。
    
  • 《精通Python爬虫框架Scrapy》,迪米特里奥斯著,李斌译,2018

    #和第一本结合着看,这本主要讲scrapy,掌握scrapy常用指令
    
  • 《Python3反爬虫原理与绕过实战》,韦世东,2020

    #全面讲解了常见与不常见的反爬虫手段以及如何绕过反爬,快速过完后,做到心中有数,方便回头查阅
    
  • 《实战Python网络爬虫》,黄永祥著,2019

    #前面的书看了,基本就掌握得从差不多了,这本主要是练习后面几章的实战案例,
    加深理解和提高代码能力。总之,实践为王。
    

**备注:**前三本我都提供了电子版,最后一本没有,但是在手机APP微信读书能搜到电子版免费阅读

推荐专栏:下面是别的大佬的源码解析,滤清了各个流程的细节,挺好。但是需要有一定scrapy实践经验,基本掌握scrapy架构,才能看懂,了解细节实现,学习别人的源码时怎么写的。



这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgfifeg
系列文章
更多 icon
同类精品
更多 icon
继续加载