【python爬虫一】爬虫基础操作

这篇具有很好参考价值的文章主要介绍了【python爬虫一】爬虫基础操作。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

爬虫概述

  • 概念:是一种按照一定的规则,自动地抓取互联网上网页中相应信息(文本、图片等)的程序或脚本,然后把抓取的信息存储下来。

爬虫的分类

  • 通用爬虫:把一整张页面源码数据进行爬取
  • 聚焦爬虫:把页面中指定的数据进行爬取
  • 增量式爬虫:监测网站数据更新的情况。
  • 分布式爬虫:基于联合且分布的形式快速进行数据爬取
  • 功能爬虫:刷评论,点赞等功能

反爬机制

作用在web的服务端。制定相关的机制来阻止爬虫对其网站数据的爬取。

  • rebots 协议: 仅仅声明了门户端的哪些数据可被爬,哪些不可被爬。

反反爬机制

作用在爬虫,破解反爬机制。

requests 基础操作

  • requests 是一个基于网络请求的模块。用来模拟浏览器发请求。
import requests

url = 'https://www.sogou.com/'
# 发起get请求
response = requests.get(url=url)
page_text = response.text
with open('./sogou.html', 'w', encoding='utf-8') as fp:
	fp.write(page_text)

User-Agent 设置

headers = {
	'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36'
}
url = 'https://www.sogou.com/web?query=杭州'
response = requests.get(url=url, headers=headers)
page_text = response.text
with open('./hang.html', 'w', encoding='utf-8') as fp:
	fp.write(page_text)

# params 参数
wd = input("enter a keyword:")
params = {'query': wd}
url = 'https://www.sogou.com/web'
response = requests.get(url=url, headers=headers, params=params) # 参数动态化
page_text = response.text

# 响应数据为json 则
page_info = response.json()

发送post请求

headers = {
	'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36'
}
url = 'https://www.sogou.com/web?query=杭州'
data = {'page': 1, 'pageSize': 10}
response = requests.post(url=url, headers=headers, data=data)
page_text = response.json()

# 参数为json形式
data = {'page': 1, 'pageSize': 10}
requests.post(url=url, headers=headers, json=data)

urllib 基于网络请求的模块

# 基于requests 的图片爬取
import requests

headers = {
	'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36'
}
img_data = requests.get("https://lmg.jj20.com/up/allimg/tp03/1Z9221U602IE-0-lp.jpg", headers=headers).content # content 返回bytes类型的数据
with open('./123.jpg', 'wb') as f:
	f.write(img_data)

# 基于urllib的图片爬取
from urllib import request

request.urlretrieve("https://lmg.jj20.com/up/allimg/tp03/1Z9221U602IE-0-lp.jpg"'./234.jpg')

html 数据解析

bs4基本使用

  • 环境安装
pip install bs4 lxml
  • bs4实现解析的流程:
    • 实例化一个BeautifulSoup的对象,需要把即将解析的页面源码数据加载到该对象中。
    • 调用BeautifulSoup对象中相关的属性和方法进行标签定位和数据的提取
  • BeautifulSoup对象的实例化
    1. BeautifulSoup(fp, 'lxml') 可以将fp表示的一个文件中的数据进行解析操作
    2. BeautifulSoup(page_text, 'lxml') 直接将请求到的页面源码数据进行解析操作
from bs4 import BeautifulSoup

fp = open('./test.html', 'r', encoding='utf-8')
soup = BeautifulSoup(fp, 'lxml')

## 标签定位
soup.title # <title>document</title>

## 属性定位
soup.find('div', class_='tang') # 返回str
soup.find_all('div', class_='tang') # 返回列表

## 选择器定位
soup.select('#feng') #返回列表
soup.select('.tang>ul>li') # 返回列表

## 取文本内容
div_tag = soup.select('.tang')[0]
div_tag.text

## 取属性
a_tag = soup.find('a', id='feng')
a_tag['href']

总结:
bs4的基本使用:

  • 标签定位:
    • soup.tagName: 只可以返回符合条件的第一个标签
    • soup.find('tagName', attrName='value'): 属性定位。返回值是匹配到的第一个元素
    • soup.find_all('tagName', attrName='value'): 返回匹配到的所以元素。返回列表
    • soup.select('css 选择器') : 返回列表
  • 数据提取:
    • 取标签中存储的数据
      • string:只可以取出标签中直系的文本内容
      • text:可以取的标签中所有的文本
    • 取标签属性的数据
      • tag['attrName']

