python爬虫

一、Urllib

1、互联网爬虫

  • 解释1:通过一个程序,根据Url(http://www.taobao.com)进行爬取网页,获取有用信息。
  • 解释2:使用程序模拟浏览器,去向服务器发送请求,获取响应信息。

2、爬虫的核心

  • 爬取网页:爬取整个网页,包含了网页中所有的内容。
  • 解析数据:将网页中得到的数据进行解析。
  • 难点:爬虫和反爬虫之间的博弈。

3、爬虫的用途

  • 数据分析/人工数据集
  • 社交软件冷启动
  • 舆情监控
  • 竞争对手监控

4、爬虫分类

1)通用爬虫:
实例:百度、360、google、sougou等搜索引擎
功能:访问网页‐>抓取数据‐>数据存储‐>数据处理‐>提供检索服务
robots协议:一个约定俗成的协议,添加robots.txt文件,来说明本网站哪些内容不可以被抓取,起不到限制作用,自己写的爬虫无需遵守。
网站排名(SEO):

  • 根据pagerank算法值进行排名(参考网站流量、点击率等指标)
  • 百度竞价排名

缺点:

  • 抓取的数据大多是无用的
  • 不能根据用户的需求来精准获取数据

2)聚焦爬虫
功能:根据需求,实现爬虫程序,抓取需要的数据
设计思路:
1.确定要爬取的url。
2.模拟浏览器通过http协议访问url,获取服务器返回的html代码。
3.解析html字符串(根据一定规则提取需要的数据)。

5、反爬手段

1)User‐Agent
User Agent:中文名为用户代理,简称 UA,它是一个特殊字符串头,使得服务器能够识别客户使用的操作系统及版本、CPU 类型、浏览器及版本、浏览器渲染引擎、浏览器语言、浏览器插件等。
2)代理IP
西刺代理、快代理
什么是高匿名、匿名和透明代理?它们有什么区别?

  • 使用透明代理,对方服务器可以知道你使用了代理,并且也知道你的真实IP。
  • 使用匿名代理,对方服务器可以知道你使用了代理,但不知道你的真实IP。
  • 使用高匿名代理,对方服务器不知道你使用了代理,更不知道你的真实IP。

3)验证码访问
打码平台、云打码平台
4)动态加载网页
网站返回的是js数据,并不是网页的真实数据
5)数据加密
分析js代码

6、urllib库的使用

urllib.request.urlopen() 模拟浏览器向服务器发送请求
response 服务器返回的数据
response 的数据类型是 HttpResponse

  • 字节→字符串:解码decode
  • 字符串→字节:编码encode
方法作用
read()字节形式读取二进制 扩展:rede(5)返回前几个字节
readline()读取一行
readlines()一行一行读取,直至结束
getcode()获取状态码
geturl()获取url
getheaders()获取headers

urllib.request.urlretrieve()请求网页、请求图片、请求视频

7、请求对象的定制

UA介绍:User Agent中文名为用户代理,简称 UA,它是一个特殊字符串头,使得服务器能够识别客户使用的操作系统及版本、CPU 类型、浏览器及版本。浏览器内核、浏览器渲染引擎、浏览器语言、浏览器插件等。
语法:request = urllib.request.Request()

8、编解码

1)get请求方式:urllib.parse.quote()

import urllib.request
import urllib.parse

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

url = 'https://www.baidu.com/s?wd='
keyword = urllib.parse.quote('周杰伦')
url = url + keyword
print(url)
request = urllib.request.Request(url=url, headers=headers)
response = urllib.request.urlopen(request)
content = response.read().decode('utf-8')

print(content)

2)get请求方式:urllib.parse.urlencode()

import urllib.request
import urllib.parse

url = 'https://www.baidu.com/s?'
data = {
    'wd': '周杰伦',
    'age': '42',
    'location': '中国台湾'
}
url = url + urllib.parse.urlencode(data)
# print(url)
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
                  'Chrome/120.0.0.0 Safari/537.36'
}
request = urllib.request.Request(url=url, headers=headers)
response = urllib.request.urlopen(request)
content = response.read().decode('utf-8')

print(content)

3)post请求方式

import urllib.request
import urllib.parse
import json

url = 'https://fanyi.baidu.com/sug'

data = {
    'kw': 'spider'
}
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
                  'Chrome/120.0.0.0 Safari/537.36'
}
# post的请求参数必须要进行编码
data = urllib.parse.urlencode(data).encode('utf-8')
request = urllib.request.Request(url=url, data=data, headers=headers)
response = urllib.request.urlopen(request)
content = response.read().decode('utf-8')
content = json.loads(content)
print(content['data'][0]['v'])

