python实训笔记(静态爬虫)

静态爬虫

用户正常访问网页的流程

确定访问的网页地址(url)—>通过HTTP请求访问页面(敲回车)—>渲染后的网页页面

当用户正常访问一个页面时,页面会形成一个User-Agent信息,里面包括浏览器信息以及操作系统信息

爬虫访问网页的流程

确定访问的网页地址(url)—>通过HTTP请求访问页面(通过请求模块发起请求)—>获取构成网页的网页源代码

1、request请求模块

1、方法介绍
#get请求
requests.get(url="",headers={},params={})
#post请求
requests.post(url="",headers={},data={})
url:请求地址
#不带参数地址
url="https://www.baidu.com/" 
#带参数请求的地址
url="https://www.baidu.com/s?"
headers:请求携带的请求头信息
#构建请求头(Cookie,可以解决一些被滑块验证拦截的)
headers={"User-Agent":"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36",
         'Cookie':'PSTM=1594551075; BAIDUID=BE1EC0FB3BCD6D7CFDCE65D946DFA810:FG=1; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; BIDUPSID=FA3243625AB3769B9B328BF0C78C693F; BD_UPN=12314753; H_PS_645EC=44ed6iu06MUcGz32Hk2BJu%2B0G5x%2BHedT1fYJXZE4fPOjq0aYYWp1Lg5tMyw; delPer=0; BD_CK_SAM=1; PSINO=2; H_PS_PSSID=32099_1442_31672_32141_32139_31254_32045_32231_32090_32258_31640; BDUSS=lZOXhpWjBhMlRIMWVRNTFWd0c4NX5TNnVZYm9weGljMUlIRGtyZXBkLThsek5mRVFBQUFBJCQAAAAAAAAAAAEAAAA2JBrPZmx50sHA-9ChuOe45wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwKDF-8CgxfbE'} 
parmes/data:请求携带的参数信息
word=input("请输入查询的词语:") #获取查询的词语
#构建请求参数字典
params={
    "wd":word
}
最后进行请求和分析:
res=requests.get(url,headers=headers,params=params)
res.encoding="utf-8"#将得到的相应内容编码为utf-8
html=res.text#解析得到的响应内容
利用params进行多页请求和分析:
for page in range(1,6):
    pn=(page-1)*10 #构建换页的参数
    #构建请求参数字典
    params={
        "wd":word,
        "pn":str(pn)  #添加换页的参数pn
    }
    res=requests.get(url,headers=headers,params=params)
使用面的对象思想进行爬虫
import requests

class Tieba:
    def __init__(self):
        self.url="https://tieba.baidu.com/f?"
        self.headers={"User-Agent":"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36"}

    def get_params(self): #构建请求参数字典的函数
        name=input("请输入贴吧名称:")
        for page in range(1,6):
            self.filename="贴吧第%d页.html"%page
            pn=(page-1)*50
            params={
                "kw":name,
                "pn":str(pn)
            }
            self.get_html(params) #调用获取网页源代码的函数

    def get_html(self,params): #请求url地址并获取响应信息的函数
        res=requests.get(self.url,headers=self.headers,params=params)
        res.encoding="utf-8"
        html=res.text
        self.save_html(html) #调用保存数据的函数


    def save_html(self,html): #保存数据的函数
        with open(self.filename,"w",encoding="utf-8") as f:
            f.write(html)
            print(self.filename,"保存成功!")

tieba=Tieba()
tieba.get_params()

2、正则表达式re

元字符作用
.匹配任意一个字符(不包括\n)
\d匹配任意数字
\s匹配任意空白字符
\n匹配一个换行符
\S匹配任意非空白字符
\w匹配字母、数字以及下划线
\W匹配不是字母、数字以及下划线
*匹配0个或多个表达式
+匹配1次或者n次
匹配1个或0个前面的正则表达式定义的片段(非贪婪)
{m}精确匹配m个前面的表达式
^匹配一行字符串的开头
$匹配一行字符串的结尾
()分组,想要什么数据就给什么数据加括号
1、match匹配

匹配得到,返回匹配结果,匹配不到,则返回None

2、贪婪与非贪婪

1、贪婪匹配:(.*)(\d+) 贪婪只会留最后一个数字给第二个分组

2、非贪婪匹配:(.*?)(\d+)而非贪婪尽可能少的获取数据,所以一遇到数字就停止

3、search方法

会在匹配时扫描整个字符串,然后返回第一个成功的匹配结果

4、修饰符

包含一些可选修饰符来控制匹配模式

re.S代表多行匹配

5、findall()

返回所有符合正则表达式片段的列表

6、compile()
p=re.compile('\d{3}',re.S)
result=re.findall(p,s)
7、网页中正则表达式练习
import re