xpath 解析

  • 解析流程:
    • 实例化一个etree对象,然后把即将被解析的数据加载到该对象中
    • 调用etree对象中的xpath方法结合着不同形式的xpath表达式进行标签定位和数据提取
  • etree对象的实例化
    1. etree.parse(filePath)
    2. etree.HTML(page_text)
  • 标签定位
    • 非最左侧的/:表示一个层级
    • 非最左侧的//:表示多个层级
    • 最左侧的/:必须从根节点开始进行标签定位(/html),表示绝对路径
    • 最左侧的//:可以从任意位置进行标签定位,表示相对路径 **重点
    • 属性定位的写法://tagName[@attrName="value"]
    • 索引定位://tagName[index] 索引是从1开始的
  • 数据提取
    • 提取标签数据
      • //text(): 返回标签下所有节点的数据。包含子节点的文本内容
      • /text():只可以返回直接子节点的文本内容
    • 提取属性数据
      • /@attrName:获取指定属性的值。返回列表
from lxml import etree

tree = etree.parse('./test.html') # ElementTree 类型的对象
tree.xpath('/html/head/title')[0]
tree.xpath('/html//title')[0]
tree.xpath('//title')[0]

tree.xpath('//div[@class="song"]')
tree.xpath('//div[3]')

## 数据提取
tree.xpath('a[@id="feng"]//text()')
tree.xpath('a[@id="feng"]/text()')

tree.xpath('a[@id="feng"]//@href')

案例

from lxml import etree

page_text = requests.get("https://www.qiushibaike.com/text/", headers={
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36'
}).text

tree = etree.HTML(page_text)
div_list = tree.xpath('//*[@id="content"]/div/div[2]/div')
fot div in div_list:
	auther = div.xpath('./div[1]/a[2]/h2/text()')[0]  # 局部解析xpath, . 表示当前div
	content = div.xpath('./a[1]/div/span//text()')
	content = ''.join(content)
	print(auther, content)
  • xpath 管道符的使用
    • 作用:可以使得xpath表达式具有更强的通用性
    • //div[1]/a/@href | //div[1]/p/a/@href

requests 高级操作

Cookie在爬虫中的应用

  • 手动处理cookie:直接将cookie放在请求头headers中
  • 自动处理:Session对象
    • session的创建:requests.Session()
    • session可以和requests一样调用get和post进行请求发送。如果使用session进行请求发送,则服务端响应后产生的cookie会被自动存储到session对象中。第二次请求时,自动携带存储的cookie。(即:session对象至少要发送两次请求)
import requests

sess = requests.Session()
sess.get("https://xueqiu.com/")
sess.get("https://xueqiu.com/statuses/hot/listV2.json?since_id=-1&max_id=156113&size=15", headers=headers)

代理

import requests
from lxml import etree

headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36'}

# 配置代理
proxies = {'http': '102.129.157.20:8080'}
page_text = requests.get("https://www.sogou.com/web?query=ip",headers=headers, proxies=proxies).text

tree = etree.HTML(page_text)
content = tree.xpath('//*[@id="ipsearchresult"]/strong//text()')
print(content)

代理池

import random

proxy_pool = [{'http': '102.129.157.20:8080'}, {'http': '102.129.157.20:8080'}]
page_text = requests.get("https://www.sogou.com/web?query=ip",headers=headers, proxies=random.choice(proxy_pool)).text

异步爬虫

线程池

import requests
from multiprocessing.dummy import Pool
import time

urls = ['http://localhost:5000/hello', 'http://localhost:5000/hello', 'http://localhost:5000/hello']
def getRequest(url):
	page_text = requests.get(url).text
	return page_text

start = time.time()
pool=Pool(3)
page_list = pool.map(getRequest, urls)
for page_text in page_list:
	print(len(page_text))

print('总耗时:', time.time() - start)

生产者消费者模式

"""
生产者,消费者模式
"""
from threading import Thread
from queue import Queue
from urllib import request

from lxml import etree
import requests


class Producer(Thread):
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
                      'Chrome/112.0.0.0 Safari/537.36'
    }

    def __init__(self, page_queue, img_queue, *args, **kwargs):
        super(Producer, self).__init__(*args, **kwargs)
        self.page_queue = page_queue
        self.img_queue = img_queue

    def run(self) -> None:
        while True:
            if self.page_queue.empty():
                break
            url = self.page_queue.get()
            self.parse_page(url)

    def parse_page(self, url):
        response = requests.get(url, headers=self.headers)
        text = response.text
        html = etree.HTML(text)

        img_list = html.xpath('//*[@id="__layout"]//div[@class="expression-list clearfix"]//img')
        for img in img_list:
            img_url = img.xpath('./@data-src')[0]
            img_name = img.xpath('./@alt')[0] + '.jpg'
            print(img_name, img_url)
            self.img_queue.put((img_url, img_name))