4)post和get区别

  • get请求方式的参数必须编码,参数是拼接到url后面,编码之后不需要调用encode方法。
  • post请求方式的参数必须编码,参数是放在请求对象定制的方法中,编码之后需要调用encode方法。

9、ajax的get请求

import urllib.parse
import urllib.request


def creat_request(page_arg):
    url = 'https://movie.douban.com/j/chart/top_list?type=13&interval_id=100%3A90&action=&'
    data = {
        'start': (page_arg - 1) * 20,
        'limit': 20
    }
    url = url + urllib.parse.urlencode(data)
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
                      'Chrome/120.0.0.0 Safari/537.36'
    }
    return urllib.request.Request(url=url, headers=headers)


def get_content(request_arg):
    response = urllib.request.urlopen(request_arg)
    return response.read().decode('utf-8')


def download(page_arg, content_arg):
    with open('douban_' + str(page_arg) + '.json', 'w', encoding='utf-8') as fp:
        fp.write(content_arg)


if __name__ == '__main__':
    start_page = int(input('请输入起始页码:'))
    end_page = int(input('请输入结束页码:'))
    for page in range(start_page, end_page + 1):
        request = creat_request(page)
        content = get_content(request)
        download(page, content)

10、ajax的post请求

import urllib.request
import urllib.parse


def create_request(arg_page):
    url = 'https://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=cname'
    data = {
        'cname': '广州',
        'pid': '',
        'pageIndex': str(arg_page),
        'pageSize': '10'
    }
    data = urllib.parse.urlencode(data).encode('utf-8')
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
                      'Chrome/120.0.0.0 Safari/537.36'
    }
    request = urllib.request.Request(url=url, data=data, headers=headers)
    return request


def get_content(arg_request):
    response = urllib.request.urlopen(arg_request)
    content = response.read().decode('utf-8')
    return content


def download(arg_page, arg_content):
    with open('kfc_' + str(arg_page) + '.json', 'w', encoding='utf-8') as fp:
        fp.write(arg_content)


if __name__ == '__main__':
    for page in range(1, 4):
        created_request = create_request(page)
        geted_content = get_content(created_request)
        download(page, geted_content)

11、URLError\HTTPError

  • HTTPError类是URLError类的子类。
  • 导入的包urllib.error.HTTPErrorurllib.error.URLError
  • http错误:http错误是针对浏览器无法连接到服务器而增加出来的错误提示。引导并告诉浏览者该页是哪里出了问题。
  • 通过urllib发送请求的时候,有可能会发送失败,这个时候如果想让你的代码更加的健壮,可以通过try‐except进行捕获异常,异常有两类,URLError \ HTTPError
import urllib.request
import urllib.error

url = 'https://blog.csdn.net/m0_52503067/article/details/1308872711'
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
                  'Chrome/120.0.0.0 Safari/537.36'
}
try:
    request = urllib.request.Request(url=url, headers=headers)
    response = urllib.request.urlopen(request)
    content = response.read().decode('utf-8')
    print(content)
except urllib.error.HTTPError:
    print('系统正在维护中……')

异常

import urllib.request
import urllib.error

url = 'https://www.yixinchd.com'
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
                  'Chrome/120.0.0.0 Safari/537.36'
}
try:
    request = urllib.request.Request(url=url, headers=headers)
    response = urllib.request.urlopen(request)
    content = response.read().decode('utf-8')
    print(content)
except urllib.error.URLError:
    print('系统正在升级中……')

异常2

12、cookie登录

import urllib.request
# 适用的场景:进行数据采集的时候,需要绕过登录,然后进入某个页面

url = 'https://weibo.cn/6348128187/info'
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
                  'Chrome/120.0.0.0 Safari/537.36',
    'Cookie': 'SUB=_2A25IkTqmDeRhGeBN71oQ8ibNwzuIHXVr7zJurDV6PUJbktANLVPfkW1NRH7w-XCjbRc1bX9unbhvkaNW9jZBFLqP; SUBP=00'
              '33WrSXqPxfM725Ws9jqgMF55529P9D9W5UG-o5opBbliwJzv9ep.M35JpX5KzhUgL.Foq0Shnpeonp1hM2dJLoIEBLxKBLB.zLBK-Lx'
              'K-LB.qL1heLxK-L1K5L12eLxK-LB-BLBKqt; SSOLoginState=1704282870; _T_WM=88327e172a5590f58515f50a61044399; '
              'MLOGIN=1'
}

