爬虫的基础知识

爬虫的基础知识

html 了解

要想对网页数据进行爬取,首先的了解一点html的知识,才能对我们爬取数据提供一个好的环境和平台

HBuilder的下载及安装

点击html下载官网根据以下步骤进行操作

第一步

在这里插入图片描述

第二步
在这里插入图片描述

第三步

在这里插入图片描述

第四步,安装
在这里插入图片描述

下载为一个压缩包,解压到自己想存放的路径,最后进行安装就ok了。

创建HTML项目

在这里插入图片描述

HTML 的基本知识

HTML: hyperText markup languagel,超文本标记语言

HTML的后缀名:

  • .html

  • .htm

HTML的两种标签名

  • 一般标签:由起始标签和结束标签组成,可以插入其他标签或其他内容-,例如<h1>yyds</h1>

  • 自闭和标签:由起始标签组成,在起始标签末尾加斜杠,在中间不能加

    入任何东西,例如:<br />

注意

  • HTML中的标准是双引号
  • HTML没有大小写之分

注释:与python不一样 html的注释为 在html中 ctrl+/ 就能打印出来

格式化代码快捷键:ctrl + k

创建新的HTML会自动生成以下

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>

	<body>
	</body>
</html>

常用标签基本用法 注意标签之间的缩进

  • 各个标签的用法
  • 明白绝对路径和相对路径
<!-- 声明此文档为HTML5文档 -->
<!DOCTYPE html>
<!-- 定义了html文档   lang 表示中文-->
<html lang="zh">
	<!-- 提供了需要定义的信息 -->
	<head>
		<!-- 元信息 -->
		<meta charset="UTF-8">
		<meta name="viewport" content="width=device-width, initial-scale=1.0">
		<meta http-equiv="X-UA-Compatible" content="ie=edge">
		<!-- 定义了标题名 -->
		<title>html基础</title>
		<link rel="stylesheet" type="text/css" href="./css/style.css"/>
	</head>
	<!-- 在body标签写页面可见元素 -->
	<body>
		<!-- div:把不属于一类的标签间隔开  -->
		<div class="a">
			<!-- 标题标签:<h1>、<h2>....<h6> -->
			<h1 id="a">我是标题标签h1</h1>
			<h2>我是标题标签h2</h2>
			<h6>我是标题标签h6</h6>
			<!-- 段落标签:<p> -->
			<p>YYDS</p>
			<!-- 超链接标签<a> -->
			<a href="https://www.baidu.com/" target='_blank'>百度</a>
			
			<!-- 图像标签 <img /> -->
			<img src=
			"https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png" width="50px"/>
			
			<!-- href和src区别 -->
			<!-- href:负责引入超文本(HTML, CSS , JS) -->
			<!-- src:负责引入一些资源(图片、音频、视频)并且将引入的资源嵌入到页面 -->
			
			<img src="E:\新建文件夹\project\day21\img\4.jpg" width="60" height="80" />
			<img src="./img/4.jpg" width="60" height="60" />
			<!-- 绝对路径和相对路径 -->
			<!-- 绝对路径:在电脑上资源盘下放的路径, 相对于电脑 -->
			<!-- 相对路径:相对于当前文件所在目录, 寻找引入文件路径 
			./ 表示当前目录
			../ 返回上一级-->
			<img src="./../gril.jpg" width="250" height="400"/>
			
			<!-- 音频文件:<audio> -->
			<audio controls src="./music/1.m4a"></audio>
			
			<!-- 视频文件<video> -->
			<video controls src="./video/puppy_2.mp4"></video>
			
		</div>
		<div class="b">
			<!-- 列表:有序列表和无序列表 -->
			<ol>
				<!-- 页面的用的是数字标记 -->
				有序列表
				<li>海王</li>
				<li>甄嬛传</li>
				<li>斗罗大陆</li>
			</ol>
			<ul>
				<!-- 页面用的逗号标记-->
				无序列表
				<li>王者荣耀</li>
				<li>摩尔庄园</li>
				<li>和平精英</li>
			</ul>
			
			<!-- iframe框架:在当前页面嵌套一个新页面 -->
			<iframe src="https://www.chinanews.com/" width="1000px" height="1000px"></iframe>
		</div>
		<div class="c">
			<!-- 表格:<tbody> -->
			<!-- tr:表格的行数 -->
			<!-- th:表头 -->
			<!-- td:存放内容的单元格 -->
			<tbody>
				<tr>
					<th>队名</th>
					<th>第一节</th>
					<th>第二节</th>
					<th>第三节</th>
					<th>第四节</th>
					<th>总分</th>
				</tr>
				<br />
				<tr>
					<td>太阳</td>
					<td>&nbsp;16</td>
					<td>31</td>
					<td>30</td>
					<td>21</td>
					<td>98</td>
				</tr>
				<br />
				<tr>
					<td>雄鹿</td>
					<td>29</td>
					<td>13</td>
					<td>35</td>
					<td>28</td>
					<td>105</td>
				</tr>
			</tbody>
			<!-- 换行标签 <br /> -->
			<!-- 水平线标签  <hr /> -->
			<hr />
			<!-- 加粗标签 b,strong -->
			<b>YYDS</b>
			<strong>YYDS</strong>
			
			<!-- 文字倾斜标签。i,em -->
			<i>文字倾斜</i>
			<em>文字倾斜</em>
			
			<!-- 表单标签: <form> -->
			<form>
				账号:<input type="tell" /><br />
				密码:<input type="password" /><br />
				<input type="submit" value="登录" />
				<input type="reset" value="重置" />
			</form>
		</div>
	</body>
