python_chapter2_爬虫(Re正则表达式、Re模块补充、豆瓣实例、子页面获取下载地址实例、Bs4、Xpath)

python_chapter2_爬虫(Re正则表达式、Re模块补充、豆瓣实例、子页面获取下载地址实例、Bs4、Xpath)

在这里得感谢,B站up主路飞学城IT提供的优秀视频,此文章仅作为学习笔记,进行记录和分享…
python,爬虫(给兄弟们挂个🔗)

Alex,python基础

python边写边更…

一、数据解析概述:

若是服务器渲染,服务器会把 (html页面源码 + 数据) 放在一起 传回给 “浏览器”;而我们只想要,其中的一部分数据;这就涉及到数据抓取的问题;

有三种解析方式:

解析方式Re解析、bs4解析、xpath解析

二、Re解析:

1.re正则:
(之前在舍友的硬盘里,白嫖到Alex16年的自动化python课程 /滑稽/滑稽/滑稽,在模块那章讲的re,讲的很好…课下我也更了文章…大家可以看下,有问题相互交流)

传送门
(Re正则表达式,在这篇文章的最后一部分…)

开源中国,可以进行Re测试

三、Re模块补充:

(1)对之前写的文章,不足的进行了补充…

#Author:Jony c
#!/usr/bin/env  python 
# -*- coding:utf-8 -*-

import re

#1.返回匹配到正则表达式的所有内容;
res = re.findall(r"\d+","我的电话号码是10010,她的电话号码是10086")
print(res)

#2.返回匹配到正则表达式的所有内容[返回的迭代器];从迭代器中拿到内容需要“.group()”
res = re.finditer(r"\d+","我的电话号码是10010,她的电话号码是10086")
for i in res:
    print(i.group())

res = re.search(r"\d+","我的电话号码是10010,她的电话号码是10086")#也是迭代器;
print(res.group())

#3.预加载正则表达式;
obj = re.compile('\d+')
res = obj.finditer("我的电话号码是10010,她的电话号码是10086")
for i in res:
    print(i.group())

conclude:

语法实现
re.finditer和findall一样,变成迭代器;
print(obj.group())从迭代器里面拿取到“数据”
obj = re.complie("\d+")正则预编译,可以进行“点调用”;

(2)简单实例:

#Author:Jony c
#!/usr/bin/env  python
# -*- coding:utf-8 -*-
import re
s = """
<div name='西游记'><span id='1'>蔡许坤</span></div>
<div name='三国演义'><span id='2'>马包国</span></div>
<div name='水浒传'><span id='3'>药水哥</span></div>
<div name='红楼梦'><span id='4'>糖果超甜</span></div>
"""
#(?P<分组名字>正则运算符);
obj  = re.compile(r"<div name='(?P<book_name>.*?)'><span id='(?P<id>\d+)'>(?P<name>.*?)</span></div>",re.S)
#re.S...标记符,使“.”可以匹配到“换行符”,此时的“.”;
rsp = obj.finditer(s)

for i  in rsp:
    print(i.group("book_name"))#按分组名,进行分组;

conclude:

方法实现功能
(?P<>.*?)装逼专用,分组
re.S使“.”可以匹配到换行符;

四、手刃豆瓣排行榜实例:

在这里插入图片描述
1.requests + re :

#Author:Jony c
#!/usr/bin/env  python
# -*- coding:utf-8 -*-
import re,requests

#Requests
page_str = input("你想爬取内容的页数:")

page_number = int(page_str)*25  #start,每页25个
ur  = "https://movie.douban.com/top250"
par = {"start": page_number,"filter":"" }
hea={"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.85 Safari/537.36 Edg/90.0.818.49"}
#1.开始爬取:
res = requests.get(url=ur,params=par,headers=hea )
print(res.text,type(res.text))#2.输出爬取文本

#Re
s = res.text

obj  =re.compile(r'<li>.*?<span class="title">(?P<book_name>.*?)</span>.*?<p class="">.*?'
                 r'(?P<year>\d+)&nbsp;/&nbsp;(?P<city>.*?)&nbsp;/&nbsp;(?P<class>.*?)</p>'
                 r'.*?<span class="rating_num" property="v:average">(?P<score>.*?)</span>.*?<span>(?P<people_num>\d+)人评价</span>.*?</li>',re.S)