request = urllib.request.Request(url=url, headers=headers)
response = urllib.request.urlopen(request)
content = response.read().decode('utf-8')

with open('weibo.html', 'w', encoding='utf-8') as fp:
    fp.write(content)

13、Handler处理器

  • urllib.request.urlopen(url)不能定制请求头。
  • urllib.request.Request(url,headers,data)可以定制请求头。
  • Handler 定制更高级的请求头。随着业务逻辑的复杂,请求对象的定制已经满足不了我们的需求,动态cookie和代理不能使用请求对象的定制。
# 需求:使用handler访问百度,获取网页源码
import urllib.request

url = 'https://www.baidu.com'
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
                  'Chrome/120.0.0.0 Safari/537.36'
}

request = urllib.request.Request(url=url, headers=headers)
# 1.获取handler对象
handler = urllib.request.HTTPHandler()
# 2.获取opener对象
opener = urllib.request.build_opener(handler)
# 3.调用open方法
response = opener.open(request)

content = response.read().decode('utf-8')

with open('handler.html', 'w', encoding='utf-8') as fp:
    fp.write(content)

14、代理服务器

1)代理的常用功能

  • 突破自身IP访问限制,访问国外站点。
  • 访问一些单位或团体内部资源
    扩展:某大学FTP(前提是该代理地址在该资源的允许访问范围之内),使用教育网内地址段免费代理服务器,就可以用于对教育网开放的各类FTP下载上传,以及各类资料查询共享等服务。
  • 提高访问速度
    扩展:通常代理服务器都设置一个较大的硬盘缓冲区,当有外界的信息通过时,同时也将其保存到缓冲区中,当其他用户再访问相同的信息时, 则直接由缓冲区中取出信息,传给用户,以提高访问速度。
  • 隐藏真实IP
    扩展:上网者也可以通过这种方法隐藏自己的IP,免受攻击。

2)代码配置代理

  1. 创建Reuqest对象
  2. 创建ProxyHandler对象
  3. 用handler对象创建opener对象
  4. 使用opener.open函数发送请求
import urllib.request
import urllib.parse

url = 'https://www.baidu.com/s?wd=ip'

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

request = urllib.request.Request(url=url, headers=headers)


# response = urllib.request.urlopen(request)
proxies = {
    'http': '121.41.8.23:16817'
}
handler = urllib.request.ProxyHandler(proxies=proxies)
opener = urllib.request.build_opener(handler)
response = opener.open(request)


content = response.read().decode('utf-8')


with open('dali.html', 'w', encoding='utf-8') as fp:
    fp.write(content)

3)代理池

import urllib.request
import random


url = 'https://www.baidu.com/s?wd=ip'
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
                  'Chrome/120.0.0.0 Safari/537.36'
}
proxies_poll = [
    {'http': '121.41.8.23:16817'},
    {'http': '121.41.8.23:16817'},
]
proxies = random.choice(proxies_poll)
# print(proxies)
request = urllib.request.Request(url=url, headers=headers)

handler = urllib.request.ProxyHandler(proxies=proxies)
opener = urllib.request.build_opener(handler)
response = opener.open(request)
content = response.read().decode('utf-8')

with open('daili.html', 'w', encoding='utf-8') as fp:
    fp.write(content)

二、解析

1、xpath

xpath基本语法

  1. 路径查询
    //:查找所有子孙节点,不考虑层级关系
    / :找直接子节点
  2. 谓词查询
    //div[@id]
    //div[@id=“maincontent”]
  3. 属性查询
    //@class
  4. 模糊查询
    //div[contains(@id, “he”)]
    //div[starts‐with(@id, “he”)]
  5. 内容查询
    //div/h1/text()
  6. 逻辑运算
    //div[@id=“head” and @class=“s_down”]
    //title | //price

获取百度首页的百度一下

import urllib.request
from lxml import etree

url = 'https://www.baidu.com/'
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
                  'Chrome/120.0.0.0 Safari/537.36'
}
request = urllib.request.Request(url=url, headers=headers)
response = urllib.request.urlopen(request)
content = response.read().decode('utf-8')

tree = etree.HTML(content)
result = tree.xpath('//span/input[@id="su"]/@value')[0]
print(result)

在这里插入图片描述

获取站长素材的一些图片

六、scrapy

1、scrapy简介

Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架。 可以应用在包括数据挖掘,信息处理或存储历史数据等一系列的程序中。

安装scrapy:pip install scrapy

2、scrapy项目的创建以及运行