class Consumer(Thread):
    def __init__(self, page_queue, img_queue, *args, **kwargs):
        super(Consumer, self).__init__(*args, **kwargs)
        self.page_queue = page_queue
        self.img_queue = img_queue

    def run(self) -> None:
        while True:
            if self.page_queue.empty() and self.img_queue.empty():
                break
            img_url, img_name = self.img_queue.get()
            request.urlretrieve(img_url, f"imgs/{img_name}")
            print(img_name + "\t 下载完成")


def main():
    page_queue = Queue(3)  # 存储页码链接的队列
    img_queue = Queue(10)  # 存储解析出来的图片链接
    # 想要爬取 前 10页的数据
    for x in range(1, 4):
        url = f"https://www.doutub.com/img_lists/new/{x}"
        page_queue.put(url)

    for x in range(2):
        t = Producer(page_queue, img_queue)
        t.start()

    for x in range(2):
        t = Consumer(page_queue, img_queue)
        t.start()


if __name__ == '__main__':
    main()

单线程+多任务的异步协程

  • 特殊的函数
    • 如果一个函数的定义被async关键字修饰,则该函数就是一个特殊的函数。
    • 特殊函数调用后,返回了一个协程对象
    • 函数内部的程序语句没有被立即执行
  • 协程
    • 特殊函数调用后返回的即是协程对象
  • 任务对象
    • asyncio.ensure_future(c)
  • 事件循环:eventLoop
    • asyncio.get_event_loop() 返回事件循环对象
    • 需要将任务对象注册到事件循环对象中,且启动事件循环即可
  • wait()方法
    • 进行任务对象的挂起操作。
    • 可以给每一个任务对象赋予一个可被挂起的权限
    • 挂起:如果挂起一个任务对象就表示让当前正在被执行的任务对象交出cpu的使用权。
  • await关键字:可以保证每一个任务对象的阻塞操作可以被异步执行
  • 核心点:如果特殊函数内部的实现语句中出现了不支持异步模块对应的代码,则会立即中断整个异步效果。
import asyncio
import time

async def getRequest(url):
    print("start: ", url)
    time.sleep(2)
    print("end. ")
    return 'aaa'

# 回调函数必须要有一个参数,就是回调函数的调用者(任务对象)
def callback(res, *args, **kwargs):
    # 特殊函数的返回值可以使用 result函数接受
    print("result: ", res.result())

# 协程对象
c = getRequest("www.baidu.com")
# 任务对象
task = asyncio.ensure_future(c)
# 任务对象的高级之处: 可以给任务对象绑定回调函数
task.add_done_callback(callback)
# 事件循环对象
loop = asyncio.get_event_loop()
# 将任务对象放到事件循环对象中,并启动事件循环
loop.run_until_complete(task)

开启多任务异步协程

import asyncio
import time


async def getRequest(url):
    print("start: ", url)
    # time.sleep(2) # 不支持异步模块的代码
    await asyncio.sleep(2)
    print("end. ")
    return 'aaa'


# 回调函数必须要有一个参数,就是回调函数的调用者(任务对象)
def callback(res, *args, **kwargs):
    # 特殊函数的返回值可以使用 result函数接受
    print("result: ", res.result())


start = time.time()
urls = ['www.baidu.com', 'www.jd.com', 'www.mi.com']
tasks = []
for url in urls:
    # 协程对象
    c = getRequest("www.baidu.com")
    # 任务对象
    task = asyncio.ensure_future(c)
    # 任务对象的高级之处: 可以给任务对象绑定回调函数
    task.add_done_callback(callback)
    tasks.append(task)

# 事件循环对象
loop = asyncio.get_event_loop()
# 将任务对象放到事件循环对象中,并启动事件循环
loop.run_until_complete(asyncio.wait(tasks))
print("花费时间: ", time.time() - start) # 2.0086746215820312

aiohttp 支持异步请求操作的模块

pip install aiohttp

requests 模块不支持异步,需要用aiohttp模块代替。异步协程爬虫代码案例:

import asyncio
import time

import aiohttp


async def getRequest(url):
    # page_text = await requests.get(url).text   # requests 不支持异步
    # 基于aiohttp 进行网络请求
    async with aiohttp.ClientSession() as sess: # 创建一个请求对象
        """
        发起请求的操作:
        sess.get/post(url, headers, data/params, proxy='http://ip:port')
        """
        async with await sess.get(url) as response:
            page_text = await response.text()  # read() => content    text() => text
            return page_text