</html>

css用来修饰html

注释:ctrl+/ 和HTML不一样 /*注释内容 */

css用于描述HMTL样式的编程语言

/* css引入分为:行内式、内嵌式、外链式 */
/ 通配符选择器 */

/* 通配符选择器 */
* {
	/* 外边距 */
	margin: none;
	/* 内边距 */
	padding: none;
}

/* 类选择器 */
.a {
	/* 外部线框 */
	/* 单实线 */
	border: 10px solid red;
}

.b {
	/* 双实线 */
	border: 10px double blue;
}

.c {
	/* dotted 虚线 */
	border: 10px dotted green;
}

/* id选择器 */
#a {
	/* 字体颜色 */
	color: yellowgreen;
	/* 字体样式 */
	font-family: "楷体";
	/* 字体尺寸 */
	font-size: 20px;
}

/* 标签选择器 */
/* 将前端中标签选择器 */
/* 直接选择p标签 */
p {
	font-size: 50px;
}

/* 父子选择器 */
/* 修改指定父标签下的某个子标签位置 */
.a>h2 {
	/* 水平中间 */
	text-align: center;
}

/* 后代选择器 */
.b li {
	color: aquamarine;
}

/* 兄弟选择器 */
/* 和连接符左边的标签同级关系的下方所有标签都是他的兄弟 */
h1~h6 {
	text-align: center;
}

/* 相邻兄弟选择器 */
/* 只能选择连接符左边的标签同级的相邻的下方的标签 */
h1+h2 {
	font-family: "仿宋";
}

/* nth-child选择器 */
/* nth-child只根据同级关系查找 */
.b>ol>li:nth-child(2) {
	color: red;
}

/* 属性选择器 */
input[type=submit] {
	/* 背景颜色 */
	background-color: darkseagreen;
	/* 字体颜色 */
	color: white;
	/* 去掉边框 */
	border: none;
}

form {
	
	border: 2px solid black;
	width: 450px;
	/* margin-left: 500px; */
	/* 修改外边距 默认 上右下左 */
	margin: 20px 500px 30px 500px;
	
	
}

网页请求

import requests

用requests请求网页

状态码
200, 爬虫可用
403,访问的网站将爬虫封了
404,页面丢失
500,服务器出问题

请求豆瓣电影

import requests
import bs4
import selenium
from lxml import etree
import re

URL ='http://movie.douban.com/top250'
#headers用来伪装爬虫
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36'
}
resp =requests.get(url=URL, headers=headers)
print(resp.text)
with open('豆瓣电影.html','w',encoding='utf-8') as file:
    file.write(resp.text)



with open('豆瓣电影.html','r',encoding='utf-8') as file:
    content = file.read()
    #print(content)

re_str = '<img width="100" alt="(.+)" src="(.+)" class="">'
result = re.search(re_str,content)
print(result)
#span()输出匹配到的字符串的起始位置和结束位置
print(result.span())
#group()将分组中的内容返回出来
# 如果参数是0 将所有分组的内容输出
print(result.group(1))#输出第一个分组
print(result.group(2))#输出第二个分组
# groups 将正则表达式中分组的内容合成一个元组
print(result.groups())

