Python爬虫入门

什么是爬虫

爬虫就是程序,一个能获取互联网上的资源(文字、图片、音视频)数据的程序。

不用爬⾍, 打开浏览器, 输⼊百度的⽹址,就能在浏览器上看到百度的内容了。那换成爬⾍呢? 道理是⼀样的。只不过,是⽤代码来模拟⼀个浏览器, 然后同样的输⼊百度的⽹址。那么程序也能拿到百度的内容

爬虫合法吗

爬虫在法律上暂时是不被禁止的。但服务器上的数据有产权归属,如果网络爬虫获取数据后牟利将带来法律风险。小规模,数据量小,频率不高, 不窃取用户隐私的爬取是可以的,合法的

反爬与反反爬

反爬机制 :网站可以通过制定相应的策略或者技术手段,防止爬虫程序进行网站数据的爬取
反反爬策略 :爬虫程序可以通过制定相关的策略或者技术手段,破解网站中具备的反爬机制,从而可以获取网站中相关的数据。
robots.txt协议:君子协议。规定了网站中哪些数据可以被爬虫爬取哪些数据不可以被爬取

requests请求库

  • 安装
powershell 复制代码
pip install requests
  • 请求百度首页源代码
python 复制代码
import requests

# 这样运行的话就把百度首页的html提取出来了
url = "https://www.baidu.com/"
response = requests.get(url)
response.encoding = "utf-8"
print(response.text)

XPath解析库

  • ⼤多数情况下, 我们并不需要整个⽹⻚的内容, 只是需要那么⼀⼩部分。所以我们要做数据解析和提取。常见的有:xpath解析、BeautifulSoup解析、正则表达式re解析
  • XPath是⼀⻔在 XML ⽂档中查找信息的语⾔, XPath可⽤来在 XML⽂档中对元素和属性进⾏遍历,⽽我们熟知的HTML恰巧属于XML的⼀个⼦集,所以完全可以⽤xpath去查找html中的内容
  • 在python中想要使⽤xpath,需要安装lxml模块:pip install lxml
  • 基础用法:①将要解析的html内容构造出etree对象②使⽤etree对象的xpath()⽅法配合xpath表达式来完成对数据的提取
python 复制代码
html = """
<!DOCTYPE html>
<html>
    <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>李嘉诚</div>
        <div>胡辣汤</div>
    </body>
</html>
"""
from lxml import etree

tree = etree.XML(html)
result = tree.xpath("/html/body/ul/li/a/@href")
print(result)

result = tree.xpath("/html/body/ul/li")
for li in result:
    print(li.xpath("./a/@href"))

result = tree.xpath("/html/body/ol/li/a/@href")
print(result)

BeautifulSoup解析库

  • 安装库:pip intall bs4
python 复制代码
<html lang="en">
<head>
	<meta charset="UTF-8" />
	<title>测试bs4</title>
</head>
<body>
	<div>
		<p>百里守约</p>
	</div>
	<div class="song">
		<p>李清照</p>
		<p>王安石</p>
		<p>苏轼</p>
		<p>柳宗元</p>
		<a href="http://www.song.com/" title="赵匡胤" target="_self">
			<span>this is span</span>
		宋朝是最强大的王朝,不是军队的强大,而是经济很强大,国民都很有钱</a>
		<a href="" class="du">总为浮云能蔽日,长安不见使人愁</a>
		<img src="http://www.baidu.com/meinv.jpg" alt="" />
	</div>
	<div class="tang">
		<ul>
			<li><a href="百度一下,你就知道" title="qing">清明时节雨纷纷,路上行人欲断魂,借问酒家何处有,牧童遥指杏花村</a></li>
			<li><a href="网易" title="qin">秦时明月汉时关,万里长征人未还,但使龙城飞将在,不教胡马度阴山</a></li>
			<li><a href="126网易免费邮--你的专业电子邮" alt="qi">岐王宅里寻常见,崔九堂前几度闻,正是江南好风景,落花时节又逢君</a></li>
			<li><a href="home.sina.com" class="du">杜甫</a></li>
			<li><a href="Awesome Coming Soon Widget Responsive Widget" class="du">杜牧</a></li>
			<li><b>杜小月</b></li>
			<li><i>度蜜月</i></li>
			<li><a href="http://www.haha.com" id="feng">凤凰台上凤凰游,凤去台空江自流,吴宫花草埋幽径,晋代衣冠成古丘</a></li>
		</ul>
	</div>