1)创建scrapy项目:scrapy startproject 项目名称
例:scrapy startproject dangdang_fiction

2)项目组成如下图所示:
在这里插入图片描述
scrapy.cfg:项目的配置文件。
spiders/dang.py:有我们自己创建,是实现爬虫核心功能的文件。
items.py:定义数据结构的地方,是一个继承自scrapy.Item的类
middlewares.py:中间件,代理
pipelines.py:管道文件,里面只有一个类,用于处理下载数据的后续处理,默认是300优先级,值越小优先级越高(1-1000)
settings.py:项目的配置文件,比如:是否遵守robots协议,User-Agent定义等。

3)创建爬虫文件:

  1. 跳转到spiders文件夹 cd 目录名字/目录名字/spiders
  2. scrapy genspider 爬虫名字 网页的域名

爬虫文件的基本组成:

import scrapy

class BaiduSpider(scrapy.Spider):
    name = 'baidu'
    allowed_domains = ['www.baidu.com']
    start_urls = ['http://www.baidu.com/']

    def parse(self, response):
        print('test test test')

name = '':运行爬虫文件时使用的名字。
allowed_domains = []:搜索的域名范围,即爬虫的约束区域,规定爬虫只爬取这个域名下的网页,不存在的URL会被忽略。
start_urls = []: 爬取的URL元组/列表。爬虫从这里开始抓取数据,所以,第一次下载的数据将会从这些urls开始。其他子URL将会从这些起始URL中继承性生成。
parse(self, response) :解析数据的回调函数。每个初始URL完成下载后将被调用,调用的时候传入从每一个URL传回的Response对象来作为唯一参数,主要作用如下:
a、负责解析返回的网页数据(response.body),提取结构化数据(生成item)
b、生成需要下一页的URL请求。

response.text:响应的是字符串。
response.body:响应的是二进制文件。
response.xpath():xpath方法的返回值类型是selector列表。
extract():提取的是selector对象的是data。
extract_first():提取的是selector列表中的第一个数据。

4)运行爬虫文件:
scrapy crawl 爬虫名称 注意:应在spiders文件夹内执行。

3、scrapy架构组成及工作原理

在这里插入图片描述

  • Scrapy Engine(引擎): 负责Spider、ItemPipeline、Downloader、Scheduler中间的通讯,信号、数据传递等。
  • Scheduler(调度器): 它负责接受引擎发送过来的Request请求,并按照一定的方式进行整理排列,入队,当引擎需要时,交还给引擎。
  • Downloader(下载器):负责下载Scrapy Engine(引擎)发送的所有Requests请求,并将其获取到的Responses交还给Scrapy Engine(引擎),由引擎交给Spider来处理,
  • Spider(爬虫):它负责处理所有Responses,从中分析提取数据,获取Item字段需要的数据,并将需要跟进的URL提交给引擎,再次进入Scheduler(调度器).
  • Item Pipeline(管道):它负责处理Spider中获取到的Item,并进行进行后期处理(详细分析、过滤、存储等)的地方。
  • Downloader Middlewares(下载中间件):一个可以自定义扩展下载功能的组件。
  • Spider Middlewares(Spider中间件):一个可以自定扩展和操作引擎和Spider中间通信的功能组件(比如进入Spider的Responses;和从Spider出去的Requests)
    在这里插入图片描述
    yield
  1. 带有 yield 的函数不再是一个普通函数,而是一个生成器generator,可用于迭代。
  2. yield 是一个类似 return 的关键字,迭代一次遇到yield时就返回yield后面(右边)的值。重点是:下一次迭代时,从上一次迭代遇到的yield后面的代码(下一行)开始执行。
  3. 简要理解:yield就是 return 返回一个值,并且记住这个返回的位置,下次迭代就从这个位置后(下一行)开始。
    日志信息和日志等级
    (1)日志级别:
    CRITICAL:严重错误
    ERROR: 一般错误
    WARNING: 警告
    INFO: 一般信息
    DEBUG: 调试信息
    默认的日志等级是DEBUG
    只要出现了DEBUG或者DEBUG以上等级的日志
    那么这些日志将会打印

(2)settings.py文件设置:
默认的级别为DEBUG,会显示上面所有的信息
在配置文件中 settings.py
LOG_FILE : 将屏幕显示的信息全部记录到文件中,屏幕不再显示,注意文件后缀一定是.log
LOG_LEVEL : 设置日志显示的等级,就是显示哪些,不显示哪些

scrapy的post请求
代理

  • 19
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

昵称只能一个月修改一次呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值