各位小伙伴想要博客相关资料的话关注公众号:chuanyeTry即可领取相关资料!
解析网页的三种解析方式:
正则表达式, 一种使用表达式的方式对字符串进行匹配的语法规则.
正则的优点: 速度快, 效率高, 准确性高
正则的缺点: 新手上手难度有点儿高.
正则的语法: 使用元字符进行排列组合用来匹配字符串
在线测试正则表达式https://tool.oschina.net/regex/
链接: 在线测试正则表达式
元字符: 具有固定含义的特殊符号。
量词: 控制前⾯的元字符出现的次数
贪婪匹配和惰性匹配
lst = re.findall("m", "mai le fo len, mai nimei!")
print(lst) # ['m', 'm', 'm']
lst = re.findall(r"\d+", "5点之前. 你要给我 5000万")
print(lst) # ['5', '5000']
ret = re.search(r'\d', '5点之前. 你要给我 5000万').group()
print(ret) # 5
ret = re.match('a', 'abc').group()
print(ret) # a
it = re.finditer("m", "mai le fo len, mai ni mei!")
for el in it:
print(el.group()) # 依然需要分组
obj = re.compile(r'\d{3}') # 将正则表达式编译成为一个正则表达式对象, 规则要匹配的是3个数字
ret = obj.search('abc123eeee') # 正则表达式对象调用search, 参数为待匹配的字符串
print(ret.group()) # 结果: 123
s = """
中国联通
"""
obj = re.compile(r"(?P\w+) ",re.S)
result = obj.search(s)
print(result.group()) # 结果: 中国联通
print(result.group("id")) # 结果: 10010 # 获取id组的内容
print(result.group("name")) # 结果: 中国联通 #获取name组的内容
这里可以看到我们可以通过使用分组. 来对正则匹配到的内容进
一步的进行筛选.
目标: 抓取"电影名称",“上映年份”,“评分”,"评分人数"四项内容.怎么做呢?
首先, 先看一下页面源代码. 数据是否是在源代码上的?很明显, 我们想要的数据全部都在页面源代码中体现了. 接下来第一步了. 拿到⻚面源代码,然后呢. 从⻚面源代码中提取我们需要的内容. 这时候我们就可以去写正则了.
import requests
headers = {
"user-agent": "Mozilla/5.0 (Macintosh; IntelMac OS X 10_15_4)AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36"
}
url = "https://movie.douban.com/top250?start=0&filter="
resp = requests.get(url, headers=headers)
print(resp.text)
obj = re.compile(r'<li>.*?<div class="item">.*?
<div class="pic">.*?<em class="">(?P<num>\d+)
</em>'
r'.*?<span class="title">(?
P<name>.*?)</span>'
r'.*?<p class="">.*?<br>\n(?
P<year>.*?) '
r'.*?property="v:average">(?
P<average>.*?)</span>'
r'.*?<span>(?P<people>\d+)⼈评价
</span>', re.S)
开始匹配, 将最终完整的数据按照自己喜欢(需要)的方式写入文件.
it = obj.finditer(resp.text)
with open("movie.csv", mode="w", encoding="utf-8") as f:
csvwriter = csv.writer(f) # 创建csv文件写入工具,也可以直f.write()
for item in it:
dic = item.groupdict()
dic['year'] = dic['year'].strip()
csvwriter.writerow(dic.values()) # 写入数据
bs4解析比较简单, 但是呢, 首先你需要了解一丢丢的html知识. 然后再去使用bs4去提取, 因为bs4就是通过html标签和属性去定位⻚面上的内容的。
<body text="green" bgcolor="#eee">
你看我的颜色. 贼健康
body>
<标签 属性=“值” 属性=“值”>
被标记的内容
标签>
在python中我一般只推荐用pip进行安装. 原因: 简单!!!
pip install bs4
bs4在使用的时候就需要参照一些html的基本语法来进行使用了. 我们直接上案例. 案例是最能直观的展现出bs4的便捷效果的.
我们来尝试抓取链接: link
http://www.xinfadi.com.cn/marketanalysis/0/list/1.shtml
老规矩, 先获取⻚面源代码. 并且确定数据就在⻚面源代码中~
import requests
from bs4 import BeautifulSoup
resp =
requests.get("http://www.xinfadi.com.cn/market
analysis/0/list/1.shtml")
print(resp.text)
将⻚面源代码丢给BeautifulSoup, 然后我们就可以通过bs对象去检索⻚面源代码中的html标签了
page = BeautifulSoup(resp.text)
BeautifulSoup对象获取html中的内容主要通过两个方法来完成
find()
find_all()
基本上有这两个方法就够用了. 不论是find还是find_all 参数几乎是一致的.
语法:
意思是在页面中查找 xxx标签, 并且标签的xxx属性必须是xxx值
例:find(‘div’, age=18) 含义: 在⻚面中查找div标签, 并且属性age必须是 18的这个标签.
find_all()的用法和find()几乎一致.
find()查找 1 个. ,find_all()查找⻚面中所有的.
page.find("div", class="honor")
注意, python中class是关键字. 会报错的. 怎么办呢? 可以在class后面加个下划线
page.find("div", class_="honor")
好了, 用法说完了. 接下来就回来看怎么抓取新发地的价格吧
table = page.find("table", class_="hq_table")
print(table)
接下来就可以进一步去提取数据了. 后面的直接给出完整代码.因为逻辑都是一样的. 并没有多么的复杂, 过程就省略了.
import requests
from bs4 import BeautifulSoup
import csv
resp =
requests.get("http://www.xinfadi.com.cn/marke
tanalysis/0/list/1.shtml")
page = BeautifulSoup(resp.text)
table = page.find("table", class_="hq_table")
f = open("新发地.csv", mode="w",
encoding="utf-8")
cv_writer = csv.writer(f)
# 提取到所有tr
tr_list = table.find_all("tr")[ 1 :] # 注意,第一
行并不是我想要的数据. (第一行是表头)
for tr in tr_list:
td_list = tr.find_all("td")
name = td_list[ 0 ].text # 获取文本内容
low = td_list[ 1 ].text
avg = td_list[ 2 ].text
high = td_list[ 3 ].text
gui = td_list[ 4 ].text
dan = td_list[ 5 ].text
day = td_list[ 6 ].text
cv_writer.writerow([name, low, avg, high,
gui, dan, day])
f.close()
print("搞定")
有人可能要问了. 为什么只有第一⻚数据. 你观察一下第二⻚, 第
三⻚的url就明白了了
http://www.xinfadi.com.cn/marketanalysis/ 0 /list/1.shtml
http://www.xinfadi.com.cn/marketanalysis/ 0 /list/2.shtml
http://www.xinfadi.com.cn/marketanalysis/ 0 /list/3.shtml
7.抓取图片
我们以优美图库作为本节课的案例。
链接:优美图库https://www.umei.cc/bizhitupian/weimeibizhi/
我需要在网站的首⻚中, 找到子⻚面的链接, 然后请求到子⻚面, 才能看到图片>也就是说, 想要下载该网站图片(高清大图), 需要三步,
第一步, 在主⻚面中拿到每一个图片的子⻚面链接
第二步, 在子⻚面中找到真正的图片下载地址
第三步, 下载图片
1.拿到子⻚面链接
def main_page():
with open("child_page_href.txt", mode="w") as
f:
for i in range( 1 , 56 ):
try:
resp =requests.get(f"https://www.umei.cc/bizhitupian/weimeibizhi/{i}.htm")
#
resp.encoding = 'utf-8' # 处理中文乱码, 这里要和⻚面上的charset对应
main_page =BeautifulSoup(resp.text, "html.parser")
typeListDiv =main_page.find("div", attrs={"class":"TypeList"})
main_a_list =typeListDiv.find_all("a")
for main_a in main_a_list:
href = main_a.get("href") #拿到某一个标签中xxx属性的值
f.write(href)
f.write("\n")
print(f"https://www.umei.cc/bizhitupian/weimeibizhi/{i}.htm, 成功了!")
time.sleep(0.5)
except:
print(f"https://www.umei.cc/bizhitupian/weimeibizhi/{i}.htm, 出错了")
print(resp.text)
break # 也可以记录下来, 供以后查错用
2.获取到子页面信息, 找到下载图片的图片路径
def child_page():
with open("child_page_href.txt", mode="r") as
f:
for line in f:
line = line.strip()
resp = requests.get(line)
resp.encoding='utf-8'
child = BeautifulSoup(resp.text,"html.parser")
div = child.find("div",class_="ImageBody")
img = div.find("img")
if img:
src = img.get("src")
print(src)
else:
print(line, "没有图片")
- 下载图片
def download_img(src):
with open("img/"+src.split("/")[- 1 ],mode="wb") as f:
resp = requests.get(src) # 下载图片
f.write(resp.content) # 图片写入文件
print(src, "down!")
最后运行一下, 看看结果对了一定记着把img文件夹设置为excluded, 否则你的pycharm会奇卡无比