</body>
</html>

from bs4 import BeautifulSoup

#本地的html
fp = open(r"test.html","r",encoding="utf-8")
soup = BeautifulSoup(fp,"lxml")
print(soup)  #返回这个网页的源代码
print(soup.a)  #返回第一个a标签的内容
print(soup.div) #返回第一个div 的内容
print(soup.find("div"))  #返回第一个div 的内容
print(soup.find("div",class_="song"))   #返回class = "song" 的div的内容
print(soup.find_all("a"))  #返回所有a标签的内容
print(soup.find("div",class_="song").a.get("href"))# 返回http://www.song.com/
print(soup.find("div",class_="song").img.get("src"))#返回http://www.baidu.com/meinv.jpg
print(soup.find("div",class_="song").a.text) # 返回文本
print(soup.select('.tang'))   返回class = "tang" 的div的内容
print(soup.select(".tang > ul > li > a")[0].text)   # 返回tang下的第一个标签的内容
print(soup.select(".tang > ul > li > a")[0]['href']) # 返回tang下的第一个标签的链接

正则表达式

  • 正则表达式是用来简洁表达一组字符串的表达式
python 复制代码
import re
# 将正则表达式编译成为⼀个正则表达式对象, 规则要匹配的是3个数字
obj = re.compile(r'\d{3}')
# 正则表达式对象调⽤search, 参数为待匹配的字符串
ret = obj.search('abc123eeee')
print(ret.group()) # 结果: 123

元字符:具有固定含义的特殊符号 常⽤元字符:

. 匹配除换⾏符以外的任意字符

\w 匹配字⺟或数字或下划线

\s 匹配任意的空⽩符 \d 匹配数字

\n 匹配⼀个换⾏符

\t 匹配⼀个制表符

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

\W 匹配⾮字⺟或数字或下划线

\D 匹配⾮数字

\S 匹配⾮空⽩符

a|b 匹配字符a或字符b

() 匹配括号内的表达式,也表示⼀个组

[...] 匹配字符组中的字符

[^...] 匹配除了字符组中字符的所有字符

量词: 控制前⾯的元字符出现的次数

*重复零次或更多次

+重复⼀次或更多次

? 重复零次或⼀次

{n} 重复n次

{n,} 重复n次或更多次

{n,m} 重复n到m次

贪婪匹配和惰性匹配

python 复制代码
str: 玩⼉吃鸡游戏, 晚上⼀起上游戏, ⼲嘛呢? 打游戏啊
reg: 玩⼉.*?游戏
此时匹配的是: 玩⼉吃鸡游戏
reg: 玩⼉.*游戏
此时匹配的是: 玩⼉吃鸡游戏, 晚上⼀起上游戏, ⼲嘛呢? 打游戏

str: <div>胡辣汤</div>
reg: <.*>
结果: <div>胡辣汤</div>

str: <div>胡辣汤</div>
reg: <.*?>
结果:
<div>
</div>

str: <div>胡辣汤</div><span>饭团</span>
reg: <div>.*?</div>
结果:
<div>胡辣汤</div>
  • 案例:练习用正则表达式提取豆瓣电影top250的数据并保存
python 复制代码
# 拿到页面源代码.   requests
# 通过re来提取想要的有效信息  re
import requests
import re
import csv

url = "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!")

cookies:处理需要登陆的网站

headers为HTTP协议中的请求头。⼀般存放⼀些和请求内容⽆关的数据。有时也会存放⼀些安全验证信息,比如常⻅的User-Agent,cookies等。通过requests发送的请求, 我们可以把请求头信息放在headers中。也可以单独进⾏存放, 最终由requests⾃动帮我们拼接成完整的http请求头

selenium

Selenium是一个Web的自动化测试工具,最初是为网站自动化测试而开发的,Selenium 可以直接调用浏览器,它支持所有主流的浏览器(包括PhantomJS这些无界面的浏览器),可以接收指令,让浏览器自动加载页面,获取需要的数据,甚至页面截屏等

  • 在下载好chromedriver以及安装好selenium模块后,可以执行下列代码并观察运行的过程
python 复制代码
from selenium import webdriver 
# 如果driver没有添加到了环境变量,则需要将driver的绝对路径赋值给executable_path参数
# driver = webdriver.Chrome(executable_path='driver的绝对路径')