'''
obj = re.compile(r'<li>.*?<div class="item">.*?<span class="title">(?P<name>.*?)'
                 r'</span>.*?<p class="">.*?<br>(?P<year>.*?)&nbsp.*?<span '
                 r'class="rating_num" property="v:average">(?P<score>.*?)</span>.*?'
                 r'<span>(?P<num>.*?)人评价</span>', re.S)'''

data = obj.finditer(s)
for i in data:

    print(i.group("book_name").strip())
    print(i.group("year").strip())
    print(i.group("score").strip())
    print(i.group("people_num").strip())

(页数每也都是25个,所以start是25的倍数…)

2.导入到csv文件 :

#Author:Jony c
#!/usr/bin/env  python
# -*- coding:utf-8 -*-
import re,requests
import csv
#Requests
page_str = input("你想爬取内容的页数:")

page_number = int(page_str)*25  #start,每页25个
ur  = "https://movie.douban.com/top250"
par = {"start": page_number,"filter":"" }
hea={"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.85 Safari/537.36 Edg/90.0.818.49"}
#1.开始爬取:
res = requests.get(url=ur,params=par,headers=hea )
print(res.text,type(res.text))#2.输出爬取文本


f = open("data.csv",mode = "w",encoding="utf-8")
csv_obj = csv.writer(f)#点调用
#Re
s = res.text

obj  =re.compile(r'<li>.*?<span class="title">(?P<book_name>.*?)</span>.*?<p class="">.*?'
                 r'(?P<year>\d+)&nbsp;/&nbsp;(?P<city>.*?)&nbsp;/&nbsp;(?P<class>.*?)</p>'
                 r'.*?<span class="rating_num" property="v:average">(?P<score>.*?)</span>.*?<span>(?P<people_num>\d+)人评价</span>.*?</li>',re.S)

'''
obj = re.compile(r'<li>.*?<div class="item">.*?<span class="title">(?P<name>.*?)'
                 r'</span>.*?<p class="">.*?<br>(?P<year>.*?)&nbsp.*?<span '
                 r'class="rating_num" property="v:average">(?P<score>.*?)</span>.*?'
                 r'<span>(?P<num>.*?)人评价</span>', re.S)'''

data = obj.finditer(s)
for i in data:
   dic = i.groupdict()#把数据生成字典;
   dic['year'] = dic['year'].strip()
   dic['class'] = dic['class'].strip()
   csv_obj.writerow(dic.values())
print("over!")
csv文件操作
导入模块import csv
生成一个句柄obj = csv.writer(f)
开始写入obj.writerow(values)
生成字典
1.it.groupdic()
2.obj.writerow(dic.values)

五、子页面获取下载地址实例:

step1:

#Author:Jony c
#!/usr/bin/env  python 
# -*- coding:utf-8 -*-
#1.定位到2020必看热片;
#2.从2020必看片中,提取到子页面的链接地址;
#3.请求子页面的链接地址,拿到我们想要的下载地址....
import requests,re

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

resp = requests.get(url,verify = False)   #verify  =false  去掉安全认证
resp.encoding="gb2312"#按照gb2313解码,gbk向下兼容gb2312;
print(resp.text)

obj1 =  re.compile(r"2021必看热片.*?<ul>(?P<child_page>.*?)",re.S)
obj1.search(resp.text)

step2:

obj1 =  re.compile(r"2021必看热片.*?<ul>(?P<child_page>.*?)</ul>",re.S)

resp1 = obj1.search(resp.text)#一次查询,生成迭代器;
print(resp1.group())

在这里插入图片描述
step3:
在这里插入图片描述
在这里插入图片描述

#Author:Jony c
#!/usr/bin/env  python
# -*- coding:utf-8 -*-
#1.定位到2020必看热片;
#2.从2020必看片中,提取到子页面的链接地址;
#3.请求子页面的链接地址,拿到我们想要的下载地址....

#1.拿到子页面信息;
import requests,re

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

resp = requests.get(url,verify = False)   #verify  =false  去掉安全认证
resp.encoding="gb2312"#按照gb2313解码,gbk向下兼容gb2312;
#print(resp.text)


obj1 =  re.compile(r"2021必看热片.*?<ul>(?P<child_page>.*?)</ul>",re.S)

resp1 = obj1.search(resp.text)#一次查询,生成迭代器;
#print()
str1  =resp1.group()
#print(str1,type(str1))
#2.进入到子页面,(触发新的url请求);

obj2 = re.compile(r"<a href='(?P<href>.*?)'",re.S)#拿到所有的href;

child_resp = obj2.finditer(str1)

for i in child_resp:
     print(i.group())