# 回调函数必须要有一个参数,就是回调函数的调用者(任务对象)
def callback(res, *args, **kwargs):
    # 此处进行解析
    html_str = res.result()
    print("result: ", len(html_str))


start = time.time()
urls = ['https://www.baidu.com', 'https://www.jd.com', 'https://www.mi.com']
tasks = []
for url in urls:
    # 协程对象
    c = getRequest(url)
    # 任务对象
    task = asyncio.ensure_future(c)
    # 任务对象的高级之处: 可以给任务对象绑定回调函数
    task.add_done_callback(callback)
    tasks.append(task)

# 事件循环对象
loop = asyncio.get_event_loop()
# 将任务对象放到事件循环对象中,并启动事件循环
loop.run_until_complete(asyncio.wait(tasks))
print("花费时间: ", time.time() - start)

Selenium

selenium最初是一个自动化测试工具,而爬虫中使用它主要是为了解决requests无法直接执行JavaScript代码的问题 。
selenium本质是通过驱动浏览器,完全模拟浏览器的操作,比如跳转、输入、点击、下拉等,来拿到网页渲染之后的结果,可支持多种浏览器。

官网: https://selenium-python.readthedocs.io/
中文文档:https://selenium-python-zh.readthedocs.io/en/latest/

环境安装

  • 下载安装selenium:pip install selenium==3.141.0
  • 下载浏览器驱动程序:
    http://chromedriver.storage.googleapis.com/index.html
  • 下载驱动时,至少要保证大版本对应

基本操作

from selenium import webdriver

from time import sleep

# 1. 创建一个浏览器对象
bro = webdriver.Chrome(executable_path='./chromedriver.exe')
# 2. 发起请求
bro.get("https://www.baidu.com/")
# 3. 标签定位
search_ele = bro.find_element_by_id("kw")
# 4. 节点交互
search_ele.send_keys("Mac Pro")
sleep(2)
btn_ele = bro.find_element_by_xpath('//*[@id="su"]')
btn_ele.click()
sleep(2)

# js 注入
bro.execute_script('window.scrollTo(0, document.body.scrollHeight)')
sleep(5)

bro.close()

相关方法

"""
## 1. 获取页面内容
bro.page_source

## 2. 选择器(find系列)
# ===============所有方法===================
# 1、find_element_by_id   # 通过id查找控件
# 2、find_element_by_link_text  # 通过a标签内容找
# 3、find_element_by_partial_link_text  # 通过a标签内容找,模糊匹配
# 4、find_element_by_tag_name   # 标签名
# 5、find_element_by_class_name  # 类名
# 6、find_element_by_name      # name属性
# 7、find_element_by_css_selector  # 通过css选择器
# 8、find_element_by_xpath       # 通过xpaht选择器

## 3. 获取元素属性
# 重点
# tag.get_attribute('href')  # 找当前控件 的href属性对的值
# tag.text   # 获取文本内容

## 4. 元素交互
# tag.send_keys()  # 往里面写内容
# tag.click()      # 点击控件
# tag.clear()      # 清空控件内容
"""

动作链

动作链这个工具类中封装好了一些基于浏览器自动化的一系列连续的行为动作(如:滑动,拖拽)文章来源地址https://www.toymoban.com/news/detail-491317.html

from selenium import webdriver
from time import sleep

bro = webdriver.Chrome(executable_path="./chromedriver.exe")
url = 'https://www.runoob.com/try/try.php?filename=jqueryui-api-droppable'

bro.get(url)

# 这里定位的标签出现在了iframe标签之中,会定位失败, 
# 需要使用 switch_to(frame的ID) 来切换到该frame
bro.switch_to.frame("iframeResult")
div_tag = bro.find_element_by_xpath('//*[@id="draggable"]')

# 实例化动作链对象,且让该对象和bro对象进行绑定
action = webdriver.ActionChains(bro)
action.click_and_hold(div_tag)  # 点击且长按
for i in range(5):
    action.move_by_offset(20, 30).perform()  # perform 表示动作链立即执行
    sleep(1)

sleep(2)
bro.close()

无可视化界面的浏览器操作

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import time

# 创建一个参数对象,用来控制chrome以无界面模式打开
chrome_options = Options()
chrome_options.add_argument('--headless')
chrome_options.add_argument('--disable-gpu')

# 创建浏览器对象
browser = webdriver.Chrome(executable_path='./chromedriver.exe', chrome_options=chrome_options)
browser.get('https://www.baidu.com/')
time.sleep(3)
# 进行截图
browser.save_screenshot('baidu.png')
browser.close()

