python实战案例

Posted 苏州程序大白

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python实战案例相关的知识,希望对你有一定的参考价值。

✨博主介绍

💂 个人主页:苏州程序大白

💂 个人社区:CSDN全国各地程序猿

🤟作者介绍:中国DBA联盟(ACDU)成员,CSDN全国各地程序猿(媛)聚集地管理员。目前从事工业自动化软件开发工作。擅长C#、Java、机器视觉、底层算法等语言。2019年成立柒月软件工作室,2021年注册苏州凯捷智能科技有限公司

💅 有任何问题欢迎私信,看到会及时回复

👤 微信号:stbsl6,微信公众号:苏州程序大白

💬如果文章对你有帮助,欢迎关注、点赞、收藏(一键三连)

🎯 想加入技术交流群的可以加我好友,群里会分享学习资料

爬虫简单入门


爬虫合法性-君子协议
  • 关于爬虫的合法性,有君子协议
    在网站网址后加上/robots.txt查看君子协议
准备注意事项
  • 做爬虫前尽量不要使用任何网络代理,否则容易出现莫名的问题
手刃一个小爬虫(request模块实现)
  • 简单试做:将百度搜索源码爬取:
#百度
#需求:用程序模拟浏览器,输入一个网址,从该网址中获取到资源或者内容
from urllib.request import urlopen      #从包中导入模块

url="http://www.baidu.com"          #准备网址
resp = urlopen(url)            #用urlopen模拟浏览器打开网址,将返回的响应存入resp

"""
先print(resp.read())查看返回的内容
从中找到编码格式,一般为charset后位置
再进行解码

print(resp.read().decode("utf-8"))         #resp.read()从响应中读取内容,并用decode解码
"""

with open("D:\\desktop\\代码\\python测试\\Mywebsite.html",mode="w",encoding="utf-8") as web:            #打开名为"Mywebsite.html"的文件,模式为w写入,as语句将其简称为web,设置encoding打开编码
    web.write(resp.read().decode("utf-8"))              #resp.read()从响应中读取内容,并用decode解码,将其写入到上述文件

Web 请求、HTTP 协议、抓包


Web 请求过程解析
  • 1.服务器渲染:在服务器直接把数据和 html 整合在一起,统一返回给浏览器。
    举例:输入**www.baidu.com**,浏览器向百度服务器发送请求,百度返回 html 页面源代码;在百度里搜索关键词,百度在服务器将关键词有关数据写入 html 页面源代码中,一并返回给浏览器
  • 2.客户端渲染:第一次请求只要一个 html 骨架,第二次请求拿到数据,进行数据展示。在页面源代码中,看不到数据。
    举例:例如豆瓣电影排行榜的分类筛选网页,浏览器先向服务器请求,服务器返回 html 骨架(不包含数据),浏览器第二次请求,服务器返回数据,浏览器将 html 骨架与数据渲染结合,呈现页面。在源代码处搜索呈现的数据,无法找到。
  • 熟练使用浏览器抓包工具
    Chrome 浏览器右键检查或者 F12,上方大类选择 Network;
    刷新页面,此时所有返回的请求都在此处显示。点击文件可以打开源代码,通常第一个文件为网页骨架;
    Headers 中 Request URL 写有 url 地址,Preview 可以查看预览效果。在这些文件中通过预览找到和页面内容匹配的数据,回到 Headers 即可找到数据 url
  • 想要得到数据无需骨架,对于爬虫而言,目的为得到数据,骨架无影响
