python学习第十节:爬虫基于requests库的方法

python学习第十节:爬虫基于requests库的方法

requests模块的作用:

发送http请求,获取响应数据,requests 库是一个原生的 HTTP 库,比 urllib 库更为容易使用。requests 库发送原生的 HTTP 1.1 请求,无需手动为 URL 添加查询串, 也不需要对 POST 数据进行表单编码。相对于 urllib 库, requests 库拥有完全自动化 Keep-alive 和 HTTP 连接池的功能。

requests的请求方式

python 复制代码
import requests
requests.get("http://httpbin.org/get") #GET请求
requests.post("http://httpbin.org/post") #POST请求
requests.put("http://httpbin.org/put") #PUT请求
requests.delete("http://httpbin.org/delete") #DELETE请求
requests.head("http://httpbin.org/head") #HEAD请求
requests.options("http://httpbin.org/OPTIONS") #OPTIONS请求

1.requests模块发送get请求

GET 参数说明:res = requests.get(url,headers=headers,params,timeout)

• url:要抓取的 url 地址。

• headers:用于包装请求头信息。

• params:请求时携带的查询字符串参数。

• timeout:超时时间,超过时间会抛出异常。

python 复制代码
# 简单的代码实现
import requests 
# 目标url
url = 'https://www.baidu.com' 
# 向目标url发送get请求
response = requests.get(url)
# 打印响应网页内容
print(response.text)
获取响应的网页内容

response.text:返回字符串类型数据

python 复制代码
import requests 
# 向目标url发送get请求
response = requests.get('https://www.baidu.com' )
# 打印响应内容
print(response.text)

response.content:返回 bytes 类型数据,decode返回的也是字符串效果等同于response.text

python 复制代码
# response.content
import requests 
# 向目标url发送get请求
response = requests.get('https://www.baidu.com' )
# 打印响应内容
print(response.content) # 注意这里!
# 通过对response.content进行decode,来解决中文乱码
print(response.content.decode()) 
response.content.decode() # 默认utf-8
response.content.decode("GBK") # 改变编码格式

查看响应的url:

python 复制代码
import requests
response = requests.get("http://httpbin.org/get")
print(response.url)

服务器返回的cookies:

python 复制代码
import requests
response = requests.get("http://httpbin.org/get")
print(response.cookies)

查看响应的headers头:

python 复制代码
import requests
response = requests.get("http://httpbin.org/get")
print(response.headers)
反爬添加 headers 的请求

我们在访问一些加了反爬检测的网站时会别识别为爬虫;我们加了header之后就会轻松绕过。

python 复制代码
import requests
url = 'https://movie.douban.com/top250'
header = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36'
}
response = requests.get(url, headers=header)
print(response.text)
请求时携带参数

爬取动态网页时我们需要传递不同的参数获取 不同的内容;GET 传递参数有两种方法,可以直接在链接中添加参数或者利用 params 添加参数。

url发送带参数的请求:

python 复制代码
import requests
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36'
}
url = 'https://search.douban.com/movie/subject_search?search_text=肖申克的救赎'
response = requests.get(url, headers=headers)
print(response.text)

通过 params 携带参数字典:

需要把请求的关键存在字典变量里,发送请求的时候带上字典

python 复制代码
import requests
headers = {
           "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"
}
# 这是目标url
url = 'https://search.douban.com/movie/subject_search?'
# 请求参数是一个字典
kw = {'search_text': '肖申克的救赎'}
# 带上请求参数发起请求,获取响应
response = requests.get(url, headers=headers, params=kw)
print(response.text)
调用json() 方法

如果我们访问之后获得的数据是JSON格式的,那么我们可以使用json方法,直接获取转换成宁典格式的数据。

但是需要注意的是,如果返回的结果不是JSON格式,便会出现解析错误,抛出异常!

python 复制代码
import requests
response = requests.get("http://httpbin.org/get")
print(response.text)
print(response.json())
print(type(response.json()))
参数中携带cookie

网站经常利用请求头中的 Cookie 字段来做用户访问状态的保持,那么我们可以在 headers 参数中添加 Cookie ,模拟普通用户的请求。

