python爬虫基础


[TOC]

requests 模块

官方文档

requests模块:发送 http 请求,获取响应数据;安装pip/pip3 install requests

requests 请求方式

  • respose = requests.get(url,data):data 为 post 数据,为一个字典
  • response = requests.post(url,data)
  • response = requests.put()
  • response = requests.delete()
  • response = requests.head()
  • response = requests.options()

requests 模拟浏览器

  • headers参数:接收字典形式的请求头即 key:value

  • params参数:一个参数字典,里面可以带 cookie;比如 get 请求的?id = 1 则 {“id”:1}

  • cookie参数:字典形式;每一个 cookie 都要写成 key:value 的形式

  • timeout参数:timeout = 3表示发送请求后,3秒钟内返回响应,否则就抛出异常

  • proxies参数:proxy 代理参数通过指定代理ip,让代理ip对应的正向代理服务器转发我们发送的请求,比如:

    • proxies = {
      “http”: “http://1.1.1.1:9527“,
      “https”: “https://1.1.1.2:9527“,
      }

      注意:如果proxies字典中包含有多个键值对,发送请求时将按照url地址的协议来选择使用相应的代理ip

  • files参数:文件上传,字典形式;eg:files = {'file':open('favicon.ico','rb')}

  • verify参数:SSL证书认证,当发送HTTPS请求的时候,会检查SSL证书,verify参数可以控制是否检查SSL证书。

  • auth参数:身份认证

requests 响应对象

  • response.text

    • 类型:str
    • 解码类型: requests模块自动根据 HTTP 头部对响应的编码作出有根据的推测,推测的文本编码
  • response.content ==> 可以解决中文乱码的情况

    • 类型:bytes
    • 解码类型: 没有指定,默认utf-8
  • response.url:响应的url;有时候响应的url和请求的url并不一致

  • response.status_code:响应状态码

  • response.request.headers:响应对应的请求头

  • response.headers:响应头

  • response.request._cookies: 响应对应请求的cookie;返回cookieJar类型

  • response.cookies:响应的cookie(经过了set-cookie动作;返回cookieJar类型)

  • response.json():自动将json字符串类型的响应内容转换为python对象(dict or list)

  • response.raise_for_status():主动抛出状态码异常

requests.utils.dict_from_cookiejar()函数可以把cookieJar类型转换为字典类型

import requests 

# 目标url
url = 'https://www.baidu.com' 

# 向目标url发送get请求
response = requests.get(url)

# 打印响应内容
#print(response.text)
#print(response.content.decode())
print("------------------------------------------------")
print(response.url)                         # 打印响应的url
print("------------------------------------------------")
print(response.status_code)                 # 打印响应的状态码
print("------------------------------------------------")
print(response.request.headers)             # 打印响应对象的请求头
print("------------------------------------------------")
print(response.headers)                     # 打印响应头
print("------------------------------------------------")
print(response.request._cookies)            # 打印请求携带的cookies
print("------------------------------------------------")
print(response.cookies)                     # 打印响应中携带的cookies

requests.session 会话保持

requests 模块中的 session 类能够自动处理发送请求获取响应过程中产生的 cookie ,进而达到状态保持的目的。

  • requests.session的作用
    • 自动处理cookie,即 下一次请求会带上前一次的 cookie
  • requests.session的应用场景
    • 自动处理连续的多次请求过程中产生的 cookie

session对象发送get或post请求的参数,与requests模块发送请求的参数完全一致

session = requests.session() # 实例化session对象
response = session.get(url, headers, ...)
response = session.post(url, data, ...)

Python 正则

正则表达式具有通用型,不仅 python 里面可以用,其他的语言也一样适用。

python 中re模块提供了正则表达式的功能,常用的有四个方法(match、search、findall)都可以用于匹配字符串

match

re.match()必须从字符串开头匹配!match 方法尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match 就返回none。

函数原型:

res = re.match(pattern, string)
# pattern     匹配的正则表达式
# string      要匹配的字符串
# 返回一个匹配对象
res.group() ==> 获取匹配内容
res.span() ==> 获取匹配内容的位置,左闭右开

eg:

import re
s = "123abc123"
pattern = '123'

res = re.match(pattern, s) 
print(res)
print(res.span())
print(res.group())
"""
输出:
<re.Match object; span=(0, 3), match='123'>
(0, 3)
123
"""

总结:

re.match()方法返回一个匹配的对象,而不是匹配的内容。如果需要返回内容则需要调用group()。通过调用span()可以获得匹配结果的位置。而如果从起始位置开始没有匹配成功,即便其他部分包含需要匹配的内容,re.match()也会返回None。

和 match 用法基本相同,但是 search 是从字符串中进行搜索,而不是起始位置开始

findall

findall 是寻找所有能匹配到的字符,并以列表的方式返回

re.S属性:

在字符串a中,包含换行符\n,在这种情况下

  • 如果不使用re.S参数,则只在每一行内进行匹配,如果一行没有,就换下一行重新开始。
  • 而使用re.S参数以后,正则表达式会将这个字符串作为一个整体,在整体中进行匹配。

eg:

import re
a = """aaatestaa     
aaaa123"""
print(re.findall('test.*123',a))       
print(re.findall('test.*123',a,re.S))
"""
输出:
[]
['testaa     \naaaa123']
"""

sub、split

sub():查找字符串中所有相匹配的数据进行替换

re.sub(pattern, replace, string)

split():对字符串进行分割,并返回一个列表

re.split(pattern, string)

网页解析

bs4

bs4 简介

官方文档

即BeautifulSoup,是python种的一个库,最主要的内容就是从网页中抓取数据。