HTTP 协议
  • HTTP 协议基本概念

    • 协议:两台计算机之间为了能流畅的进行沟通而设置的一个君子协定,常见的协议有 TCP/IPSOAP 协议,HTTP 协议,SMTP 协议等

    • HTTP 协议:Hyper Text Transfer Protocol(超文本传输协议)的缩写,是用于从万维网(WWW:World Wide Web)服务器传输超文本到本地浏览器的传输协议。直白点儿,浏览器和服务器之间的数据交互遵守的就是 HTTP 协议

    • HTTP 协议把一条消息分为

      三大块内容

      ,无论是请求还是响应都是三块内容

      • 请求

        1、请求行 → 请求方式(get/post),请求 url 地址,协议
        2、请求头 → 放一些服务器要使用的附加信息
        3、请求体 → 一般放一些请求参数

      • 响应

        1、状态行 → 协议,状态码
        2、响应头 → 放一些客户端要使用的附加信息
        3、响应体 → 服务器返回的真正客户端要用的内容(HTML,json 等)

  • 抓包工具及获得的重要信息

    • Network-Headers-General:一般信息

      Request URL:URL 地址
      Request Method:请求方式
      Status Code:状态码

    • Network-Headers-

      Response Headers

      响应头

      cookie:本地字符串数据信息(用户登录信息,反爬的 token)
      其他:各种神奇的莫名其妙的字符串(这个需要经验,一般都是 token 字样,防止各种攻击和反爬)

    • Network-Headers-

      Request Headers

      请求头

      User-Agent:请求载体的身份标识(用啥发送的请求,如浏览器信息)
      Referer:防盗链(这次请求是从哪个页面来的,反爬需要)
      cookie:本地字符串数据信息(用户登录信息,反爬的 token)

    附:请求方式

    • Get:显示提交(常用于搜索,通常只读)
    • Post:隐式提交(常用于对数据增删改,通常可写入)

requests 模块入门


模块安装
  • requests 模块为第三方支持库,需要手动安装
pip install requests
Requests 入门-1

GET 请求:将搜狗搜索内容爬取,并学习简单的反爬

import requests

url = "https://www.sogou.com/web?query=周杰伦"          #保存网址字符串给变量,中文可能转码错误,手动打上去
#第10行处被拦截,可以将更多请求头信息补入,定义一个字典headers,将User-Agent写入字典,User-Agent通过抓包网页骨架中的Request Headers(请求头)找到,注意直接复制后Mozilla前会多一个空格,记得删除
dict = "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36"

#用get请求方式请求url,所有地址栏中的url都是get方式请求,将响应存入resp。第四行信息补充完成后,将字典写入headers参数,处理简单的反爬
resp = requests.get(url,headers=dict)

#print(resp)         #打印resp,返回网页状态码,返回200正常
print(resp.text)        #打印页面源代码,但爬虫被拦截了,前往第四行补充信息

resp.close()            #关闭请求

可以进行一些小修改,做到更改搜索对象:

import requests

#手动输入搜索的内容
query=input("输入你要搜索的内容:")
#利用f-string,做到搜索内容更改
url = f"https://www.sogou.com/web?query=query"          #保存网址字符串给变量,中文可能转码错误,手动打上去
#第10行处被拦截,可以将更多请求头信息补入,定义一个字典headers,将User-Agent写入字典,User-Agent通过抓包网页骨架中的Request Headers(请求头)找到,注意直接复制后Mozilla前会多一个空格,记得删除
dict = "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36"

#用get请求方式请求url,所有地址栏中的url都是get方式请求,将响应存入resp。第四行信息补充完成后,将字典写入headers参数,处理简单的反爬
resp = requests.get(url,headers=dict)

#print(resp)         #打印resp,返回网页状态码,返回200正常
print(resp.text)        #打印页面源代码,但爬虫被拦截了,前往第四行补充信息

resp.close()            #关闭请求
Requests 入门-2

POST 请求:爬取百度翻译的结果

"""
打开百度翻译后按F12进入抓包工具,清除多余的文件,注意输入法切换为英文,输入英文单词后,翻译框下方有一个小列表
在抓包工具中通过preview预览尝试寻找列表的数据文件,发现sug文件为数据文件
打开sug文件的Headers,获取需要的信息:url地址,请求方式为POST
打开Payload,找对From Data,为POST传参数据,对于上个GET程序中利用f-string传入参数的方式就不灵了
"""
import requests