step4:

#Author:Jony c
#!/usr/bin/env  python
# -*- coding:utf-8 -*-
#1.定位到2020必看热片;
#2.从2020必看片中,提取到子页面的链接地址;
#3.请求子页面的链接地址,拿到我们想要的下载地址....

#1.拿到子页面信息;
import requests,re

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

resp = requests.get(url,verify = False)   #verify  =false  去掉安全认证
resp.encoding="gb2312"#按照gb2313解码,gbk向下兼容gb2312;
#print(resp.text)


obj1 =  re.compile(r"2021必看热片.*?<ul>(?P<child_page>.*?)</ul>",re.S)

resp1 = obj1.search(resp.text)#一次查询,生成迭代器;
#print()
str1  =resp1.group()
#print(str1,type(str1))
#2.进入到子页面,(触发新的url请求);

obj2 = re.compile(r"<a href='(?P<href>.*?)'",re.S)#拿到所有的href;

child_resp = obj2.finditer(str1)
child_list = []#准备你空列表;
for i in child_resp:
    #进入子页面;
     url2 = url+ i.group("href").strip("/")
     #print(i.group("href"))
     child_list.append(url2)#把子连接存放起来;


#3.获取子页面内容;

for j in child_list:
     child_resp2 = requests.get(j,verify = False)#取消安全热认证;
     child_resp2.encoding = "gb2312"
     #print(child_resp2.text)#输出一个

     obj3 = re.compile(r'◎片  名(?P<name>.*?)<br />.*?<ul>		<li><a href="(?P<BD国语双字>.*?)".*?</a></li>',re.S)
     child_name  =obj3.search(child_resp2.text)
     print(child_name.group("name"))
     print(url2+child_name.group("BD国语双字").strip("/"))
     #break#测试,循环一次;

conclude:
1.老师这个写的很简单…你可以自己完善一下…加上input或者自己搞个“面向对象”去实现;
2.只需要记住这两点:

verfiy = Flase取消安全验证
href存放子连接、超链接的地址

六、BS4前析-HTML语法规则:

1.标签语言:
(enen…你别看在网页上会有什么图片、链接、地址…但是,服务器给你的是源代码都是一些HTML超文本…而这些 “超文本”用的都是“标签语言”…下面老师让我大概了解了一下什么是“标签语言”)

标签语言:1.标签 2. 属性 3. 属性值

标签功能
< h1> </ h1>变粗、变大(一级标签)
< h2> </ h2>二级标签
p段落
font字体(被废弃了,但能用)
body主体
<标签 属性="值" 属性="值">
被标记的内容
</标签>

2.解析入门之搞菜价:

(url:北京生发地…用bs4这种标签语言,去爬取菜价…)
在这里插入图片描述在这里插入图片描述



#1.拿到页面源代码;
#2.使用bs4进行解析,拿到数据;


import requests
from bs4 import BeautifulSoup
import csv



f = open("caijia.csv",mode="w",encoding="utf-8")
obj  = csv.writer(f)


url = "http://www.xinfadi.com.cn/marketanalysis/0/list/1.shtml"
resp = requests.get(url)
#print(resp.text)#可以拿到...

#3.把页面HTML源代码,交给beautifulsoup进行处理,生成bs对象;
page = BeautifulSoup(resp.text,"html.parser")#指定HTML解析器
#4.从bs对象中查找数据;
#find(标签,属性);
#find_all;

#data1 = page.find("table",class_ = "hq_table")#class是python 的关键字 ,用class_代替;
data = page.find("table",attrs= {"class":"hq_table"})#和上面的等价操作,避免使用“class”
#print(data)

data1 = data.find_all("tr")[1:]#tr是行的意思,切片拿到一行一行的纯数据;
#print(data1)
for i in data1:
  data3 = i.find_all("td")#(每一行拿每个的单个数据)
  name = data3[0].text#拿到被标签标记的数据;
  low_price = data3[1].text#最低价
  average = data3[2].text#平均
  high_price = data3[3].text#最高价
  size= data3[4].text#规格
  danwei = data3[5].text#单位
  time = data3[6].text#日期

  obj.writerow([name,low_price,average,high_price,size,danwei,time])
print("finish!!!")
step操作
1.生成htmlresp.text
2.Beautifulsoup(resp.text , “html.parse”)使用html解释器;
3.bs4对象进行find(标签,属性)、find_all()
4.“tr”代表表格中的每一个“行”;
5.“text”被标签标记的“内容”

