前言

你好! 这是基于b站2021年路飞学成爬虫教程的python爬虫学习笔记,主要是方便作者复习和回顾课程内容。
已经发布了第一章和第二章,可以在主页中查看。

python爬虫笔记(第二章)

  • 前言
  • 01数据解析概述
  • 02正则表达式
    • 元字符
    • 量词
    • 贪婪匹配和惰性匹配
  • 03 re模块
    • 03_01 findall
    • 03_02 search
    • 03_03 match
    • 03_04 finditer
    • 03_05 compile
    • 03_06 提取正则表达式中的单独内容
  • 04 运用request和re的两个爬虫案例
    • 0401 爬取豆瓣top250排行榜
    • 0402爬取电影天堂2020必看榜
  • 05 BS4解析——html语法
    • HTML标签
    • HTML属性
  • 06 bs4解析
  • 07 bs4案例解析:爬取唯美壁纸
  • 08 xpath解析
    • xpath解析1
    • xpath解析2
  • 09 案例:xpath解析猪八戒网

01数据解析概述

  1. re解析
  2. bs4解析
  3. xpath解析

02正则表达式

正则的语法: 使⽤元字符进⾏排列组合⽤来匹配字符串 在线测试正则表达式https://tool.oschina.net/regex/

元字符

. 匹配除换⾏符以外的任意字符
\w 匹配字⺟或数字或下划线
\s 匹配任意的空⽩符
\d 匹配数字
\n 匹配⼀个换⾏符
\t 匹配⼀个制表符

^ 匹配字符串的开始
$ 匹配字符串的结尾

\W 匹配⾮字⺟或数字或下划线
\D 匹配⾮数字
\S 匹配⾮空⽩符
a|b 匹配字符a或字符b
() 匹配括号内的表达式,也表示⼀个组
[…] 匹配字符组中的字符
[^…] 匹配除了字符组中字符的所有字符

量词

*重复零次或更多次
+重复⼀次或更多次
? 重复零次或⼀次
{n} 重复n次
{n,} 重复n次或更多次
{n,m} 重复n到m次

贪婪匹配和惰性匹配

.* 贪婪匹配