# 如果driver添加了环境变量则不需要设置executable_path
driver = webdriver.Chrome()
# 向一个url发起请求
driver.get("https://www.baidu.com/")
# 把网页保存为图片
driver.save_screenshot("baidu.png")
# 打印页面的标题
print(driver.title) 
# 在百度搜索框中搜索'python'
driver.find_element_by_id('kw').send_keys('python')
# 点击'百度搜索'
driver.find_element_by_id('su').click()
# 退出模拟浏览器
driver.quit()
  • selenium工作原理:利用浏览器原生的API,封装成一套更加面向对象的Selenium WebDriver API,直接操作浏览器页面里的元素,甚至操作浏览器本身(截屏,窗口大小,启动,关闭,安装插件,配置证书之类的)
  • 在selenium中可以通过多种方式来定位标签,返回标签元素对象
python 复制代码
find_element_by_id                         (返回一个元素)
find_element(s)_by_class_name             (根据类名获取元素列表)
find_element(s)_by_name                 (根据标签的name属性值返回包含标签对象元素的列表)
find_element(s)_by_xpath                 (返回一个包含元素的列表)
find_element(s)_by_link_text             (根据连接文本获取元素列表)
find_element(s)_by_partial_link_text     (根据链接包含的文本获取元素列表)
find_element(s)_by_tag_name             (根据标签名获取元素列表)
find_element(s)_by_css_selector         (根据css选择器来获取元素列表)
  • selenium获取cookie:driver.get_cookies()返回列表,其中包含的是完整的cookie信息!不光有name、value,还有domain等cookie其他维度的信息。所以如果想要把获取的cookie信息和requests模块配合使用的话,需要转换为name、value作为键值对的cookie字典
python 复制代码
# 获取当前标签页的全部cookie信息
print(driver.get_cookies())
# 把cookie转化为字典
cookies_dict = {cookie['name']: cookie['value'] for cookie in driver.get_cookies()}
  • selenium控制浏览器执行js代码
python 复制代码
import time
from selenium import webdriver

driver = webdriver.Chrome()
driver.get("http://www.itcast.cn/")
time.sleep(1)

js = 'window.scrollTo(0,document.body.scrollHeight)' # js语句
driver.execute_script(js) # 执行js的方法 跳转到最底部

time.sleep(5)
driver.quit()

scrapy框架

  • Scrapy是一个Python编写的开源网络爬虫框架。它是一个被设计用于爬取网络数据、提取结构性数据的框架
  • scrapy的架构如下图,图中中文是为了方便理解后加上去的。图中绿色线条的表示数据的传递。注意图中中间件的位置,决定了其作用。注意其中引擎的位置,所有的模块之前相互独立,只和引擎进行交互
  • 爬虫中起始的url构造成request对象-->爬虫中间件-->引擎-->调度器
  • 调度器把request-->引擎-->下载中间件--->下载器
  • 下载器发送请求,获取response响应---->下载中间件---->引擎--->爬虫中间件--->爬虫
  • 爬虫提取url地址,组装成request对象---->爬虫中间件--->引擎--->调度器,重复步骤2
  • 爬虫提取数据--->引擎--->管道处理和保存数据

scrapy的三个内置对象

  • request请求对象:由url method post_data headers等构成
  • response响应对象:由url body status headers等构成
  • item数据对象:本质是个字典

scrapy中每个模块的具体作用

相关推荐
一点媛艺39 分钟前
Kotlin函数由易到难
开发语言·python·kotlin
姑苏风43 分钟前
《Kotlin实战》-附录
android·开发语言·kotlin
奋斗的小花生2 小时前
c++ 多态性
开发语言·c++
魔道不误砍柴功2 小时前
Java 中如何巧妙应用 Function 让方法复用性更强
java·开发语言·python
闲晨2 小时前
C++ 继承:代码传承的魔法棒,开启奇幻编程之旅
java·c语言·开发语言·c++·经验分享
_.Switch2 小时前
高级Python自动化运维:容器安全与网络策略的深度解析
运维·网络·python·安全·自动化·devops
老猿讲编程2 小时前
一个例子来说明Ada语言的实时性支持
开发语言·ada
Chrikk3 小时前
Go-性能调优实战案例
开发语言·后端·golang
幼儿园老大*3 小时前
Go的环境搭建以及GoLand安装教程
开发语言·经验分享·后端·golang·go
canyuemanyue3 小时前
go语言连续监控事件并回调处理
开发语言·后端·golang