3.解析入门之抓图片:

url =“https://pic.netbian.com/”在这里插入图片描述
(html下面的“子页面”)
在这里插入图片描述
子页面下的img -> 找到scr(下载地址)

import requests,time
from bs4 import BeautifulSoup

url = "https://pic.netbian.com/"

resp  = requests.get(url)
resp.encoding = "gbk"
#print(resp.text)

obj = BeautifulSoup(resp.text,"html.parser")
child_page = obj.find("div", class_="slist")#进一步缩小范围
#print(child_page)

#抓住子连接;
alist = child_page.find_all("a")

#print(alist)
# for i in child_page:

for i in alist:
    child_href = url+i.get("href")#得到属性;

    #进去子页面
    child_resp =  requests.get(child_href)
    child_resp.encoding = "gbk"
    #从子页面里面拿到下载路径:
    down_path = BeautifulSoup(child_resp.text,"html.parser").find("div", class_="photo-pic")
    #找到img
    img = down_path.find("img")
    down_img = img.get("src")#下载地址;
    print(down_img)
    #下载图片
    hearder = {"user-agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36 Edg/90.0.818.51"}
    img_resp = requests.get(url + down_img,hearder)

    #img_resp.content  #这里拿到的是字节;
    img_name  = down_img.split("/")[-1]#拿到url中的最后一个内容;
    with open ("img/"+img_name,mode = "wb") as f:
        f.write(img_resp.content)#图片内容写入文件

    print("%s finish downing。。。"%(img_name))
    time.sleep(1)
print("all finishing、、、")
bs4属性
child_href = i.get(“href”)得到相应的属性
下载文件操作
requests.get(src)拿到resp
f.write(resp.content)写成字节文件

(将文件夹中的索引去掉;)

七、Xpath前析-HTML语法规则:

Xpath是xml里面搜索内容的一门语言;
html是xml的一个子集合;
子节点、父节点、根节点…

1.安装“lxml”模块,里面要用到etree方法;

(cmd 切到 python/scripts 路径下…)

pip install lxml

2.xpath的基本语法:

1.操作一:

#Author:Jony c
#!/usr/bin/env  python 
# -*- coding:utf-8 -*-


from lxml import etree
obj_1 = """
<book>
     <id>1</id>
     <name>野花遍地⾹</name>
     <price>1.23</price>
     <nick>臭⾖腐</nick>
     <author>
            <nick id="10086">周⼤强</nick>
            <nick id="10010">周芷若</nick>
            <nick class="joy">周杰伦</nick>
            <nick class="jolin">蔡依林</nick>
            <div>
                 <nick>惹了</nick>
                     <div>
                     <nick>惹了1111</nick>
                     </div>
            </div>
            <span>
                     <nick>惹了1111</nick>
            </span>

     </author>
     <partner>
            <nick id="ppc">胖胖陈</nick>
            <nick id="ppbc">胖胖不陈</nick>
     </partner>
</book>
"""
#寻找路径,etree.xml(对象).xpath