.* ?惰性匹配 (让*尽可能少出现的结果

注意:.*? 表示尽可能少的匹配, .*表示尽可能多的匹配

03 re模块

03_01 findall

查找所有,返回list

import re
lst = re.findall(r"\d+", "我的电话号是:10086,我女朋友电话是10010")
print(lst)
#['10086', '10010']

03_02 search

search 会进⾏匹配. 但是如果匹配到了第⼀个结果. 就会返回这个结果. 如果匹配不上search返回的则是None

ret = re.search(r'\d', '5点之前. 你要给我5000万').group()
print(ret) # 5s = re.search(r"\d+", "我的电话号是:10086,我女朋友电话是10010")
print(s.group())# 10086

03_03 match

只能从字符串的开头进⾏匹配

#从头匹配
ss = re.match(r"\d+", "10086,我女朋友电话是10010")
print(ss.group())

03_04 finditer

finditer, 和findall差不多. 只不过这时返回的是迭代器(重点)

# finditer: 匹配字符串中所有的内容[返回的是迭代器], 从迭代器中拿到内容需要.group()
it = re.finditer(r"\d+", "我的电话号是:10086, 我女朋友的电话是:10010")
for i in it:print(i.group())
#10086
#10010

03_05 compile

compile() 可以将⼀个⻓⻓的正则进⾏预加载. ⽅便后⾯的使⽤

#预加载正则表达式
obj = re.compile(r"\d+")ret = obj.finditer("我的电话号是:10086,我女朋友电话是10010")
for it in ret:print(it.group())

03_06 提取正则表达式中的单独内容

单独获取到正则中的具体内容可以给分组起名字.
(?P<分组名字>正则) 可以单独从正则匹配的内容中进一步提取内容

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>
"""# (?P<分组名字>正则) 可以单独从正则匹配的内容中进一步提取内容
obj = re.compile(r"<div class='.*?'><span id='(?P<id>\d+)'>(?P<name>.*?)</span></div>", re.S)
# re.S: 让.能匹配换行符
result = obj.finditer(s)
for it in result:print(it.group("name"))print(it.group("id"))

04 运用request和re的两个爬虫案例

0401 爬取豆瓣top250排行榜

需求:在https://movie.douban.com/top250上抓取"电影名称",“上映年份”,“评分”,"评分⼈数"四项内容。

# 拿到页面源代码.   requests
# 通过re来提取想要的有效信息  re
import requests
import re
import csvurl = "https://movie.douban.com/top250"
headers = {"user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.192 Safari/537.36"
}
resp = requests.get(url, headers=headers)
page_content = resp.text# 解析数据
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)
# 开始匹配
result = obj.finditer(page_content)
f = open("data.csv", mode="w")
csvwriter = csv.writer(f)
for it in result:# print(it.group("name"))# print(it.group("score"))# print(it.group("num"))# print(it.group("year").strip())dic = it.groupdict()dic['year'] = dic['year'].strip()csvwriter.writerow(dic.values())f.close()
print("over!")

0402爬取电影天堂2020必看榜

需求:在 "https://www.dytt89.com/"上,

  1. 定位到2020必看片
  2. 从2020必看片中提取到子页面的链接地址
  3. 请求子页面的链接地址. 拿到我们想要的下载地址…

预备知识
HTML中a标签表示超链接
实例:指向 w3school 的超链接:

<a href="http://www.w3school.com.cn">W3School</a>

1.定位到2020必看片

import requests
import redomain = "https://www.dytt89.com/"
resp = requests.get(domain, verify=False)#去掉安全验证#'str' object is not callable。因为默认字节转换成utf-8,而网站编码可能不是utf-8
#查看网页源代码,发现charset=gb2312
resp.encoding = 'gb2312'
#print(resp.text)
# 拿到ul里面的li
obj1 = re.compile(r"2020必看热片.*?<ul>(?P<ul>.*?)</ul>", re.S)result1 = obj1.finditer(resp.text)
for it in result1:ul = it.group('ul')
#    print(ul)

2.从2020必看片中提取到子页面的链接地址

# 1. 定位到2020必看片
# 2. 从2020必看片中提取到子页面的链接地址
# 3. 请求子页面的链接地址. 拿到我们想要的下载地址....
import requests
import redomain = "https://www.dytt89.com/"
resp = requests.get(domain, verify=False)#去掉安全验证#'str' object is not callable。因为默认字节转换成utf-8,而网站编码可能不是utf-8
#查看网页源代码,发现charset=gb2312
resp.encoding = 'gb2312'
#print(resp.text)
# 拿到ul里面的li
obj1 = re.compile(r"2020必看热片.*?<ul>(?P<ul>.*?)</ul>", re.S)
obj2 = re.compile(r"<a href='(?P<href>.*?)'", re.S)result1 = obj1.finditer(resp.text)
for it in result1:ul = it.group('ul')
#    print(ul)result2 = obj2.finditer(ul)for itt in result2:print(itt.group('href'))

此时的结果是:

很明显不是完整的网址。所以需要子页面链接与domain链接拼接到一起。将代码改如下:(子页面链接与domain链接拼接到一起,并把子页面链接保存在列表里)

result1 = obj1.finditer(resp.text)
child_href_list= []
for it in result1:ul = it.group('ul')
#    print(ul)result2 = obj2.finditer(ul)for itt in result2:
#        print(itt.group('href'))child_href = domain + itt.group('href').strip("/")# 拼接子页面的url地址:  域名 + 子页面地址child_href_list.append(child_href)  # 把子页面链接保存起来

最后请求子页面的链接地址. 拿到我们想要的下载地址。
全部代码如下:

# 1. 定位到2020必看片
# 2. 从2020必看片中提取到子页面的链接地址
# 3. 请求子页面的链接地址. 拿到我们想要的下载地址....
import requests
import redomain = "https://www.dytt89.com/"
resp = requests.get(domain, verify=False)#去掉安全验证#'str' object is not callable。因为默认字节转换成utf-8,而网站编码可能不是utf-8
#查看网页源代码,发现charset=gb2312
resp.encoding = 'gb2312'
#print(resp.text)
# 拿到ul里面的li
obj1 = re.compile(r"2020必看热片.*?<ul>(?P<ul>.*?)</ul>", re.S)
obj2 = re.compile(r"<a href='(?P<href>.*?)'", re.S)
obj3 = re.compile(r'◎片  名(?P<movie>.*?)<br />.*?<td'r' style="WORD-WRAP: break-word" bgcolor="#fdfddf"><a href="(?P<download>.*?)">', re.S)
result1 = obj1.finditer(resp.text)
child_href_list= []
for it in result1:ul = it.group('ul')
#    print(ul)result2 = obj2.finditer(ul)for itt in result2:
#        print(itt.group('href'))child_href = domain + itt.group('href').strip("/")# 拼接子页面的url地址:  域名 + 子页面地址child_href_list.append(child_href)  # 把子页面链接保存起来
#提取子页面内容
for href in child_href_list:child_resp = requests.get(href, verify=False)child_resp.encoding = 'gb2312'
#   print(child_resp.text)result3 = obj3.search(child_resp.text)print(result3.group("movie"))print(result3.group("download"))#    break#测试用

05 BS4解析——html语法

HTML(Hyper Text Markup Language)超⽂本标记语⾔, 是我们编写⽹⻚的最基本也是最核⼼的⼀种语⾔. 其语法规则就是⽤不同的标签对⽹⻚上的内容进⾏标记, 从⽽使⽹⻚显示出不同的展示效果.

HTML标签

h1: ⼀级标题
h2: ⼆级标题
p: 段落
font: 字体(被废弃了, 但能⽤)
body: 主体

HTML属性

<标签 属性="值" 属性="值">被标记的内容
</标签><body text="green" bgcolor="#eee">你看我的颜⾊. 贼健康
</body>

06 bs4解析

1.bs4模块安装
参考教程

2 尝试爬取http://www.xinfadi.com.cn/marketanalysis/0/list/1.shtml

预备知识:
HTML中每一行是一个tr,每一列叫一个td。

# 1. 拿到页面源代码
# 2. 使用bs4进行解析. 拿到数据
import requests
from bs4 import BeautifulSoup
import csvurl = "http://www.xinfadi.com.cn/marketanalysis/0/list/1.shtml"
resp = requests.get(url)
#print(resp.text)f = open("菜价.csv", "w")
csvwriter = csv.writer(f)#解析数据
# 1. 把页面源代码交给BeautifulSoup进行处理, 生成bs对象
page = BeautifulSoup(resp.text, "html.parser")# 若不指定html解析器,会出现warning
# 2. 从bs对象中查找数据
# find:找一个(标签, 属性=值)
# find_all:找全部(标签, 属性=值)
#table = page.find("table", class_="hq_table")
table = page.find("table", attrs={"class":"hq_table"})
# 和上一行是一个意思. 此时可以避免class。因为class是python的关键字。
#print(table)
trs = table.find_all("tr")[1:]
#每一行是一个tr,每一列叫一个td
for tr in trs: # 每一行tds = tr.find_all("td") # 拿到每行中的所有tdname = tds[0].text  # .text 表示拿到被标签标记的内容low = tds[1].text  # .text 表示拿到被标签标记的内容avg = tds[2].text  # .text 表示拿到被标签标记的内容high = tds[3].text  # .text 表示拿到被标签标记的内容gui = tds[4].text  # .text 表示拿到被标签标记的内容kind = tds[5].text  # .text 表示拿到被标签标记的内容date = tds[6].text  # .text 表示拿到被标签标记的内容
#    print(name, low, avg, high, gui, kind, date)csvwriter.writerow([name, low, avg, high, gui, kind, date])f.close()
resp.close() #爬完要关掉resp
print("over!")

07 bs4案例解析:爬取唯美壁纸

对于https://www.umei.cc/bizhitupian/weimeibizhi/。需求如下:
1.拿到主页面的源代码. 然后提取到子页面的链接地址, href
2.通过href拿到子页面的内容. 从子页面中找到图片的下载地址 img -> src
3.下载图片

# 1.拿到主页面的源代码. 然后提取到子页面的链接地址, href
# 2.通过href拿到子页面的内容. 从子页面中找到图片的下载地址 img -> src
# 3.下载图片
import requests
from bs4 import BeautifulSoup
import timeurl = "https://www.umei.cc/bizhitupian/weimeibizhi/"
resp = requests.get(url)
resp.encoding = 'utf-8' # 处理乱码 charset=utf-8
#print(resp.text)
# 把源代码交给bs
main_page = BeautifulSoup(resp.text, "html.parser")
alist = main_page.find("div", class_="TypeList").find_all("a")
#print(alist)
for a in alist:# 拿到子页面的源代码href = a.get('href')child_page_resp = requests.get(href)child_page_resp.encoding = 'utf-8'child_page_text = child_page_resp.text# 从子页面中拿到图片的下载路径child_page = BeautifulSoup(child_page_text, "html.parser")p = child_page.find("p", align="center") #一般通过class或id定位,但是这个网页源代码align="center是唯一的img = p.find("img")src = img.get("src")#下载图片img_resp = requests.get(src)img_resp.content #拿到的是字节,但是写进文件里就成了图片img_name = src.split("/")[-1]# 拿到url中的最后一个/以后的内容with open("img/"+img_name, "wb") as f:f.write(img_resp.content)print("over!!!", img_name)time.sleep(1)f.close()
resp.close() #爬完要关掉resp
print("all over!!!")

08 xpath解析

XPath是⼀⻔在 XML ⽂档中查找信息的语⾔. XPath可⽤来在 XML⽂档中对元素和属性进⾏遍历. ⽽我们熟知的HTML恰巧属于XML的⼀个⼦集. 所以完全可以⽤xpath去查找html中的内容.

  1. book, id, name, price…都被称为节点.
  2. Id, name, price, author被称为book的⼦节点
  3. book被称为id, name, price, author的⽗节点
  4. id, name, price,author被称为同胞节点

⽤法:

  1. 将要解析的html内容构造出etree对象.
  2. 使⽤etree对象的xpath()⽅法配合xpath表达式来完成对数据的提取

xpath解析1

# xpath 是在XML文档中搜索内容的一门语言
# html是xml的一个子集# xpath解析
from lxml import etreexml = """
<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>热热热热热1</nick></div><span><nick>热热热热热2</nick></span></author><partner><nick id="ppc">胖胖陈</nick><nick id="ppbc">胖胖不陈</nick></partner>
</book>
"""tree = etree.XML(xml)
# /表示层级关系. 第一个/是根节点
#result = tree.xpath("/book")
#result = tree.xpath("/book/name")
#result = tree.xpath("/book/name/text()")# text() 拿文本
#result = tree.xpath("/book/author/nick/text()")
#result = tree.xpath("/book/author//nick/text()")  # // 后代
#result = tree.xpath("/book/author/*/nick/text()")  # * 任意的节点. 通配符
result = tree.xpath("/book//nick/text()")
print(result)

xpath解析2

预备知识:在网页中右键-检查:

先准备一个网页b.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>

用xpath解析:

from lxml import etreetree = etree.parse("b.html")
#result = tree.xpath('/html')
#result = tree.xpath('/html/body/ul/li/a/text()')
#result = tree.xpath('/html/body/ul/li[1]/a/text()')# xpath的顺序是从1开始数的, []表示索引
#result = tree.xpath('/html/body/ol/li//a[@href="dapao"]/text()')
# [@xxx=xxx] 属性的筛选#print(result)# ol_li_list = tree.xpath("/html/body/ol/li")
# for li in ol_li_list:
#     result = li.xpath("./a/text()")# ./表示在li中继续去寻找. 相对查找
#     print(result)
#     result2 = li.xpath("./a//@href")# 拿到属性值: //@属性
#     print(result2)print(tree.xpath("/html/body/ul/li/a//@href"))
print(tree.xpath("/html/body/div[1]/text()"))
print(tree.xpath("/html/body/ol/li/a/text()"))

09 案例:xpath解析猪八戒网

需求:对于https://beijing.zbj.com/search/f/?type=new&kw=saas,拿到页面源代码,提取和解析数据

# 拿到页面源代码
# 提取和解析数据
import requests
from lxml import etreeurl = "https://beijing.zbj.com/search/f/?type=new&kw=saas"
resp = requests.get(url)
#print(resp.text)# 解析
html = etree.HTML(resp.text)
# 拿到每一个服务商的div
divs = html.xpath("/html/body/div[6]/div/div/div[2]/div[4]/div[1]/div")
for div in divs:price = div.xpath("./div/div/a[1]/div[2]/div[1]/span[1]/text()")[0].strip("¥")title = "SaaS".join(div.xpath("./div/div/a[1]/div[2]/div[2]/p/text()"))com_name = div.xpath("./div/div/a[2]/div[1]/p/text()")[0]location = div.xpath("./div/div/a[2]/div[1]/div/span/text()")[0]print(price)print(title)print(com_name)print(location)

python爬虫笔记第二章相关推荐

  1. Python爬虫学习第二章-1-requests模块简介

    Python爬虫学习第二章-1-requests模块简介   这一章主要是介绍requests模块的相关知识以及使用 1.requests模块简介: 概述:是python中原生的一款基于网络请求的模块 ...

  2. Python学习笔记—第二章—IPython

    书目:Python(Unix和Linux系统管理指南) 学习日期:20130807 知识点总结: 安装IPython: 源码安装: 1 2 tar zxvf ipython-0.13.2.tar.gz ...

  3. 《计算传播学导论》读书笔记——第二章文本分析简介

    <计算传播学导论>读书笔记--第二章文本分析简介 第一节 文本分析研究现状 常用文本挖掘技术 第二节 文本分析与传播学研究 (一)为什么文本挖掘技术逐渐受到传播学者的关注 (二)不同文本分 ...

  4. Python爬虫笔记(3)- 爬取丁香园留言

    Python爬虫笔记(3)- 爬取丁香园留言 爬取丁香园留言:主要用到了模拟登录 爬取丁香园留言:主要用到了模拟登录 import requests, json, re, random,time fr ...

  5. 小吴的《机器学习 周志华》学习笔记 第二章 模型评估与选择

    小吴的<机器学习 周志华>学习笔记 第二章 模型评估与选择 上一周我们介绍了第一章的基础概念,这一次将带来第二章的前三节.后面的2.4 比较检验与2.5 偏差与方差,涉及概率论与数理统计概 ...

  6. 深入理解 C 指针阅读笔记 -- 第二章

    Chapter2.h #ifndef __CHAPTER_2_ #define __CHAPTER_2_/*<深入理解C指针>学习笔记 -- 第二章*//*内存泄露的两种形式1.忘记回收内 ...

  7. 《Go语言圣经》学习笔记 第二章 程序结构

    Go语言圣经学习笔记 第二章 程序结构 目录 命名 声明 变量 赋值 类型 包和文件 作用域 注:学习<Go语言圣经>笔记,PDF点击下载,建议看书. Go语言小白学习笔记,几乎是书上的内 ...

  8. Web前端开发笔记——第二章 HTML语言 第四节 超链接标签

    目录 前言 一.超链接标签 (一)链接其它子网页 (二)链接其它站点 (三)虚拟超链接 二.从当前页面链接到指定位置 三.链接的访问情况 四.在新窗口中打开链接 例题 结语 前言 本节介绍超链接标签即 ...

  9. Python精确指南——第二章 界面开发

    2 Python GUI 借助Python语言的优势,使用Python的界面库开发界面程序,开发周期更短.但因为Python的界面开发库底层实现一般不是Python,只是为Python封装的接口,所以 ...

最新文章

  1. python 装饰器 生成器 迭代器和闭包
  2. Omnispace 收藏夹
  3. sencha touch 手势识别左右滑动
  4. 打印心形c语言,C语言打印心形
  5. MYSQL类型与JAVA类型对应表
  6. JavaScript学习(六十四)—关于JS的浮点数计算精度问题解决方案
  7. 自己编写的新闻显示控件(列表显示不过不够完善还需努力)
  8. idea license 20200104
  9. CIC Dips Its Toe Back In US Waters
  10. 软件是怎么开发出来的?怎么进行软件开发流程详解
  11. Office-PPT如何使多张图片自动等距排列
  12. 【转】U-Boot启动过程--详细版的完全分析
  13. java正则表达式 字母数字下划线_字母数字下划线常用正则表达式
  14. python -- 基础知识
  15. Using a coordinate with ws.cell is deprecated问题的解决
  16. efibootmgr修改Linux系统默认启动项
  17. implement和extend的区别 在java中
  18. 警惕! ”黑帽子“的社会工程学攻击
  19. 英雄互娱任命吴旦为总裁 同时宣布成立英雄体育
  20. pip 安装tensorflow.whl包出错 PermissionError: [Errno 13] Permission denied:

热门文章

  1. position:sticky;粘性布局
  2. vlookup匹配 匹配结果错误_vlookup函数的12种常见错误、原因及解决方法
  3. 性能分析——dmesg
  4. 各类云服务器网站云计算平台大全
  5. 程序员用哪种输入法好呢
  6. 投资股票《三友化工》的复盘
  7. 计算机主板巨头,2020电脑主板排行_板卡巨头纷纷退出:2020台北电脑展悬了
  8. Excel如何批量插入图片并导入图片名称?
  9. Android AIDL(接口定义语言)简单理解和基本使用方法
  10. postgres字符串转数字