BeautifulSoup提供一些简单的、python式的函数用来处理导航、搜索、修改分析树等功能。它是一个工具箱,通过解析文档为用户提供需要抓取的数据。

BeautifulSoup自动将输入文档转换为Unicode编码,输出文档转换为utf-8编码。你不需要考虑编码方式,除非文档没有指定一个编码方式;这时,BeautifulSoup就不能自动识别编码方式了。然后,你仅仅需要说明一下原始编码方式就可以了。

bs4 基本使用

节点查找

节点信息

from bs4 import BeautifulSoup


html_doc = """<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title"><b>The Dormouse's story</b></p>

<p class="story">Once upon a time there were three little sisters; and their names were
<a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>,
<a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
<a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
and they lived at the bottom of a well.</p>

<p class="story">...</p>
"""
#创建一个BeautifulSoup对象
bs = BeautifulSoup(html_doc, "html.parser")
print('---------------------------------------------')
#格式化输出全部内容
print(bs.prettify())
print('---------------------------------------------')
#取出title标签
print(bs.title, type(bs.title), dir(bs.title), sep='\n-----------------\n')
print('---------------------------------------------')
#取出第一个a标签
print(bs.a)
print('---------------------------------------------')
#取出a标签的所有属性,字典形式
print(bs.a.attrs)
print('---------------------------------------------')
#取出a标签的具体属性值
print(bs.a.attrs['href'])
print('---------------------------------------------')
#判断a标签是否有某属性
print(bs.a.has_attr('xxx'))
print('---------------------------------------------')
#bs.p.children取出第一个p标签的所有子节点,是一个迭代器
print(bs.p.children)
print(list(bs.p.children))
print(list(bs.p.children)[0])
print(list(bs.p.children)[0].text)
print('---------------------------------------------')
#找到所有标签:bs.find_all('tag'),返回一个列表
print(bs.find_all('a'))
for a in bs.find_all('a'):
    print(a.attrs['href'])
print('---------------------------------------------')
#找到包含某个属性的标签(如果有多个只返回第一个)
print(bs.find(class_='sister'))
print('---------------------------------------------')
#去掉标签,只输出内容
print(bs.get_text())
print('---------------------------------------------')

print('---------------------------------------------')
print('---------------------------------------------')
print('---------------------------------------------')

lxml

xpath 基础

表达式 功能描述
nodename 选中所有子节点。
/ 从根节点选取、或者是元素和元素间的过渡。
// 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置。
. 选取当前节点。
.. 选取当前节点的父节点。
@ 选取属性。
text() 选取文本。
from lxml import etree

html_doc = """<bookstore>
<book category="COOKING">
  <title lang="en">Everyday Italian</title> 
  <author>Giada De Laurentiis</author> 
  <year>2005</year> 
  <price>30.00</price> 
</book>
<book category="CHILDREN">
  <title lang="en">Harry Potter</title> 
  <author>J K. Rowling</author> 
  <year>2005</year> 
  <price>29.99</price> 
</book>
<book category="WEB">
  <title lang="en">Learning XML</title> 
  <author>Erik T. Ray</author> 
  <year>2003</year> 
  <price>39.95</price> 
</book>
</bookstore>

"""
#创建选择器对象
selector = etree.HTML(html_doc)
#取出页面所有链接
print(selector.xpath('book'))
print('---------------------------------------------')
print(selector.xpath('//book'))
print('---------------------------------------------')
#选取所有书作者的名字
print(selector.xpath('//bookstore/book/author/text()'))
print('---------------------------------------------')
#选取所有书的语言
print(selector.xpath('//bookstore/book/title/@lang'))
print('---------------------------------------------')
#选取第1本书的标题
print(selector.xpath('//book[1]/title/text()'))
print('---------------------------------------------')
#选取最后1本书的标题
print(selector.xpath('//book[last()]/title/text()'))
print('---------------------------------------------')
#选取倒数第2本书的标题
print(selector.xpath('//book[last()-1]/title/text()'))
print('---------------------------------------------')
#选取前两本书的标题
print(selector.xpath('//book[position()<3]/title/text()'))
print('---------------------------------------------')
#选取分类为WEB的书
print(selector.xpath('//book[@category="WEB"]/title/text()'))
print('---------------------------------------------')
#选取价格≥30的书
print(selector.xpath('//book[price>=30]/price/text()'))
print('---------------------------------------------')
#属性有多个值可以使用contains(@name, value)
print('---------------------------------------------')
print('---------------------------------------------')
print('---------------------------------------------')
print('---------------------------------------------')
"""
xpath:在XML文档中查找信息的语言
概念:
节点、属性、文本、命名空间、文档(根)节点
节点关系:
父 parent、子 children、同胞 sibling、先辈 ancestor、后代 descendant

nodename 选取所有子节点
//  从任意子节点中选取
/   从根节点选取
@ 选取属性
"""

实战

下厨房主页图片爬取

import os
from bs4 import BeautifulSoup
import requests

url = "https://www.xiachufang.com/"

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36 SLBrowser/8.0.0.12022 SLBChan/103"
}

session = requests.session()
res = session.get(url=url, headers=headers)
bs = BeautifulSoup(res.text, 'html.parser')

img_url = []
all_img = bs.find_all('img')
for i in all_img:
    if i.has_attr('data-src'):
        img_url.append(i.attrs['data-src'].split('?')[0])
    else:
        img_url.append(i.attrs['src'].split('?')[0])

for urll in img_url:
    filename = os.path.join(os.curdir, 'spider\img\\' + urll.split('/')[-1])
    res = session.get(url=urll, headers=headers)
    with open(filename, 'wb') as f:
        f.write(res.content)

动态网页

Selenium


文章作者: XiaozaYa
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 XiaozaYa !
  目录