url = "https://fanyi.baidu.com/sug"         #准备url,注意url为数据的url,即sug文件Headers的url

word = input("请输入你要翻译的英文:")        #准备翻译的单词
dat = "kw":word               #由于POST传参数据来源为From Data,所以按照From Data中的格式,将搜索数据改写入字典,此时可以通过变量更改数据

resp = requests.post(url,data=dat)             #由于网页访问方式为POST,故使用POST访问,将dat传入data参数,即传入From Data。将响应存入resp
#print(resp.text)               #输出发现文件有乱码,可以另外直接输出json文件
print(resp.json())                #将服务器返回的内容直接处理成json(),按照python字典方式输出

resp.close()            #关闭请求

#总结,对于POST请求,发送的数据必须放在字典中,通过data参数进行传递
Requests 入门-3

浏览器渲染的二次 GET 请求网页
豆瓣电影分类排行榜-喜剧

  • 通常网站 url 里有问号”?”,问号前的是 url,问号后的是参数
"""
豆瓣电影分类排行榜网页通过浏览器渲染,有两次数据传递
在抓包工具中选择筛选XHR类别(常表示二次请求数据),找到跟页面差不多的蕴含量大一些的XHR文件,就是页面的数据文件找到数据文件Headers:
查看url,通常网站url里有问号"?",问号前的是url,问号后的是参数,查看请求方式为GET方式
在Payload中有Query String Parameters(url问号后参数),
"""
import requests

url = "https://movie.douban.com/j/chart/top_list"        #参数过长,可以重新封装url参数,url问号后参数部分可以删除

#重新封装参数。将抓包Query String Parameters的参数复制进字典,分别打双引号,加逗号
param = 
    "type": "24",
    "interval_id": "100:90",
    "action":"" ,
    "start": "0",
    "limit": "20"


header = "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36"        #布置user-agent

resp = requests.get(url,params=param,headers=header)              #将param的参数传入params(截止params)。将返回的响应存入resp
#print(resp.request.url)         #输出按照参数重组后的url地址
#print(resp.text)                #code 0,什么都没有,说明被反爬了
print(resp.json())

resp.close()            #关闭请求

#反爬处理

#首先尝试修改user-agent
#print(resp.request.headers)         #(补充)查看默认信息,user-agent
#获取浏览器抓包user-agent,准备(第20行),写入requests.get的参数
#成功拿到数据,但有乱码,将24行优化为25行,获取json文件
  • 在豆瓣中下拉,刷新出新的电影,同时 Query String Parameters 中出现新的数据,与原数据对比发现只有 Query String Parameters 的 start 参数变化,可以借此修改代码中 start 参数实现新效果

数据解析


数据解析概述
  • 爬取到的网站内容和数据被夹在了

    html
    

    内,想要提取需要的数据,这便涉及到了数据提取

    本课程提供三种解析方式:

    Re 解析(理论运行速度最快)
    Bs4 解析(代码简单,但效率较低)
    Xpath 解析(目前较流行,中规中矩)

  • 三种方式可以混合进行使用,完全以结果做导向,只要能拿到想要的数据,用什么方法不重要,当掌握了这些之后再考虑性能的问题

Re 解析_正则表达式
  • Re 解析:Regular Expression 的简写,正则表达式,一种使用表达式的方式对字符串进行匹配的语法规则
  • 我们抓取到的网页源代码本质上就是一个超长的字符串。,想从里面提取内容,用正则表达式再合适不过了
  • 优点:速度快效率高准确性高
    缺点:新手上手难度较大
  • 不过只要掌握了正则编写的的逻辑关系,写出一个提取页面内容的正则并不复杂
  • 正则的语法:使用元字符进行排列组合用来匹配字符串
    在线测试正则表达式https://tool.oschina.net/regex/
  • 元字符:具有固定含义的特殊符号
  • 常用元字符
  • 量词:控制前面的元字符出现的次数
  • 贪婪匹配惰性匹配

    这两个着重说一下,写爬虫用的最多的就是惰性匹配
    *?表示尽可能少的让*匹配东西