可以先获取网站cookie:

python 复制代码
import requests
url = 'https://movie.douban.com/'
response = requests.get(url)
print(response.cookies)
#print(r.cookies.items())
# 响应的cookies
for key, value in response.cookies.items():
    print(f"{key} = {value}")

再使用cookie访问登录后网站内容

python 复制代码
import requests
import re
# 构造请求头字典
headers = {
# 从浏览器中复制过来的User-Agent
    "user-agent": 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36',
# 从浏览器中复制过来的Cookie
    "cookie": 'bid = Mx0Pmwb-qI8'
}
# 请求头参数字典中携带cookie字符串
response = requests.get('https://www.douban.com/doumail/', headers=headers)
data = re.findall('<div id="content">(.*?)<h1>(.*?)</h1>',response.text)
print(response.status_code)
print(data)

通过cookies参数来设置,将cookies构造字典传入cookies字段

python 复制代码
import requests
url = "'https://user.qzone.qq.com/这里写上要登录的QQ号/infocenter'"
headers = {
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36',
}
cookies={"Cookie":"123456789"}
r = requests.get(url, headers=headers,cookies=cookies)
print(r.text)
获取原始响应内容
python 复制代码
import requests
response = requests.get("http://httpbin.org/get")
print(response.raw)
指定响应字符编码
python 复制代码
print(response.encoding)  # 查看响应字符编码
response.encoding="utf-8"    #更改为utf-8编码
重定向allow_redirects

在网络请求中,通常都会存在重定向问题,在Requests中是默认开启允许重定向的,如果存在重定向时,自动继续跟随访问

python 复制代码
import requests
response = requests.get("http://httpbin.org/get",allow_redirects=False)

2.requests模块发送post请求

方法:post(url, data=None, json=None, **kwargs)

python 复制代码
import requests
payload = {"username": "admin", "password": "123456"}
#response = requests.post("http://httpbin.org/post", data={'usernaem':'admin'}
response = requests.post("http://httpbin.org/post", data=payload)
print(response.text)
POST 请求抓取网页
python 复制代码
import requests

wd = {"search_text": "金瓶梅"}
# 准备伪造请求
headers = {
# User-Agent:首字母大写,表示请求的身份信息;一般直接使用浏览器的身份信息,伪造爬虫请求
# 让浏览器认为这个请求是由浏览器发起的[隐藏爬虫的信息]
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36 Edg/85.0.564.41"
}
# 发送POST请求,附带要翻译的表单数据--以字典的方式进行传递
response = requests.post("https://search.douban.com/movie/subject_search?", data=wd)
print(response.url)
# 打印返回的数据
# print(response.content)
print(response.content.decode("utf-8"))
# print(response.text.encode("utf-8"))
使用Session维持登录信息
python 复制代码
import requests
import re
# 构造请求头字典
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36'
}
# 实例化session对象
session = requests.session()
# 访问登陆页获取登陆请求所需参数
response = session.get('https://github.com/login', headers=headers)
authenticity_token = re.search('name="authenticity_token" value="(.*?)" />',response.text).group(1)  # 使用正则获取登陆请求所需参数
# 构造登陆请求参数字典
data = {
'commit': 'Sign in', # 固定值
'utf8': ' ', # 固定值
'authenticity_token': 'authenticity_token', # 该参数在登陆页的响应内容中
'login':input('输入github账号:'),
'password':input('输入github账号:')
}
# 发送登陆请求(无需关注本次请求的响应)
session.post('https://github.com/session', headers=headers, data=data)
# 打印需要登陆后才能访问的页面
response = session.get('https://github.com/settings/profile', headers=headers)
print(response.text)
python 复制代码
from requests import sessions
headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36',

    }
session = sessions.Session()
response = session.get("https://www.baidu.com/s?wd=python",headers=headers)
print(response.text)
# or
# requests = sessions.Session()
# response = requests.get("https://www.baidu.com/s", params={"wd": "python"})

print(u"请求的URL: ", response.request.url)
print(u"请求的参数(GET方法专属): ", response.request.path_url)
print(u"请求的Method: ", response.request.method)
print(u"请求的头: ", response.request.headers)