results2 = re.findall('<img width="100" alt="(.+)" src="(.+)" class="">',content)
for results in results2:
    print(results)

requests的几种方法

import requests
import re

URL = 'https://wwwbaidu.com/'

#User-Agent: 将爬虫模拟成浏览器
#Cooike :存放的用户的账号密码信息
headers = {
    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36'

}

resp = requests.get(url=URL,headers=headers)
#状态码
#200,爬虫可用
#403,访问的网站将爬虫封了
#404,页面丢失
#500,服务器出问题
print(resp.status_code)

#打印访问的网址
print(resp.url)

#打印响应头:只需要记住'Content-Type'
print(resp.headers)

#打印响应头中提供的编码方式
#如果没有 ,默认选择ISO-8859-1:不能显示中文
print(resp.encoding)

#打印网页原代码中提供的编码方式
print(resp.apparent_encoding)

resp.encoding = resp.apparent_encoding

#文本流方式打印网页源码
print(resp.text)

# #以字节流(二进制)输出源码
# print(resp.content)

字符匹配的三种方式

re正则表达式

group(1)#输出第一个分组

group(2)#输出第二个分组

groups() 将正则表达式中分组的内容合成一个元组

爬取成都链家二手房信息

# 成都链家二手房信息
import requests
import re

URL = 'https://cd.lianjia.com/ershoufang/rs/'
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36 Edg/92.0.902.73'
}
resp = requests.get(url=URL, headers=headers)
# print(resp.text)
li_str = re.compile('<li class="clear(.+?)</li>')
content = li_str.findall(resp.text)
# print(content, len(content))
for i in content:
    # print(i)
    # 房屋标题
    title = re.compile(
        'data-log_index="\d{1,2}"  data-el="ershoufang" data-housecode="\d{12}" data-is_focus="" data-sl="">(.+?)</a>')
    title_content = title.search(i)
    title_1 = title_content.group(1)
    print(title_1)

    # 位置
    area = re.compile(
        'data-el="region">([\u4e00-\u9fa5]+([\u4e00-\u9fa5]+|\d+|[A-Z]+)[\u4e00-\u9fa5]+)[^\u4e00-\u9fa5]+([\u4e00-\u9fa5]+)</a>')
    area_content = area.search(i)
    x, y, z = area_content.groups()
    print(f'{x}-{z}')

    # 单价
    unit_price = re.compile('<span>(单价\d+元/平米)</span>')
    unit_price_1 = unit_price.search(i)
    print(unit_price_1.group(1))

    # 总价
    total_price = re.compile('<span>(\d+\.?\d+)</span>万')
    total_price_1 = total_price.search(i)
    print(total_price_1.group(1) + '万')

    print('*' * 10)

bs4

bs4 :全称 :Beautiful 4,可以从HTML或者XMl中提取数据。

请求过后使用bs4中的BeautifulSoup方法

soup = bs4.BeautifulSoup(resp.text, 'lxml') 第一个参数是请求到的网页,第二给是解释方法

.text 提取标签中的内容

.attrs[]提取标签中的链接

格式化爬取到的HTML源码
print(soup.prettify())

bs4用法

select:使用(id、class、标签、属性、父子、后代、兄弟、相邻兄弟选择器等)去选择标签,返回的结果是一个列表

select_one:使用(id、class、标签、属性、父子、后代、兄弟、相邻兄弟选择器等)去选择标签,,返回的结果是select结果中的第一个元素后代)

import bs4

# bs4 :全称 :Beautiful 4,可以从HTML或者XMl中提取数据。
html = """
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title" name="dromouse"><b>The Dormouse's story</b></p>
<p class="story">Once upon a time there were three little sisters; and their names were
<a href="http://example.com/elsie" class="sister" id="link1"><!-- Elsie --></a>,
<a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
<a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
and they lived at the bottom of a well.</p>
<p class="story">...</p>
"""
soup = bs4.BeautifulSoup(html,'lxml')
# print(soup,type(soup),sep='\n')
#格式化爬取到的HTML源码
print(soup.prettify())


print('--'*20)
#打印标签:只打印第一个某某标签的内容
# print(soup.head.title)

#打印标签的内容
# print(soup.head.title.string)
# print(soup.head.title.get_text())
# print(soup.head.title.text)
# print(soup.head.title.contents)
"""
The Dormouse's story
The Dormouse's story
The Dormouse's story
["The Dormouse's story"]
"""

