Python爬虫底子总结条记

打印 上一主题 下一主题

主题 1043|帖子 1043|积分 3129

条记主体内容来自尚硅谷Python爬虫小白教程,老师课讲得很好,非常保举!!!
1. 爬虫简介

将整个互联网看作是蜘蛛网,各网站数据为猎物,程序员为狩猎者,因此爬虫顾名思义即程序员通过各种本领获取互联网上的数据。
2. urllib

urllib 是 python 标准库种用于发送网络请求的库,掌握根本命令可以便于批量获取网络数据
2.1 访问服务器

  1. import urllib.request
  2. url = 'http://www.baidu.com'
  3. # 模拟浏览器访问(返回的是HTTPResponse对象)
  4. response = urllib.request.urlopen(url)
  5. # 获取网页内容,读取到的是二进制数据,通过decode解码为utf-8形式
  6. # response还有readlines,getcode,geturl,getheaders等方法
  7. html = response.read().decode('utf-8')
复制代码
2.2 下载资源

   传入资源地址, 下载图片,视频等资源
  1. import urllib.request
  2. # 图片地址
  3. url_retrieve = 'https://img1.baidu.com/it/u=959337756,4186275445&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=889'
  4. # 下载图片并存储到本地,重命名为1.jpg
  5. urllib.request.urlretrieve(url_retrieve, '1.jpg')
复制代码
2.3 自界说请求对象

为什么必要?
https 请求头部中有 User Agent 字段,使得服务器可以或许识别客户利用的操作体系及版本,CPU 类型、欣赏器及版本等信息,而当利用脚本发出普通请求时,这一字段为空,此时服务端返回的相应内容会有所保留。利用自界说请求对象添加此部门信息即可解决问题。
User Agent 字段获取方式如下
  1. import urllib.request
  2. url = 'https://www.baidu.com'
  3. header = {
  4.     'User-Agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Mobile Safari/537.36'}
  5. # 自定义请求对象,post请求数据由data关键字传入字典
  6. request = urllib.request.Request(url, headers=header)
  7. # 发送请求
  8. response = urllib.request.urlopen(request)
  9. # 读取响应内容
  10. content = response.read().decode('utf-8')
复制代码
2.4 请求编码

   在 request 中传入中文无法被识别,因此必要将文本转换为 Unicode 格式再传入
  1. import urllib.parse
  2. # 得到周杰伦的unicode编码
  3. name = urllib.qarse.quote('周杰伦')
  4. # 转换多个参数且用&连接【可直接与get请求拼接】
  5. data = {
  6.     'wd':'周杰伦',
  7.     'sex':'男'
  8. }
  9. # wd=xxxx&sex=yyyy
  10. # 如果用于post请求则还需要使用encode('utf-8')转为字节流
  11. a = urllib.parse.urllencode(data)
复制代码
2.5 代理服务器

   当一个IP地址短时间内多次向服务器发送请求时,大概会被拉黑,此时可以利用代理服务器模仿多用户,实现反爬
  1. import urllib.request
  2. url = 'http://www.baidu.com/s?wd=IP'
  3. header = {
  4.     'User-Agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Mobile Safari/537.36'
  5. }
  6. # 云平台查询得到的IP地址【百度搜索“快代理”】
  7. proxies = {
  8.     'http': '8.130.71.75:3128'
  9. }
  10. request = urllib.request.Request(url, headers=header)
  11. # handler可以自定义更复杂的头部信息,此处添加访问IP地址
  12. handler = urllib.request.ProxyHandler(proxies=proxies)
  13. # handler固定使用步骤:handler,builder_opner,open
  14. opener = urllib.request.build_opener(handler)
  15. # 发送请求
  16. response = opener.open(request)
  17. # 读取响应内容
  18. content = response.read().decode('utf-8')
  19. with open('main.html', 'w', encoding='utf-8') as f:
  20.     f.write(content)
复制代码
若手上有大量IP地址,可以通过代理池的方式随机选择访问IP,防止地址被封
  1. proxies_pool = [{'http': '8.130.71.75:1111'},{'http': '8.130.71.75:2222'}]
  2. proxies = random.choice(proxies_pool)