html = """<div class="threadlist_title pull_left j_th_tit ">
    <a rel="noreferrer" href="/p/6811318934" title="奥特曼路人辨识贴,帮助本吧吃瓜群众辨识全部奥特曼" target="_blank" class="j_th_tit ">奥特曼路人辨识贴,帮助本吧吃瓜群众辨识全部奥特曼</a>
</div>"""
p = re.compile('<div class="threadlist_title pull_left j_th_tit ">.*?title="(.*?)"', re.S)
result = re.findall(p, html)

p1 = re.compile('<div class="threadlist_title pull_left j_th_tit ">.*?href="(.*?)".*?title="(.*?)"', re.S)
result1 = re.findall(p1, html)
print(result1)

3、持久化

csv持久化存储

使用写入对象写入数据(写入的数据必须为序列 列表、元组)

import csv

L=["小明","20","男"]
L1=["小红","23","女"]
with open("data.csv","w",encoding="utf-8",newline="") as f: #newline=""表示取消两行数据之间的空行
    writer=csv.writer(f) #创建写入对象
    writer.writerow(L)  #写入数据
    writer.writerow(L1)
数据库持久化存储
import pymysql
#建立链接
conn=pymysql.connect(
    host="127.0.0.1",
    port=3306,
    user="root",
    password="root", #数据库密码  如果没有设置密码 为""
    database="demo"    #数据库名称
)
cursor=conn.cursor() #创建游标对象
#编写sql语句
sql_insert="""insert into movie(title,star,release_time) values (%s,%s,%s)"""
data=["我的世界","小明,小红","2020年7月14日"]
cursor.execute(sql_insert,data) #插入数据
conn.commit() #执行操作

4、解析器解析

1、bs4解析器

bs4解析方式是依赖第三方解析库,利用节点去取出页面内容,当多个相同名称节点,此方法只返回一个

from bs4 import BeautifulSoup

html = """
<html>
<head>
<title>The Dormouse's story</title>
</head>
<body>
<p class="title" name="dromouse"><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>
"""

soup = BeautifulSoup(html, "lxml")
print(soup.title)#提取节点信息
print(soup.p.b)#获取p标签里的b标签
print(soup.title.string)#提取文本信息
print(soup.a["href"])#获取a节点的href属性

#用标签选择
soup = BeautifulSoup(html, "lxml")
for ul in soup.find_all(name="ul"):#返回的结果是所有ul的列表信息
    for li in ul.find_all(name="li"):#返回的结果是所有li的信息
        print(li.string)#返回的结果是所有li的文本信息
        
#用id和class选择
soup = BeautifulSoup(html, "lxml")
print(soup.find_all("ul", id="list-2"))#返回id属性的信息
print(soup.find_all("ul", class_="list list-small"))#返回class属性的信息

#Css选择器
print(soup.select(".panel .panel-heading")
print(soup.select('div > ul > li'))

#用Bs4获取文本信息时,经常使用text
print(li.text)#如果有li中有span可以直接返回文本信息,string只会返回None
2、正则和bs4混用

需要将bs4获取的数据进行str的转换

才可以进行正则表达式的匹配

head=soup.head  #通过bs4获取head节点 head不是字符串
#想再通过正则表达式解析出head节点中的title节点中的文本信息The Dormouse's story
p=re.compile('<head>(.*?)</head>',re.S)
data=re.findall(p,str(head)) #当使用正则匹配bs4解析后的数据时,需要将此数据转换为str字符串类型
print(data)
#如果使用bs4解析正则表达式匹配过后的数据,需要将此数据转换变soup对象才能进行匹配
3、xpath解析器
parse_html = etree.HTML(text)
# 获取所有节点信息
print(parse_html.xpath("//*"))
# 通过标签符获取信息
print(parse_html.xpath("//li/a"))
# 通过属性获取详细信息
print(parse_html.xpath('//li[@class="link1"]/a/text() | //li[@class="link2"]/a/text()'))
# 获取a节点中的属性信息
print(parse_html.xpath('//a/@href'))
# 获取第几个,是以1初始
print(parse_html.xpath('//li[@class="link1"][2]'))
# 多属性值匹配
print(parse_html.xpath('//li[@class="link1" and @name="item"]/a/text()'))

5、非结构化数据的获取

import requests

url="http://tiebapic.baidu.com/forum/w%3D580/sign=03fb108f1ffa513d51aa6cd60d6c554c/01a82bf5e0fe99252e45ec0323a85edf8cb1719d.jpg"
res=requests.get(url)
res.encoding="utf-8"
# html=res.text  #text 解析网页源代码为字符串
html=res.content #将获取的图片数据转换为二进制数据
with open("杨超越.jpg","wb") as f:
    f.write(html)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值