# 选择标签内容方法:
# select:使用(id、class、标签、属性、父子、后代、兄弟、相邻兄弟选择器等)去选择标签,返回的结果是一个列表
# select_one:使用(id、class、标签、属性、父子、后代、兄弟、相邻兄弟选择器等)去选择标签,,返回的结果是select结果中的第一个元素后代)
p_list = soup.select('body > p')
print(p_list)
# p_list_1 = soup.select('body > .title')
# print(p_list_1)
#
p = soup.select_one('body > p')
print(p)

爬取中国新闻网标题及时间

# 中国新闻网当天新闻爬取
import requests
import bs4
import time

print(time.localtime())#现在的时间

flag = True
page = 1
while flag:
    URL = f'https://www.chinanews.com/scroll-news/news{page}.html'
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36'
    }
    resp = requests.get(url=URL, headers=headers)
    page += 1
    print(resp.status_code)
    resp.encoding = 'UTF-8'
    # print(resp.text)
    soup = bs4.BeautifulSoup(resp.text, 'lxml')
    # print(soup)
    li_list = soup.select('body > #content > #content_right > div.content_list > ul > li')
    # print(li_list,len(li_list))
    for i in li_list:
        # print(i)
        try:
            localtime = time.localtime()
            if f'{localtime.tm_mon}-{localtime.tm_mday}' == i.select_one('li > .dd_time').text[:-6]:
                # 新闻类型
                news_type = i.select_one('li > .dd_lm').text
                # 新闻标题
                news_title = i.select_one('li > .dd_bt > a').text
                # 新闻链接
                news_href = 'https:' + i.select_one('li > .dd_bt > a').attrs['href']
                # 发布时间
                news_time = i.select_one('li > .dd_time').text
                print(news_type, news_title, news_href, news_time)
            else:
                flag = False
                break
        except Exception as err:
            print(err)

selenium 自动化测试

from selenium import webdriver

# selenium,自动化测试
from selenium import webdriver
import time

URL = 'https://www.chinanews.com/scroll-news/news1.html'
URL1 = 'https://www.baidu.com/'
URL2 = 'https://www.taobao.com/'
# 创建浏览器对象
b = webdriver.Chrome('./chromedriver.exe')

# # 设置浏览器窗口大小
# b.set_window_size(1920, 1080)
# 将浏览器设置成全屏
# b.maximize_window()

# # 请求链接
b.get(URL)
# b.get(URL1)
# b.get(URL2)
#
# # 后退
# b.back()
# time.sleep(1)
# # 前进
# b.forward()

# # 打印网页源码:是字符串 --> bs4
# print(b.page_source, type(b.page_source))


#滚动滚动条
max_y = 4000
y = 0
while y <= max_y:
    b.execute_script(f'window.scrollTo(0,{y})')
    y += 1000
    time.sleep(1)

# contents = b.find_element_by_id('content_right').text  #包含下一级标签
#  print(contents)
# news_title = b.find_elements_by_class_name('dd_bt')  #同级标签是个列表
# for new in news_title:
#     print(new.text)
# print(news_title)


# news_href = b.find_element_by_css_selector(
#     '#content_right > div.content_list > ul > li > div.dd_bt > a').get_attribute('href')
# print(news_href)

# close()如果selenium打开了一个浏览器窗口,但是这个窗口有多个标签页,只关闭当前所在标签页;
# quit()直接关闭浏览器窗口;
# 浏览器打开时会产生缓存文件,close()只关闭浏览器,不执行清理缓存操作。quit()在关闭浏览器的同时会清理缓存。
b.close()
b.quit()

获取cookie

import time

from selenium import webdriver


URL = 'https://www.taobao.com/'
url2 = 'https://www.baidu.com/'

# 设置配置项
#options = webdriver.ChromeOptions()
#不加载图片提升速度
#options.add_argument('blink-settings=imagesEnabled=false')
#创建浏览器对象
b = webdriver.Chrome('./chromedriver.exe')
b.get(URL)

# 打开新的标签页
b.execute_script('window.open()')
# 输出选项卡
print(b.window_handles)
# 切换选项卡
b.switch_to.window(b.window_handles[1])
b.get(url2)
time.sleep(1)

#切换选项卡
b.switch_to.window(b.window_handles[0])