复制代码
3. 解析网页

3.1 XPath

   Python 利用 XPath 提取网页目标元素依赖于 lxml 库
  1. from lxml import etree
  2. # 解析本地的html文件
  3. html_tree = etree.parse('xx.html')
  4. # 解析服务器响应的response
  5. html_tree = etree.HTML(response.read().decode('utf-8'))
  6. # xpath路径解析后结果,返回一个列表
  7. res = html_tree.xpath('xpath路径')
复制代码
3.2 JSonPath

   Python利用 jsonpath 第三方库提取 json 格式相应数据,jsonpath只能解析本地文件
  1. import json
  2. import jsonpath
  3. # 加载json数据
  4. obj = json.load('xxx')
  5. # 具体语法使用时查询即可
  6. res = jsonpath.jsonpath(obj,'jsonpath语法')
复制代码
3.3 BeautifulSoup

   bs4 库作用与 lxml 库雷同,但是效率低,优点是接口设计更符合利用风俗
  1. from bs4 import BeautifulSoup
  2. # 服务器响应的文件生成对象
  3. soup = BeautifulSoup(response.read().decode(),'lxml')
  4. # 本地文件生成对象
  5. soup = BeautifulSoup(open('xx.html'),'lxml')
复制代码
常用方法
  1. # 找到第一个<a>
  2. soup.a
  3. # 返回第一个<a>标签的所有属性,以字典的形式存储
  4. soup.a.attrs
  5. # 返回当前定位元素中value属性值
  6. soup.attrs.value
  7. # 找到第一个title为xxx且classw为yyy的<a>
  8. soup.find('a',title='xxx',class_='yyy')
  9. # 找到所有<a>和<span>标签,只返回前两个
  10. soup.find_all(['a','span'],limit=2)
  11. # 返回所有<a>,逗号分隔拼接可以获取多个不同标签
  12. soup.select('a')
  13. # 支持类选择器【.】,Id选择器【#】以及属性选择器
  14. # 支持层级选择器【空格是不严格子代,>是严格子代】
  15. # 查找拥有id的属性的<li>标签,也可以指定id为具体值【用双引号】
  16. soup.select('li[id]')
  17. # 获取节点文本内容
  18. obj.get_text()
  19. # 通过key,value的格式可以获得对应属性值
  20. obj['name']
复制代码
4. UI自动化

   有些网页当利用请求的方式无法获得全部数据,因此必要利用UI自动化的方式获取目标数据
  Selenium 提供了 UI 自动化方案,但是加载页面效率较低,可以考虑利用无欣赏器界面的自动化
  1. from selenium import webdriver
  2. from selenium.webdriver.chrome.options import Options
  3. import time
  4. # 获得浏览器对象
  5. def share_brower(browser_path='D:\Chrome\Google\Chrome\Application\chrome.exe'):
  6.     # 驱动路径
  7.     option = Options()
  8.     # 设置浏览器启动地址
  9.     option.binary_location = browser_path
  10.     option.add_argument('--headless')  # 无头模式
  11.     option.add_argument('--disable-gpu')  # 禁用gpu加速
  12.     # 创建浏览器对象
  13.     browser = webdriver.Chrome(options=option)
  14.     return browser
  15. # 上网
  16. url = 'http://www.baidu.com/'
  17. browser = share_brower()
  18. browser.get(url)
  19. # 截图
  20. browser.save_screenshot('baidu.png')
复制代码
5. requests库

   requests 是一个用于发送请求的第三方库,相对于 urllib 而言操作更加便捷
  1. # request 发送请求后得到的返回值记为 r
  2. # 得到返回文本
  3. r.text
  4. # 定制编码方式
  5. r.encoding
  6. # 获取请求的ur1
  7. r.url
  8. # 返回文本的字节类型
  9. r.content
  10. # 响应的状态码
  11. r.status_code
  12. # 响应的头信息
  13. r.headers