Bs4 解析_HTML 语法
  • Bs4 解析:Beautiful Soup4 的简写,简单易用的 HTML 解析器,需要掌握一些 HTML 语法
  • HTML(Hyper Text Markup Language)超文本标记语言,是编写网页最基本最核心的语言,其语法就是用不同的标签,对网页上的内容进行标记,从而使网页显示不同的效果,简单举例:
<h1>I Love You</h1>
  • 常用标签
  • 属性:标签内后跟的控制标签行为属性,其后所写的为属性值,简单举例:
<h1 align="right">I Love You</h1>

借此实现标题文字右对齐,其中,align为属性,right为属性值

  • 由此,HTML基本语法格式为:
<标签 属性="" 属性="">被标记的内容</标签>
Xpath 解析_XML 概念
  • Xpath 解析:XML 解析器,用来提取XML 文档中的节点,Xpath 是在 XML 文档中搜索的一门语言。HTML 是 XML 的一个子集
  • 基础概念
<book>
  <id>1</id>
  <name>野花遍地香</name>
  <price>1.23<price>
  <author>'
    <nick>周大强</nick>
    <nick>周芷若</nick>
  </author>
</book>

在上述 html 中:

  1. book,id,name,price等都被称为节点
  2. id,name,price,author被称为book子节点book被称为他们的父节点
  3. id,name,price,author被称为同胞节点

python 实现 Re 解析


Python 的 re 模块使用

在 python 中使用正则表达式,可以使用re模块,re模块记住几个常用功能就足够我们日常使用了:

import re           #引入re模块

#findall:匹配字符串中所有的符合正则的内容
list = re.findall("\\d+","我的电话号是10086,我朋友的电话是10010")           #findall的结果是一个列表
print(list,"\\n")

#列表效率低下,面对大量数据难以应对,按如下处理
#finditer:匹配字符串中所有的内容[返回的是迭代器],从迭代器中遍历拿到内容需要.group()函数
it = re.finditer("\\d+","我的电话号是10086,我朋友的电话是10010")
#print(it)
for i in it:
    print(i.group())
print()

#search返回的结果是match对象,那数据需要.group(),此外search全文检索,检索到一个就直接返回
s = re.search("\\d+","我的电话号是10086,我朋友的电话是10010")
#print(s)
print(s.group(),"\\n")

#match从头开始匹配,可以认为默认在正则前加了^符号,如下方10086前加一个非数字,则匹配为空
a = re.match("\\d+","10086,我朋友的电话是10010")
print(a.group(),"\\n")

#compile预加载正则表达式,能够提高一定的运行效率
obj = re.compile("\\d+")
#此时obj即预加载\\d+的正则,下次使用可以obj.函数,如下:
ret = obj.finditer("我的电话号是10086,我朋友的电话是10010")
#print(ret)
for it in ret:
    print(it.group())
print()

#用正则表示全部文本信息
s="""
<div class='jay'><span id='1'>雷军</span></div>
<div class='jj'><span id='2'>李彦宏</span></div>
<div class='jolin'><span id='3'>张小龙</span></div>
<div class='sylar'><span id='4'>马云</span></div>
<div class='tory'><span id='5'>马化腾</span></div>
"""
obj1 = re.compile("<div class='.*?'><span id='\\d+'>.*?</span></div>",re.S)            #re.S作用:让点.能匹配换行符
#<div class='部分都一样,后面不一样部分.*?代替,匹配后jay双引号后部分一样,一直到id=后单引号后不同,
#用\\d或\\d+或者.*?代替,后同理,略
result = obj1.finditer(s)
for it in result:
    print(it.group())
print()