到了这里,关于【python爬虫一】爬虫基础操作的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 一个月学通Python(二十八):Python网络数据采集(爬虫)概述(爬虫)

    结合自身经验和内部资料总结的Python教程,每天3-5章,最短1个月就能全方位的完成Python的学习并进行实战开发,学完了定能成为大佬!加油吧!卷起来! 全部文章请访问专栏:《Python全栈教程(0基础)》 爬虫(crawler)也经常被称为网络蜘蛛(spider),是按照一定的规则自

    2024年02月14日
    浏览(41)
  • Python爬虫数据分析的基本概念

    Python爬虫数据分析是一种利用Python编程语言和相关的库来获取互联网上的数据,并对数据进行处理、分析和可视化的技术。Python爬虫数据分析技术在数据挖掘、商业智能、市场调研、舆情分析等领域都有广泛的应用。本文将介绍Python爬虫数据分析的基本概念、常用库和实战案

    2024年02月06日
    浏览(33)
  • linuxOPS基础_操作系统概述

    第一台计算机是1946 年2 月14 日诞生日,第一台名称ENIAC。体积一间屋子的大小,重量高达28t。 第一代:1946 – 1958 = 12 年 (电子管) 第二代:1958 – 1964 = 6 年 (晶体管) 第三代:1964 – 1970 = 6 年 (集成电路) 第四代:1970 – 至今 (大规模集成电路) CPU、内存、风扇、硬盘

    2024年02月06日
    浏览(26)
  • ElasticSearch 7.4学习记录(基础概念和基础操作)

    若你之前从未了解过ES,本文将由浅入深的一步步带你理解ES,简单使用ES。作者本人就是此状态,通过学习和梳理,产出本文,已对ES有个全面的了解和想法,不仅将知识点梳理,也涉及到自己的理解,初次学习踩的坑都汇总如下。 对于第一次接触ES的读者,该章节将直观的

    2024年02月12日
    浏览(24)
  • [架构之路-236]:目标系统 - 纵向分层 - 数据库 - 数据库系统基础与概述:三阶段模型(概念模型、逻辑模型、物理模型)、三级模式结构(外模式、模式、内模式)

    目录 一、数据库设计阶段性模型:概念模型、逻辑模型、物理模型 1.1 概念模型(Conceptual Model)- 业务模型: 实体:entity 属性或特征: key键值/码: 域(Domain): 实体类型:entity type 实体集合: 联系: 1.2 逻辑模型(Logical Model)- 内存模型(最核心): 1.3 物理模型(Phys

    2024年02月02日
    浏览(38)
  • C++OpenCV(2):图像处理基础概念与操作

    🔆 文章首发于我的个人博客:欢迎大佬们来逛逛 🔆 OpenCV项目地址及源代码:点击这里 通过 imread 我们可以读取一个图片 其形式如下: 而我们需要传递一个InputArray类型的参数,实际上就是 cv::Mat 如果创建cv::Mat呢? 可以通过 它的很多的构造函数 先来了解一下图片的 颜色通

    2024年02月16日
    浏览(27)
  • 【linux】docker基本概念和基础指令操作(镜像、容器)

    docker 镜像 images xxxx(名称):xxxx(版本号) 每一个image可以生成若干个 容器 (container),所有用相同镜像生成的容器环境完全一样 每一个容器都是一个完全独立的云端服务器

    2024年02月01日
    浏览(44)
  • #Python基础#JSON 和编码转换方法概述

    这里是关于 json.dumps() 、 json.loads() 、 .encode() 和 .decode() 方法的区别: json.dumps() : json.dumps() 方法用于将 Python 对象转换为 JSON 格式的字符串。 它接受一个 Python 对象作为参数,并返回一个 JSON 格式的字符串。 这个方法通常用于将 Python 字典、列表等数据结构转换为 JSON 格式

    2024年02月21日
    浏览(32)
  • python爬虫selenium操作下拉框详解

    使用python爬虫的selenium操作网页的下拉框。 以该网站为例:https://www.17sucai.com/pins/demo-show?id=5926 该网页下存在多个可供测试的下拉框。 基本脚手架代码: 定位下拉框(以第一个下拉框为例) Select()方法 不推荐这样定位 选中下拉框,点击 第一个下拉框的可选值如图所示 选择

    2024年02月11日
    浏览(38)
  • Python爬虫(4)-Selenium模拟鼠标操作

    在Selenium4.2以后的版本里面鼠标的操作方法都封装在了ActionChains中需要时直接取即可。 使用方法就是调用ActionChains然后传入你需要点击的按钮的位置即可 ActionChains(driver).double_click(f1).perform() perform()的意思就是执行所有ActionChains中的动作 具体的操作方法如下 鼠标单击就是直接

    2024年01月19日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包