复制代码
发送请求样例
   若要保证多个请求在同一个域里,可以通过获取 session 对象再举行请求调用
  1. import requests
  2. url = 'https://www.baidu.com/s'
  3. # 请求头
  4. headers = {
  5.     'User-Agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Mobile Safari/537.36'
  6. }
  7. # 请求参数
  8. data = {
  9.     'wd': '广东'
  10. }
  11. # 传入,post请求中params对应是data关键字
  12. r = requests.get(url, params=data, headers=headers)
  13. # 指定编码
  14. r.encoding = 'utf-8'
  15. print(r.text)
复制代码
开启代理
  1. # 只需要准备好ip和端口,传入proxies参数即可
  2. proxy = {
  3.     'http':'xxx.xxx.xxx.xxx:yyy'
  4. }
  5. request.get(url,params,headers,proxies=proxy)
复制代码
6. scrapy库

   Scrapy 是一个为了爬取网站数据,提取结构性数据而编写的应用框架。可以应用在包罗数据挖掘、信息处置惩罚或存储历史数据等一系列的程序中
  6.1 底子结构介绍

  1. # 创建爬虫项目,名称为scrapy_test_project
  2. scrapy startproject scrapy_test_project
复制代码
项目组成介绍
  1. 项目名称
  2.         项目名称
  3.             spiders
  4.                 __init__.py
  5.             自定义爬虫文件                # 实现爬虫核心功能的文件
  6.     __init__.py
  7.     items.py                                # 定义数据结构的地方,是一个继承自scrapy.Item的类
  8.     middlewares.py                        # 中间件,代理
  9.     pipelines.py                        # 管道文件,里面只有一个类,用于处理下载数据的后续处理,默认是300                                                      优先级,值越小优先级越高(1-1000)
  10.     settings.py                                # 配置文件,比如是否遵守robots协议等
复制代码
进入到 spiders 目次下,天生爬虫文件
  1. # 创建一个叫baidu的爬虫,用于爬取www.baidu.com内容
  2. scrapy genspider baidu www.baidu.com
  3. # 执行爬虫【在根目录下的settings中注释ROBOTSTXT_OBEY = True】
  4. scrapy crawl baidu
复制代码
response的属性和方法
  1. # 获取响应的字符串
  2. response.text       
  3. # 获取的是二进制数据
  4. response.body
  5. # xpath过滤
  6. response.xpath()
  7. # 提取selector对象的data属性值
  8. response.extract()
  9. # 提取selector列表的第一个数据
  10. response.extract_first()
复制代码
实行过程简介
  1. # 开启调试模式,可在控制台查看response相关信息
  2. scrapy shell 目标网站
复制代码
settings.py 日记设置
  1. # 设置日志显示等级(CRITICAL,ERROR,WARNING,INFO,DEBUG)
  2. # 默认等级是DEBUG,只要出现了DEBUG或以上等级的日志都会被打印
  3. LOG_LEVEL = DEBUG
  4. # 将屏幕显示的信息全部记录到文件中,屏幕不再显示,文件以.log结尾
  5. LOG_FILE = xxx.log