#从全部文本信息中提取想要的信息(在上述代码中修改)
#在要提取的文本.*?等正则符号处,用小括号包住,小括号前写?P<组名> ,最后在遍历的组括号(60行)写入这个组名
obj1 = re.compile("<div class='.*?'><span id='\\d+'>(?P<gualudeng>.*?)</span></div>",re.S)            #re.S作用:让点.能匹配换行符
#<div class='部分都一样,后面不一样部分.*?代替,匹配后jay双引号后部分一样,一直到id=后单引号后不同,
#用\\d或\\d+或者.*?代替,后同理,略
result = obj1.finditer(s)
for it in result:
    print(it.group("gualudeng"))
print()
手刃豆瓣 top250

豆瓣 top250

#数据在页面源代码中
#思路:拿到页面源代码,通过re正则提取我们想要的有效信息
from email import header
import requests,re,csv

url = "https://movie.douban.com/top250"
ua = "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36"
resp = requests.get(url,headers=ua)             #简单的提取源代码和反反爬
#print(resp.text)            #检查页面源码
page_content = resp.text            #保存源代码至变量

#解析数据
#正则表达式定位,建议找需要数据的上几层标签做定位
#<li>为上层标签,换行时的空白可能是换行可能是空格,使用.*?表示,继续匹配到下一行,后面多行都用.*?匹配,直接找到需要的title,在需要部分单独列组(),补充后面的截止部分(此处截止至</span>处),后略
obj = re.compile('<li>.*?<div class="item">.*?<span class="title">(?P<title>.*?)</span>.*?<p class="">.*?<br>(?P<year>.*?)&nbsp.*?<span class="rating_num" property="v:average">(?P<score>.*?)</span>',re.S)               #编写正则方法

#使用finditer进行正则筛选
result = obj.finditer(page_content)
#遍历result,得到数据
for it in result:
    print("\\n电影名:",it.group("title"),"\\n年份:",it.group("year").strip(),"\\n评分:",it.group("score"))            #group中的名字均为正则中的组名, .strip()为去除空白(空格)

#将数据存入文件,建议存储为csv格式。引入csv模块,.csv文件默认以逗号进行数据分割
f = open("data.csv",mode="w",encoding="utf-8")          #打开文件data.csv,没有文件自动创建,模式为r写入,打开格式为utf-8
csvwriter = csv.writer(f)               #创建csvwriter,写入数据时写入f文件,注意写入数据格式应为字典
result = obj.finditer(page_content)     #同18行
for it in result:
    dic= it.groupdict()                 #创建字典,将上述20-21行数据整理进字典
    dic["year"] = dic["year"].strip()           #单独处理需要去掉空格的year组
    csvwriter.writerow(dic.values())              #writerow为写入一行函数,括号()内为写入数据,写入的为字典的数据.values()
f.close()                               #关闭文件
print("over!")

#目前完成了top25的整理,而翻页数据只需要修改url后的参数即可,比如第二页url为https://movie.douban.com/top250?start=25&filter=
#由此得第一页参数start=0,第三页start=50,所以输出top250排行榜,可以此为方向研究

参考源代码:

屠戮盗版天堂电影信息

盗版天堂
补充 html 中 a 标签超链接知识

"""
1、确认数据在页面源码中,定位到2022必看热片
2、从2022必看热片中提取到子页面链接地址
3、请求子页面的链接地址,拿到想要的下载地址
"""
  • 实际操作
import requests,re

main_url = "https://dytt89.com/"            #主界面url
child_url_list = []
#原老版网站存在https加密,requests模块也有安全验证,所以会报错,可以使用verify=False关闭安全验证来解决,运行时最上部的警告意为“请求没有进行安全验证”。新版网站已取消
resp = requests.get(main_url , verify=False)          #verify=False关闭安全验证
resp.encoding = "gb2312"            #指定字符集编码
#print(resp.text)            #输出乱码,需要重新编码,网页编码格式通常在源码charset处会写明,找到后补充上一行代码,更改默认编码
#定位提取ul里面的li
obj1 = re.compile('2022必看热片.*?<ul>(?P<ul>.*?)</ul>',re.S)           #提取需要的部分
obj2 = re.compile("<a href='(?P<href>.*?)'",re.S)                       #提取a标签中的url链接