print(u"响应状态码: ", response.status_code)
print(u"响应头: ", response.headers)
print(u"响应内容: ", response.content)

print(u"请求所带的cookie和响应所返回的cookie集合: ", response.cookies)
print(u"总共耗时: ", response.elapsed)
proxies 代理参数的使用

在爬虫开发过程中,经常会遇到被封IP或者频繁访问同一网站被限制访问等问题。这时,使用代理IP就可以避免这些问题,保证爬虫程序正常运行。

代理IP是指通过代理服务器获取的IP地址,因为代理服务器具有隐藏用户真实IP、改变客户端访问地址、提高访问速度、突破访问限制等功能,所以使用代理IP可以实现一些数据获取的目的。

在Python中,使用urllib库实现网页访问时,可以通过设置代理IP来实现IP轮换、反反爬虫等功能。下面,我们以爬取某个网站为例,讲解如何设置代理IP。

首先,我们需要从免费的代理IP网站上获取代理IP,这里以站大爷代理为例,代码如下:

python 复制代码
import requests
from bs4 import BeautifulSoup
def get_proxy():
	url = 'https://www.zdaye.com/free/'
	headers = {
	'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 Edge/16.16299'}
	r = requests.get(url, headers=headers)
	soup = BeautifulSoup(r.text, 'html.parser')
	table = soup.find('table', attrs={'id': 'ip_list'})
	proxies = []
	for row in table.tbody.find_all('tr'):
		if row.find_all('td')[4].string == 'HTTP':
			proxy = ':'.join([row.find_all('td')[1].string, row.find_all('td')[2].string])
			proxies.append(proxy)
	return proxies

上面的代码中,我们使用requests库访问西刺代理网站,获取网页内容。然后,使用BeautifulSoup库解析网页内容,获取代理IP信息。

获取到代理IP后,我们需要测试这些代理IP是否可用,筛选出可用的代理IP。代码如下:

python 复制代码
import requests
def test_proxy(proxy):
	url = 'https://www.baidu.com'
	proxies = {'http': 'http://' + proxy, 'https': 'http://' + proxy}
	try:
		r = requests.get(url, proxies=proxies, timeout=10)
		if r.status_code == 200:
			return True
		else:
			return False
	except:
		return False
		
def get_valid_proxies(proxies):
	valid_proxies = []
	for proxy in proxies:
		if test_proxy(proxy):
			valid_proxies.append(proxy)
	return valid_proxies

在上面的代码中,我们使用requests库通过代理IP访问百度网站,如果返回状态码为200,则说明代理IP可用。如果访问出现异常或者状态码不为200,则说明代理IP不可用。

获取到可用的代理IP后,我们就可以使用这些代理IP来访问指定的网站。代码如下:

python 复制代码
import random
import requests
def get_html(url, proxies):
	proxy = random.choice(proxies)
	proxies = {'http': 'http://' + proxy, 'https': 'http://' + proxy}
	headers = {
	'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 Edge/16.16299'}
	try:
		r = requests.get(url, headers=headers, proxies=proxies, timeout=10)
		if r.status_code == 200:
			return r.text
		else:
			return None
	except:
		return None

上面的代码中,我们使用random库随机选择一个代理IP,然后使用requests库访问指定的网站。在访问时,需要将代理IP添加到proxies参数中,这样就可以使用代理IP来访问指定的网站了。

完整代码

python 复制代码
import random
import requests
from bs4 import BeautifulSoup
def get_proxy():
	url = 'https://www.zdaye.com/free/'
	headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 Edge/16.16299'}
	r = requests.get(url, headers=headers)
	soup = BeautifulSoup(r.text, 'html.parser')
	table = soup.find('table', attrs={'id': 'ip_list'})
	proxies = []
	for row in table.tbody.find_all('tr'):
		if row.find_all('td')[4].string == 'HTTP':
			proxy = ':'.join([row.find_all('td')[1].string, row.find_all('td')[2].string])
			proxies.append(proxy)
	return proxies

def test_proxy(proxy):
	url = 'https://www.baidu.com'
	proxies = {'http': 'http://' + proxy, 'https': 'https//' + proxy}
	try:
		r = requests.get(url, proxies=proxies, timeout=10)
		if r.status_code == 200:
			return True
		else:
			return False
	except:
		return False