test  = etree.XML(obj_1).xpath("/book")#"/"表示层级关系,第一个/是根节点;
#test  = etree.XML(obj_1).xpath("/book/name")
test_1  = etree.XML(obj_1).xpath("/book/name/text()")#text()拿文本;
test_2  = etree.XML(obj_1).xpath("/book/author/nick/text()")#text()拿文本;
test_3  = etree.XML(obj_1).xpath("/book/author//nick/text()")#author里面的后代,全部找到;
test_4  = etree.XML(obj_1).xpath("/book/author/*/nick/text()")#*任意节点的通配符;
test_5  = etree.XML(obj_1).xpath("/book//nick/text()")#所有的nick里面的内容;
print(test)
print(test_1)
print(test_2)
print(test_3)
print(test_4)
print(test_5)
操作意义
etree.XML(file.xml).xpath(路径)在路径下搜索文件file.xml里的内容;
1.xpath(/book)第一个“/”代表的是,根节点;
2.xpath(/book//nick)"后代"操作,book下面的所有nick全部找出来;
3.xpath(/book/*/nick)“/*”通配符,代表所有的节点;
4.xpath(/book/test())test()是取内容的操作

2.操作二:

在这里插入图片描述
(先写一个“test.html”测试文件…)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <title>Title</title>
</head>
<body>
    <ul>
       <li><a href="http://www.baidu.com">百度</a></li>
       <li><a href="http://www.google.com">⾕歌</a></li>
       <li><a href="http://www.sogou.com">搜狗</a></li>
    </ul>
    <ol>
        <li><a href="feiji">⻜机</a></li>
        <li><a href="dapao">⼤炮</a></li>
        <li><a href="huoche">⽕⻋</a></li>
    </ol>
    <div class="job">李嘉诚</div>
    <div class="common">胡辣汤</div>
</body>
</html>

(下面是python操作文件…)

#Author:Jony c
#!/usr/bin/env  python 
# -*- coding:utf-8 -*-

from lxml import etree

#输出所有的;
obj = etree.parse("test.html").xpath("/html/body/ul/li/a/text()")
print(obj)
#我只想要第一个li里面a标签的东西;
obj_1 = etree.parse("test.html").xpath("/html/body/ul/li[1]/a/text()")
print(obj_1)
#符合某种属性的筛选;
obj_2 = etree.parse("test.html").xpath("/html/body/ol/li/a[@href = 'dapao']/text()")
print(obj_2)

#遍历查询;

ol_li_list = etree.parse("test.html").xpath("/html/body/ol/li")

for i in ol_li_list:
    #从每一个li中提取到文字信息;
    obj_3 = i.xpath("./a/text()")# "./"表示从当前的节点往下找;
    print(obj_3)
     #从每一个li中提取到属性信息;
    obj_4 = i.xpath("./a/@href")# "@href"从a标签里面拿到属性;
    print(obj_4)
操作意思
1.xpath("/html/body/ul/li[1]/a/text()")取第一个内容;
2.xpath("/html/body/ol/li/a[@href = ‘dapao’]/text()")取属性值符合的内容;
3.xpath("./")"./"是从当前的节点往下查询;
4.xpath("./a/text()")text()…取内容;
5.xpath("./a/@href")“@href”取属性值;

(下面是个“分屏”的小技巧,之前不知道;看老师操作了就截了下来…)
在这里插入图片描述
在这里插入图片描述
(下面的小技巧是老师重点提到的…)

1.下面是Elements操作:

(鼠标滚动会“一一对应”)
在这里插入图片描述
2.可以拷贝…xpath(/…/…)

在这里插入图片描述
conclude:
1.etree.XML().xpath();
2.xpath("//nick"),“后代"操作;
3.xpath(”/*/"),匹配符;
4.xpath(“test()”),匹配内容;
5.xpath(’’@href’’),匹配属性;

3.猪八戒网xpath实例操作:
在这里插入图片描述
(选入第一个窗口…进行"右键"检查…在Element上面可以看见div标签的"分层")
在这里插入图片描述
(1.这里可以copy"xpath路径")

#Author:Jony c
#!/usr/bin/env  python 
# -*- coding:utf-8 -*-

#拿取页面源代码;
#提取和解析数据;
import requests
from lxml import etree

url = "https://shanxi.zbj.com/search/f/?type=new&kw=工作"

resp = requests.get(url)
#print(resp.text)

resp_obj = resp.text#生成html文件对象;

#提取和解析数据;
#1.所有的divs:
divs= etree.HTML(resp_obj).xpath("/html/body/div[6]/div/div/div[2]/div[6]/div[1]/div")
#2.遍历每个div;
for i in divs:
    obj_1 =  i.xpath("./div/div/a[1]/div[2]/div[1]/span[1]/text()")[0].strip("¥")#找到每个div里面的价格;
    obj_2 =  "工作".join(i.xpath("./div/div/a[1]/div[2]/div[2]/p/text()"))#找到每个div里面的标题;
    obj_3 =  i.xpath("./div/div/a[2]/div[1]/p/text()")[0]#找到每个div里面的运营商;
    obj_4 =  i.xpath("./div/div/a[2]/div[1]/div/span/text()")[0]#找到每个div里面的地址;
    print(obj_1)
    print(obj_2)
    print(obj_3)
    print(obj_4)
    print("-------------")

(2.这里可以直接copy),然后稍微改动一下…

在这里插入图片描述

#这里粘贴的代码是不一样的,需要稍微改动....
//*[@id="utopia_widget_51"]/a[1]/div[2]/div[1]/span[1]

在这里插入图片描述
(上述的代码改为…以下),就是定位的id在往上数到 i 定位的地方;

./div/div/a[1]/div[2]/div[1]/span[1]
//*[@id="utopia_widget_51"]/a[1]/div[2]/div[1]/span[1]

(你会发现,这个和之前的那个"路径",一模一样…)

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值