#开始筛选提取
result1 = obj1.finditer(resp.text)             #第一次提取板块源码部分
for it in result1:
    ul = it.group("ul")                         #存入ul
    #print(ul)              #检验输出
    #html知识补充:在html中,a标签表示超链接,如:<a href='url'>周杰伦</a>,网页上显示周杰伦的超链接,跳转地址为href=后的url
    #提取子页面链接(href后url)
    result2 = obj2.finditer(ul)             #第二次从板块源码部分提取url,但提取的url为参数,需要与main_url拼接
    for itt in result2:
        add = itt.group("href")                 #存入add
        #print(add)              #检验输出
        child_url = main_url + add.strip("/")              #拼接url,使用strip除去拼接处多余的一个/符号
        #print(child_url)            #检验输出
        child_url_list.append(child_url)            #将网址保存进列表里(注意空列表已经提前定义)

#提取子页面内容
obj3 = re.compile('◎片  名(?P<movie>.*?)<br />.*?<td style="WORD-WRAP: break-word" bgcolor="#fdfddf"><a href="(?P<download>.*?)">',re.S)
for url in child_url_list:
    child_resp = requests.get(url)           #操作基本同上
    child_resp.encoding = "gb2312"
    #下两行仅为测试使用
    #print(child_resp.text)
    #break
    result3 = obj3.search(child_resp.text)
    print(result3.group("movie"))
    print(result3.group("download"))

参考源代码:


python 实现 Bs4 解析


Python 的 bs4 模块使用

python 的 bs4 模块为第三方模块,需要先安装,安装 cmd 语法如下:

pip install bs4
抓取示例:北京新发地菜价(已失效,仅可参考)

北京新发地地址(已重构)
:页面重构,下示例代码仅可参考,无法运行,网站改为浏览器渲染,使用 POST 请求

# 页面源代码中能找到数据,所以直接爬取,后使用bs4提取数据即可
import requests
import csv
from bs4 import BeautifulSoup
url = "http://www.xinfadi.com.cn/marketanalysis/0/list/1.shtml"
resp = requests.get(url)
# print(resp.text)           #测试

# 准备需要写入的文件
f = open("菜价.csv", mode="w")
csvwriter = csv.writer(f)

# 解析数据,把页面源代码交给beautiful soup处理,生成bs4的对象
page = BeautifulSoup(resp.text, "html.parser")  # 括号第二个参数指定html解析器

# 从bs4对象查找数据(find / find_all(标签 属性="值"))
# 查找内容。由于class是python关键字,所以写class_代替
table = page.find("table", class_="hq_table")
# print(table)           #测试

# 得到的是表格,表格内每一行为tr标签,每一行内每列为td标签
# 再次筛选tr,拿到所有数据行,做切片,从1行开始切,去除0行的表头
trs = table.find_all("tr")[1:]
for tr in trs:              # 每一行的数据进行遍历
    tds = tr.find_all("td")              # 拿到每行中的所有td
    name = tds[0].text              # .text表示拿到被标签标记的内容
    low = tds[1].text
    avg = tds[2].text
    high = tds[3].text
    kind = tds[4].text
    set = tds[5].text
    date = tds[6].text
    # print(name, low, avg, high, kind, set, date)           #输出测试
    csvwriter.writerow([name, low, avg, high, kind, set, date])  # 写入文件,需要列表
f.close()
print("over")

参考源代码:

以上是关于python实战案例的主要内容,如果未能解决你的问题,请参考以下文章

培训网络爬虫与文本挖掘核心技术案例实战

深度学习实战案例:新闻文本分类

深度学习实战案例:新闻文本分类

PAI文本分析实验:常用文本分析组件及案例实战

Structured Streaming 实战案例 读取文本数据

python3多进程实战(python3经典编程案例)