def get_valid_proxies(proxies):
	valid_proxies = []
	for proxy in proxies:
		if test_proxy(proxy):
			valid_proxies.append(proxy)
	return valid_proxies


def get_html(url, proxies):
	proxy = random.choice(proxies)
	proxies = {'http': 'http://' + proxy, 'https': 'http://' + proxy}
	headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 Edge/16.16299'}
	try:
		r = requests.get(url, headers=headers, proxies=proxies, timeout=10)
		if r.status_code == 200:
			return r.text
		else:
			return None
	except:
		return None

if __name__ == '__main__':
	url = 'https://www.baidu.com'
	proxies = get_proxy() #获取代理IP
	valid_proxies = get_valid_proxies(proxies) #获取可用的代理IP
	html = get_html(url, valid_proxies) #使用代理IP访问指定的网站,并返回HTML内容。
	print(html)

在上面的代码中,我们首先定义了一个函数get_proxy(),用于获取代理IP。然后,定义了一个函数test_proxy(),用于测试代理IP是否可用。接下来,定义了一个函数get_valid_proxies(),用于获取可用的代理IP。最后,定义了一个函数get_html(),用于使用代理IP访问指定的网站,并返回HTML内容。

上传文件
python 复制代码
url = 'https://httpbin.org/post'
files = {'file': open('report.xls', 'rb')}
r = requests.post(url, files=files)
print('\n', r.text)

requests版的豆瓣电影top250完整版代码

python 复制代码
from bs4 import BeautifulSoup
import re
import requests
# import urllib.request, urllib.error
import xlwt
import sqlite3

# urllib.parse模块是一个用于解析URL的工具包,支持各种对URL的操作,包括拆分、拼接、编码、解码等。
import urllib.parse

def main():
    baseurl = "https://movie.douban.com/top250?start="
    print("爬虫开始....")
    datalist = get_data(baseurl)
    save_path = r"D:\豆瓣网电影TOP250.xls"
    save_data(datalist, save_path)
    dbpath = "test1.db"
    saveData2DB(datalist,dbpath)

# 影片详情链接的规则
findLink = re.compile(r'<a href="(.*?)">')   # 创建正则表达式对象,表示规则(字符串的模式)
# 影片图片
findImgSrc = re.compile(r'<img.*src="(.*?)"',re.S)  # re.s 让换行符包含在字符中
# 影片片名
findTitle =re.compile(r'<span class="title">(.*)</span>')
# 影片评分
findRating = re.compile(r'<span class="rating_num" property="v:average">(.*)</span>')
# 找到评价人数
findJudge =re.compile(r'<span>(\d*)人评价</span>')
# 找到概况
findInq =re.compile(r'<span class="inq">(.*)</span>')
# 找到影片的相关内容
findBd = re.compile(r'<p class="">(.*?)</p>',re.S)
#   爬取所有网页内容
def get_data(baseurl):
    datalist = []
    # 循环爬取所有页面
    for i in range(0,10):
        url = baseurl + str(i*25)
        html = askurl(url)
        #print(html)

        # 逐一解析数据 把html使用html.parser进行解析
        soup = BeautifulSoup(html, "html.parser")

        # 引入正则表达式,匹配满足的特征的字符串
        for item in soup.find_all("div", class_="item"):   #查找符合要求的字符串,形成列表
            #print(item) #测试:查看电影item全部信息
            #break
            data = []  #用于保存所有数据
            item = str(item)
            Link = re.findall(findLink, item)[0]  # re.findall查询所有符合条件的字符串,返回一个列表
            data.append(Link)
            ImgSrc = re.findall(findImgSrc, item)[0]
            data.append(ImgSrc)
            Titles = re.findall(findTitle, item)     #片名可能只有一个中文名,没有外国名
            if (len(Titles)) == 2:
                ctitle = Titles[0]
                data.append(ctitle)             #添加中文名
                otitle = Titles[1].replace("/","")
                data.append(otitle)            #添加外国名
            else:
                data.append(Titles[0])
                data.append(" ")           #外国名字留空
            Rating = re.findall(findRating, item)[0]
            data.append(Rating)
            Judge = re.findall(findJudge, item)[0]
            data.append(Judge)
            Inq = re.findall(findInq, item)
            if (len(Inq) != 0 ):
                Inq = Inq[0].replace("。","")                     # 去掉 。
                data.append(Inq)
            else:
                data.append(" ")
            Bd = re.findall(findBd, item)[0]
            Bd = re.sub(r'<br(\s+)?/>(\s+)?',"",Bd)   # 去掉换行符<br/>
            Bd = re.sub(r'/', "", Bd)                 # 去掉 /
            data.append(Bd.strip())
            datalist.append(data)
            # print(len(datalist))
    return datalist