复制代码
6.2 爬取当当网数据实战

   我们的目标是获取青春爱情文学前三页的全部书名,图片与代价信息
  

  • 创建爬虫项目,手动创建 books 以及 books/img 目次方便后续存储相干信息
    1. # 创建名为scrapy_dangdang的爬虫项目
    2. scrapy startproject scrapy_dangdang
    复制代码

  • 编辑数据结构文件 items.py ,将必要存储的变量都交由框架管理
    1. import scrapy
    2. class ScrapyDangdangItem(scrapy.Item):
    3.     # define the fields for your item here like:
    4.     # name = scrapy.Field()
    5.     # 要下载的数据都有什么
    6.     # 图片
    7.     src = scrapy.Field()
    8.     # 名字
    9.     name = scrapy.Field()
    10.     # 价格
    11.     price = scrapy.Field()
    复制代码
  • 在 spiders 目次下创建爬虫核心文件,指明初始页面并命名为 dangdang
    1. scrapy genspider dangdang https://category.dangdang.com/pg1-cp01.01.02.00.00.00.html
    复制代码
    根据处置惩罚逻辑编辑该文件
    1. import scrapy
    2. from scrapy_dangdang.items import ScrapyDangdangItem
    3. class DangdangSpider(scrapy.Spider):
    4.     # 爬虫名称
    5.     name = "dangdang"
    6.     allowed_domains = ["category.dangdang.com"]
    7.     start_urls = ["https://category.dangdang.com/pg1-cp01.01.02.00.00.00.html"]
    8.     # 需要爬取的文章页码
    9.     page = 1
    10.     # 执行爬虫文件时自动调用此方法
    11.     def parse(self, response):
    12.         # 根据调试网页获得的目标xpath路径
    13.         # src = '//ul[@class='bigimg']//li/a[1]/img/@data-original'
    14.         # alt = '//ul[@class="bigimg"]//li/a[1]/img/@alt'
    15.         # price = '//ul[@class='bigimg']//li/p[@class='price']/span[1]/text()'
    16.         li_list = response.xpath('//ul[@class="bigimg"]//li')
    17.         for li in li_list:
    18.             # 懒加载图片,data-original属性值是真实地址
    19.             src = li.xpath('.//a[1]/img/@data-original').extract_first()
    20.             # data-original不存在时,使用src数属性值作为地址
    21.             if src is None:
    22.                 src = li.xpath('.//a[1]/img/@src').extract_first()
    23.             name = li.xpath('.//a[1]/img/@alt').extract_first()
    24.             price = li.xpath(
    25.                 './/p[@class="price"]/span[1]/text()').extract_first()
    26.             # 将解析的目标值封装并交由管道处理
    27.             book = ScrapyDangdangItem(src=src, name=name, price=price)
    28.             yield book
    29.         # 爬取前3页的数据
    30.         if self.page <= 2:
    31.             self.page += 1
    32.             # 新页面地址
    33.             url = f'http://category.dangdang.com/pg{self.page}-cp01.01.02.00.00.00.html'
    34.             # scrapy.Request是scrapy的get请求,callback传入需要调用的下一个函数
    35.             # 此处是向url发送get请求后重新调用parse方法
    36.             yield scrapy.Request(url, callback=self.parse)
    复制代码
  • 编辑管道文件 pipelines.py,用于下载处置惩罚爬虫所返回的数据
    1. # useful for handling different item types with a single interface
    2. from itemadapter import ItemAdapter
    3. import urllib.request
    4. # 用于存储json文件
    5. class ScrapyDangdangPipeline:
    6.     # 在爬虫文件开始前执行的方法
    7.     def open_spider(self, spider):
    8.         self.res = []
    9.     def process_item(self, item, spider):
    10.         # 将单引号替换为双引号
    11.         temp = str(item).replace('\'', '"')
    12.         self.res.append(temp)
    13.         return item
    14.     # 在爬虫文件结束后执行的方法
    15.     def close_spider(self, spider):
    16.         with open('./books/books.json', 'w', encoding='utf-8') as f:
    17.             # 以逗号作为分隔符将元素拼接并写入json文件
    18.             f.write(f'[{",".join(self.res)}]')
    19. # 用于处理图片文件
    20. class DangDangDownloadPipeline:
    21.     # 在爬虫文件开始前执行的方法
    22.     def open_spider(self, spider):
    23.         pass
    24.     def process_item(self, item, spider):
    25.         pic_url = 'http:' + item.get('src')
    26.         pic_name = './books/img/' + item.get('name') + '.jpg'
    27.         urllib.request.urlretrieve(pic_url, pic_name)
    28.         return item
    29.     # 在爬虫文件结束后执行的方法
    30.     def close_spider(self, spider):
    31.         pass
    复制代码
    管道处置惩罚设计完毕后,还必要共同 settings.py 设置管道除了优先级,同时记得解释ROBOTSTXT_OBEY = True【君子协议,为 True 则不允许爬取特定网站】
    1. ITEM_PIPELINES = {
    2.     # 值越小,管道优先级越高
    3.     "scrapy_dangdang.pipelines.ScrapyDangdangPipeline": 300,
    4.     "scrapy_dangdang.pipelines.DangDangDownloadPipeline": 301,
    5. }
    复制代码
  • 进入 spiders 目次,实行爬虫文件,完成资源爬取
    1. scrapy crawl dangdang
    复制代码

