欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Python 爬虫实战 1

程序员文章站 2022-07-14 10:49:54
...

源:参加阿里云的Python 爬虫实战课
本文代码相关资源见本人CSDN主页 ”正则表达式基础.zip“。资源包括:
Python 爬虫实战 1

本文是课程 “Python网络爬虫快速入门到精通“ 的听课笔记 + 自己跟随的操作实战。
Python 爬虫实战 1
Python 爬虫实战 1
Python 爬虫实战 1

正则表达式

概念

基础1

  • 全局匹配函数使用格式
re.compile(正则表达式).findall(源字符串)

普通字符   正常匹配
  \n     匹配换行符
  \t     匹配制表符
  \w     匹配字母、数字、下划线
  \W     匹配除字母、数字下划线
  \d     匹配十进制数字
  \D     匹配除十进制数字
  \s     匹配空白字符
  \S     匹配除空白字符
  [ab89x]     原子表,匹配ab89x 中的任意一个
  [^ab89x]     原子表,匹配除ab89x 中的任意一个字符

例子见同名 .py文件

基础2

.     匹配除换行外任意一个字符
^     匹配开始位置[在原子表代表非,不在代表匹配开始位置]
$     匹配结束位置
*    前一个字符出现0\1\多次
?     前一个字符出现0\1次
+    前一个字符出现1\多次
{n}     前一个字符恰好出现n次
{n,}     前一个字符至少n次。
{n,m}     前一个字符至少n,至多m次
|      模式选择符或
()     模式单元,通俗说就是,想提取出什么内容,就在正则中用小括号将其括起来。

基础3

贪婪模式:尽可能多地匹配
懒惰模式:尽可能少地匹配,精准模式
默认贪婪模式
如果出现如下组合,则代表为懒惰模式
*?
+?

基础4

模式修正符:在不改变正则表达式的情况下通过模式修正符使匹配结果发生更改
re.S     让.也可以匹配多行
re.I     让匹配时忽略大小写

Python 代码测试

对应上面四个基础的测试代码如下:

import re

print("-"*50, "基础1", "-"*50)
src = "aliyunedu"
pat = re.compile("yu").findall(src)
print(pat)

src ="'aliyunedu'"
pat = re.compile("yun\n").findall(src)
print(pat)

src ='"aliyun\nedu"'
pat = re.compile("yun\n").findall(src)
print(pat)

src ="aliyun89787nedu"
pat = re.compile("\w\d\w\d\d\w").findall(src)
print(pat)
# 原子表
pat = re.compile("\w\d[nedu]\w").findall(src)
print(pat)
"""
-------------------------------------------------- 基础1 --------------------------------------------------
['yu']
[]
['yun\n']
['n89787']
['87ne']
"""

# 基础2
print("-"*50, "基础2", "-"*50)
src ="aliyunnnnji87362387aoyubaidu"
pat = re.compile("ali...").findall(src)
print(pat)
pat = re.compile("^ali...").findall(src)
print(pat)
pat = re.compile("bai..$").findall(src)    # 注意,结束位置$ 是 \n
print(pat)
pat = re.compile("ali.*").findall(src)      # TIPS:默认贪婪,即默认尽可能多地进行匹配
print(pat)
pat = re.compile("aliyun+").findall(src)    # 多次n全部匹配出来
print(pat)
pat = re.compile("aliyun?").findall(src)    # 匹配1次最多
print(pat)
pat = re.compile("yun{1,2}").findall(src)    # 不超过2次,最少一次。
print(pat)
pat = re.compile("^al(i..)").findall(src)  #  相匹配括号里面的
print(pat)

# 基础3
print("-"*50, "基础3", "-"*50)
src ="poythonyhjskjsa"
pat = re.compile("p.*y").findall(src)       # 尽可能多地匹配
print(pat)
pat = re.compile("p.*?y").findall(src)      # 尽可能少地匹配
print(pat)
pat = re.compile("p.+?y").findall(src)      # 尽可能少地匹配
print(pat)
src ="poythponyhjskjsa"
pat = re.compile("p.*y").findall(src)       # 尽可能多地匹配
print(pat)
pat = re.compile("p.*?y").findall(src)      # 尽可能少地匹配
print(pat)
pat = re.compile("p.+?y").findall(src)      # 尽可能少地匹配
print(pat)