#点击登录选项
b.find_element_by_class_name('h').click()
b.find_element_by_class_name('icon-qrcode').click()

#隐式等待:全局等待方式
b.implicitly_wait(258)
# 检测信息是否被加载
b.find_element_by_class_name('site-nav-login-info-nick ')


# 获取cookie
cookie = b.get_cookies()
print(cookie)

# 保存cookie :数据的持久化
with open('cookie.txt','w') as file:
    file.write(str(cookie))

b.quit()

请求淘宝

import time

from Tools.i18n.pygettext import safe_eval
from selenium import webdriver
#导入按键事件
from selenium.webdriver.common import keys


URL = 'https://www.taobao.com/'


#设置配置项
options = webdriver.ChromeOptions()
# 设置取消图片加载
options.add_experimental_option("prefs", {"profile.managed_default_content_settings.images": 2})

with open('cookie.txt','r') as file:
    cookie = file.read()
print(cookie)
new_cookie = safe_eval(cookie)

#创建浏览器对象
b = webdriver.Chrome('./chromedriver.exe', options=options)
# 防止selenium被监测
# 先修改js,再加载js
b.execute_cdp_cmd(
    "Page.addScriptToEvaluateOnNewDocument",
    {
        "source": "Object.defineProperty(navigator, 'webdriver', {get: () => undefined})"
    }
)

#先访问淘宝页面 ,再传cookie
b.get(URL)
for i in new_cookie:
    if i['secure']:
        b.add_cookie(i)
# 再重新请求页面
b.get(URL)

# 定位搜索框
search = b.find_element_by_id('q').send_keys('三只松鼠大礼包')

# 定位搜索按钮
enter = b.find_element_by_class_name('btn-search').send_keys(keys.Keys.ENTER)


# 拖动进速度条
max_y = 5000
y = 0
while y <= max_y:
    b.execute_script(f'window.scrollTo(0, {y})')
    y += 1000
    time.sleep(2)

print(b.page_source)#打印源码

代理IP

当请求过多的时候我们的IP可能会被封掉,此时就需要使用代理ip也就是用其他IP来请求

代理IP有专门的网站售卖,但不是所有的代理IP都行,所以我们要进行代理IP的检查
在这里插入图片描述

把下面代码装为一个包 check_proxies

"""
此代码为代理IP可用性检测模块,可准确筛选出尚未失效IP
注:
1.此代码只针对TXT数据格式接口。
2.尚未失效IP不一定为爬虫可用IP
3.使用时,请调用check_ip(url),url为TXT数据格式接口地址
"""
import requests
import telnetlib
import re
from concurrent.futures.thread import ThreadPoolExecutor


# 请求接口,匹配出代理IP,多线程检测
def check_ip(url):
    real_ip = []

    # 检测代理IP是否失效
    def telnet_ip(ip, port):
        try:
            telnetlib.Telnet(ip, port, timeout=1)
            real_ip.append(f'{ip}:{port}')
        except:
            pass

    resp = requests.get(url)
    ip_data = re.findall('(\d+\.\d+\.\d+\.\d+):(\d+)', resp.text)
    with ThreadPoolExecutor(max_workers=16) as pool:
        for ip, port in ip_data:
            pool.submit(telnet_ip, ip, port)
    return real_ip
检查代理IP

导入上面的包check_proxies

请求豆瓣电影

from check_proxies import check_ip
import requests
import bs4

flag = True
while flag:
    URL = 'http://api.66daili.cn/API/GetCommonProxy/?orderid=2291244402101903832&num=20&token=66daili&format=text&line_separator=win&protocol=http&anonymous=elite,anonymous,transparent&area=%E4%B8%AD%E5%9B%BD&proxytype=https&speed=fast#api'
    ip_list = check_ip(URL)   #检查代理ip 能用的则把IP 装为一个列表
    print(ip_list)
    for i in range(len(ip_list)):
        douban_url = 'https://movie.douban.com/top250'
        headers = {
            'User-Agent': 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36'
        }
        # 代理IP
        proxy = {
            'http': 'http://' + ip_list[i],
            'https': 'https://' + ip_list[i]
        }
        try:
            resp = requests.get(url=douban_url, headers=headers, proxies=proxy, timeout=1)
            if resp.status_code == 200:
                print(resp.text)
                flag = False
                break
        except:
            print('ERROR')
  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值