6.3 post请求处置惩罚

先前利用 start_urls 的方式指定初始访问界面,但在post请求中由于必要请求头,因此无法利用这种方式,以是针对post请求我们必要重新界说一种方式举行处置惩罚
  1. import scrapy
  2. import json
  3. class TransPostSpider(scrapy.Spider):
  4.     name = "trans_post"
  5.     allowed_domains = ["fanyi.baidu.com"]
  6.     # post请求需要指定请求体,start_urls无法做到
  7.     # start_urls = ["https://fanyi.baidu.com/mtpe-individual/multimodal#/"]
  8.     # 自定义请求体发送post请求
  9.     def start_requests(self):
  10.         url = 'https://fanyi.baidu.com/sug'
  11.         data = {
  12.             'kw': '你好'
  13.         }
  14.         # scrapy中的post,callback指定请求完毕后后续处理的函数
  15.         yield scrapy.FormRequest(url, formdata=data, callback=self.parse)
  16.     def parse(self, response):
  17.         content = json.loads(response.text)
  18.         print(content)
复制代码
7. CrawlSpider

CrawlSpider 继承至 scrapy.Spider,在解析网页内容的时候,它可以根据链接规则提取出指定的链接,然后再向这些链接发送请求,非常实用于爬取网页后必要提取链接举行二次爬取的环境。
其爬虫类创建命令稍有差别
  1. # 创建爬虫项目
  2. scrapy startproject scrapy_dushu
  3. # 爬虫类名称为read,爬取网站为www.dushu.com
  4. scrapy genspider -t crawl read https://www.dushu.com/book/1107_1.html
复制代码
利用链接提取器过滤得到目标链接
  1. scrapy.linkextractors.LinkExtractor(
  2.         allow=(),        # 通过正则表达式过滤
  3.     restrict_xpaths=(),        # 通过xpath过滤(定位到a元素即可)
  4. )
复制代码
爬取读书网实战

   我们的目标是获取计算机网络/读书网首页所能看见页面里全部书名,图片链接信息
  
除了爬虫核心函数有所差别,其余setting,pipeline,items的用法雷同,此处不再赘述,根据需求自行修改即可
  1. import scrapy
  2. from scrapy.linkextractors import LinkExtractor
  3. from scrapy.spiders import CrawlSpider, Rule
  4. from scrapy_dushu.items import ScrapyDushuItem
  5. class ReadSpider(CrawlSpider):
  6.     name = "read"
  7.     allowed_domains = ["www.dushu.com"]
  8.     start_urls = ["https://www.dushu.com/book/1107_1.html"]
  9.     rules = (Rule(
  10.         LinkExtractor(
  11.             # 正则表达式写法
  12.             # allow=r'/book/1107_\d+\.html',
  13.             # xpath写法
  14.             restrict_xpaths=("//div[@class='pages']/a")
  15.         ),
  16.         # 重复调用的函数名称
  17.         callback="parse_item",
  18.         # 为False时不会在新页面中再次调用匹配规则,即最初过滤得到的链接不会实时变动
  19.         follow=False),)
  20.     def parse_item(self, response):
  21.         # 定位到所有图片
  22.         img_list = response.xpath(
  23.             "//div[@class='book-info']//a/img")
  24.         for img in img_list:
  25.             # 获取图书名称
  26.             name = img.xpath("./@alt").extract_first()
  27.             # 获取图书封面图片地址
  28.             src = img.xpath("./@data-original").extract_first()
  29.             if src is None:
  30.                 src = img.xpath("./@src").extract_first()
  31.             # 封装为数据结构交由管道处理
  32.             book = ScrapyDushuItem(name=name, src=src)
  33.             yield book
复制代码

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

汕尾海湾

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表