def save_data(datalist,save_path):
    book = xlwt.Workbook(encoding="utf-8",style_compression=0)
    sheet = book.add_sheet("豆瓣网电影TOP250",cell_overwrite_ok=True)
    col = ("电影链接","图片链接","电影中文名称","电影外语名称","电影评分","评论人数","电影概述","电影的相关内容")
    for i in range(len(col)):
        sheet.write(0,i,col[i])
    for i in range(len(datalist)):
        data = datalist[i]
        #print('爬到到第%d行了' % i)
        for j in range(len(data)):

            sheet.write(i+1, j,data[j])

    book.save(save_path)

def saveData2DB(datalist,dbpath):
    init_db(dbpath)
    conn =sqlite3.connect(dbpath)
    cur =conn.cursor()
    for data in datalist:
        for index in range(len(data)):
            if index == 4 or index ==5:
                continue
            data[index]='"'+data[index]+'"'
        sql1 ='''
                insert into movie250(info_link,pic_link,cname,ename,score,rated,instroduction,info)
                values(%s)'''% ",".join(data)
        print(sql1)
        cur.execute(sql1)
        conn.commit()
    cur.close()
    conn.close()

def init_db(dbpath):
    sql = '''
        create table movie250
        (
        id integer primary key autoincrement,
        info_link text,
        pic_link text,
        cname varchar,
        ename varchar,
        score numeric,
        rated numeric,
        instroduction text,
        info text
        )
    '''
    print(sql)
    conn = sqlite3.connect(dbpath)
    c = conn.cursor()
    c.execute(sql)
    conn.commit()
    conn.close()

# 爬取单个网页内容
def askurl(url):
    headers = {
        'User-Agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
                      "Chrome/121.0.0.0 Safari/537.36"
    }
    req = requests.get(url, headers=headers)
    try:
        html = req.content.decode('utf-8')
        # print(html)
    except requests.error.URLError as e:
        if hasattr(e, "code"):
            print(e.code)
        if hasattr(e, "reason"):
            print(e.reason)
    except Exception as e:
        print(e)

    return html


if __name__ == '__main__':
    main()
    # askurl('https://movie.douban.com/top250')
    print("爬虫结束")```
相关推荐
至简行远2 分钟前
路由器全局配置DHCP实验简述
linux·网络·数据结构·python·算法·华为·智能路由器
艾伦~耶格尔4 分钟前
Java API 之集合框架进阶
java·开发语言·学习
韩子谦5 分钟前
Java迭代器Iterator和Iterable有什么区别?
java·windows·python
至简行远8 分钟前
路由器接口配置DHCP实验简述
java·服务器·网络·数据结构·python·算法·智能路由器
hakesashou13 分钟前
python有main函数吗
开发语言·python
小肆不吃白菜19 分钟前
硬件(驱动开发概念)
linux·数据结构·学习
网安kk20 分钟前
2024年自学手册 网络安全(黑客技术)
网络·学习·安全·web安全·网络安全
肥猪猪爸41 分钟前
sklearn特征选取之RFE
数据结构·人工智能·python·算法·机器学习·数据挖掘·sklearn
CC城子44 分钟前
Wireshark学习使用记录
学习·测试工具·wireshark
繁依Fanyi1 小时前
828华为云征文|华为Flexus云服务器搭建Cloudreve私人网盘
开发语言·人工智能·pytorch·python·算法·华为云·php