# 基础4
print("-"*50, "基础4", "-"*50)
src ="Python"
pat = re.compile("pyt").findall(src)       # 匹配不到,因为有大写
print(pat)
pat = re.compile("pyt", re.I).findall(src)       # 可以匹配大小写
print(pat)

src ="我是阿里云大学\n欢迎来学习Python网络爬虫课程"
pat = re.compile("阿里.*?Python").findall(src)       # 匹配不到,因为有换行
print(pat)
pat = re.compile("阿里.*?Python", re.S).findall(src)       # 可以匹配换行
print(pat)

XPath表达式

概念

/               逐层提取
text()              提取标签下面的文本
//标签名**           提取所有名为**的标签
//标签名[@属性=‘属性值’]    提取属性为XX的标签
@属性名            代表取某个属性值

<!DOCTYPE html>
<html>
    <head>
        <title>主页</title>
    </head>
    <body>
        <p>abc</p>
        <p>bbbvb</p>
        <a href="//qd.alibaba.com/go/v/pcdetail" target="_top">安全推荐</a>
        <a href="//qd.alibaba.com/go/v/pcdetail" target="_top">安全推荐2</a>
        <div class="J_AsyncDC" data-type="dr">
            <div id="official-remind">明月几时有</div>
        </div>
    </body>
</html>

分析以下XPath 表达式提取的内容:
提取标题=主页
/html/head/title/text()
提取所有的div标签
//div
提取div中

标签的内容
//div[@class=“tools”]
提取p标签下的所有文本=[abc, bbbvb]
//p/text()
提取所有的a标签
//a
提取所有的div标签,且标签属性的id有定位=明月几时有
//div[@id=“official-remind”]/text()
提取所有a标签下的href属性值=上面代码的两个网址
//a/@href

Python 代码测试

from lxml import etree

print("-"*50, "测试: 打印 html 应该显示内容", "-"*50)
html = etree.parse('XPath_test.html')
html_data = html.xpath('//*')      # 打印是一个列表需要遍历
print(html_data)
print("-"*50)
for i in html_data:
    print(i.text)

print("-"*50, "测试: 打印 html 所有文本内容", "-"*50)
html = etree.parse('XPath_test.html')
html_data = etree.tostring(html, pretty_print=True)
res = html_data.decode('utf-8')
print(res)

print("-"*50, "测试: XPath表达式测试=标题提取", "-"*50)
html = etree.parse('XPath_test.html')
html_data = html.xpath('/html/head/title/text()')
for i in html_data:
    print(i)

print("-"*50, "测试: XPath表达式测试=所有div标签内容提取", "-"*50)
html_data = html.xpath('//div')
for i in html_data:
    print(i)

print("-"*50, "测试: XPath表达式测试=所有div标签指定属性的内容提取", "-"*50)
html_data = html.xpath('//div[@id="official-remind"]/text()')
for i in html_data:
    print(i)

print("-"*50, "测试: XPath表达式测试=所有p标签内容提取", "-"*50)
html_data = html.xpath('//p/text() ')
for i in html_data:
    print(i)

print("-"*50, "测试: XPath表达式测试=所有a标签内容提取", "-"*50)
html_data = html.xpath('//a')
for i in html_data:
    print(i)

print("-"*50, "测试: XPath表达式测试=所有a标签href属性的内容提取", "-"*50)
html_data = html.xpath('//a/@href')
for i in html_data:
    print(i)

后注

来找自己浏览器的Headers属性。
–(1)打开任意网页,按F12,并选择网络(network)
–(2)任意点击网页连接,使其发生动作。点击,触发一个动作,User-Agent字样的一串信息即是。