有点闲适不知道看什么才好,那可以看看大众的口味。我们可以爬取各类国创,番剧等视频在榜作品,看看那些视频收到大家的喜爱。(虽然没人会用爬虫来看番)
目录
一、分析爬取网页
1.分析url
2.分析网页原码
二、分析爬取过程
三、✏代码实现
1.导入类
2.初始化
3.获取爬取类别和构造对应url
4.获取相关信息并将数据储存为csv文件
5.运行文件
四、完整代码
本文爬虫用到的各类函数和库
- import re
- import time
- import csv
- from selenium import webdriver
- from urllib.parse import quote
- from pyquery import PyQuery as pq
- from selenium.webdriver.support.wait import WebDriverWait
- from selenium.common.exceptions import TimeoutException
re | 提取原码信息(不可提取bytes-like类型字符) | |
time |
文中用于暂停或休眠 | |
csv |
|
|
selenium | 驱动浏览器,初始或browser对象 | |
quote | 将传入字符进行符合url格式的编码 | |
PyQuery |
|
|
WebDriverWait |
|
|
TimeoutException | 防止网络超时引起爬取停止 | |
打开站网页
找到想要爬取的内容,注意查看url的变化
分析不同内容之间url的变化,有时是某个参数的变化
我们注意到,在点击不同分类时,url的整体大致不改变,改变的只是url中的某一个参数。
如,点击查看分类、不同页数时url的变化
有时可以明确看到单个参数的变化。
我们记录下了我们想要爬取网页对应的变化参数
可用列表、字典等方式记录。
有时变化的形式可能为:参数 = 数字(数字会变化)
下面我们以字典为例
TITLE_DICT = {
'参数1': '内容1', '参数2': '内容2', '参数3': '内容3',
'参数4': '内容4', '参数5': '内容5',.......}
我们右键点击检查(开发者模式)
如果爬取的是单一内容
可以直接找到相关网页原码
爬取时直接传入url即可
如果爬取不同区域,但又相互联系的内容
可以尝试找到包含这些相互联系内容的总条目,点开总条目就可以看到相关的内容信息
那么我们就可以寻找和定位自己想爬取的信息。
爬取时因为url参数的变化,需要构造对应的url
下面主要以分析爬取多个内容为主
经上面分析,那么我们爬取不同内容时,我们可以先在我们记录的变化参数字典中一个一个取出参数,再构造url传入url进行爬取.
在爬取前,建议先将网页原码打印出来,因为我们获取到的原码可能会有些出入。
比如,打印出原码,我们会发现,有时一些文本是没有双引号的,但是正在网页中看时时有双引号的。
在爬取相关信息过程中,我们可以在获取网页原码后使用PyQuery构造解析对象,接着使用CSS选择器选出总条目,接着利用CSS选择器的chilren()方法获取包含作品信息的子条目。再用正则表达获取相关的信息。
当然也可以一开始就时用正则表达直接获取相关信息,不过正则表达会匹配完所有符合内容的信息,后续需要将他们分离出来再组成独立内容信息。
获取到爬取内容相关信息后我们将每个不同内容的信息都储存到字典中,接着将数据保存为csv文件,便于今后读取,检索等操作。
# -*- coding: utf-8 -*- # 默认编码为utf-8
import re
import time
import csv
from selenium import webdriver
from urllib.parse import quote
from pyquery import PyQuery as pq
from selenium.webdriver.support.wait import WebDriverWait
from selenium.common.exceptions import TimeoutException
开头已经说明导入函数作用,再次不在赘述
browser = webdriver.Chrome() # 以Chrome为驱动浏览器
wait = WebDriverWait(browser, 10)
"""
WebDriverWait 对象,它可以指定等待条件,同时指定一个最长等待时间,这里指定为最长 10 秒。如果在这个时间内成功匹配了等待条件,也就是说页面元素成功加载出来了,就立即返回相应结果并继续向下执行,否则到了最大等待时间还没有加载出来时,就直接抛出超时异常。
"""
# 初始化要爬取的类别
TITLE_DICT = {
'参数1': '内容1', '参数2': '内容2', '参数3': '内容3',
'参数4': '内容4', '参数5': '内容5',.......}
def get_category(key, value):
"""抓取xx内容"""
print('正在爬取xx内容:{value}'.format(value=value))
try:
"""这里使用quote接受key,也就是url分类对应参数,quote将key编码成
符合url格式的字符"""
url = 'https://www.网站连接' + quote(key) # 行如 ‘部分网站连接’ + ‘变化参数’
browser.get(url) # 传入url进行访问
time.sleep(10) # 休息十秒,避免访问频率过高导致ip被封
get_information() # 调用get_information()函数获取相关信息
except TimeoutException: # 如果连接超时则进行下一个分类的爬取
get_category(key, value)
quote函数用于屏蔽特殊的字符、比如如果url里面的空格!url里面是不允许出现空格的。
按照标准, URL 只允许一部分 ASCII 字符(数字字母和部分符号),其他的字符(如汉字)是不符合 URL 标准的。
所以 URL 中使用其他字符就需要进行 URL 编码,以构造正确的url。
def get_information():
"""提取内容信息"""
html = browser.page_source # 获取网页原码
doc = pq(html) # 构造解析对象
items = doc.find('使用选择器(如css选择器)初步选出包含爬取信息的总条目')
lis = items.children() # 使用items.children()获取各个子节点,也就是分条目
with open('文件名.csv', 'a', encoding='utf-8') as csvfile:
"""
打开文件名.csv(没有则自动创建),‘a’定义以添加方式写入文件,
因为数据包含中文,所以需要指定编码encoding='utf-8',不然会出现乱码
"""
# 定义csv文件头
fieldnames = ['参数1', '参数2', '参数3','参数4', '参数5',.......]
writer = csv.DictWriter(csvfile, fieldnames=fieldnames, delimiter=' ')
"""
因为我们使用字典储存爬取到数据,所以使用DictWriter将数据写入字典,
接着将定义的文件头传给fielnames参数,delimiter参数指定用何种分隔符
分隔字符
"""
writer.writeheader() # 写入文件头
for li in lis.items(): # 遍历各个条目和利用正则表达提取信息
information = {
'内容1': li.find('利用选择器寻找节点').text(),
'内容2': re.findall('正则表达式', str(li), re.S),
'内容3': str(re.findall('正则表达式',str(li),re.S)).replace(r'\n','').replace(' ', '').replace('[', '').replace(']', '').replace('\'', ''),
'内容4': str(re.findall('正则表达式', str(li), re.S)).replace(r'\n', '').replace(' ', '').replace('[', '').replace(']', '').replace('\'', '')
}
"""
这里使用的repla()函数是将正则获取到的数据进行清洗,去除换行符,
中括号,单引号等字符
writer.writerow(information) # 将数据字典写入csv文件
开头我们说到,正则表达不可提取bytes-like类型字符,而 for 循环中的 li 正是bytes-like型数据,所以我们使用str()函数将其转换为字符串类型(str(li))。
对于数据的清洗。如我们使用正则获取到的字符可能为
[ \n '文本1' \t \n]
为了便于查看和美观,我们将‘[’,‘\n’和单引号等符号用replace()函数去除。
简单用法replace('要去除的字符', '替换成的字符'),我们将这些符号替换成 '',也就相当于删除。
那没什么不直接使用CSS选择器选取?
这个视情况而定
有时候想获取的内容又相同的class节点,而且此时的解析对象 li 只包含一个条目的网页原码,使用CSS选择器选择较为麻烦,所以我们选择正则表达提取相关信息。
if __name__ == '__main__':
for key, value in TITLE_DICT.items():
get_category(key, value)
因为我们设置了休眠,所以运行后耐心等待十几秒,输出栏会有以下输出
正在爬取:内容1
正在爬取:内容2
等程序运行完毕后,我们可以再程序所在文件夹或者根目录找到 创建的csv 文件。
# -*- coding: utf-8 -*- import re import time import csv from selenium import webdriver from urllib.parse import quote from pyquery import PyQuery as pq from selenium.webdriver.support.wait import WebDriverWait from selenium.common.exceptions import TimeoutException browser = webdriver.Chrome() wait = WebDriverWait(browser, 10) TITLE_DICT = { '参数1': '内容1', '参数2': '内容2', '参数3': '内容3', '参数4': '内容4', '参数5': '内容5'} def get_category(key, value): """抓取xx内容""" print('正在爬取xx内容:{value}'.format(value=value)) try: url = 'https://www.网站连接' + quote(key) browser.get(url) time.sleep(10) get_information() except TimeoutException: get_category(key, value) def get_information(): """内容信息""" html = browser.page_source doc = pq(html) items = doc.find('使用选择器(如css选择器)初步选出包含爬取信息的总条目') lis = items.children() with open('文件名.csv', 'a', encoding='utf-8') as csvfile: fieldnames = ['参数1', '参数2', '参数3','参数4', '参数5'] writer = csv.DictWriter(csvfile, fieldnames=fieldnames, delimiter=' ') writer.writeheader() for li in lis.items(): infoinformation = { '内容1': li.find('利用选择器寻找节点').text(), '内容2': re.findall('正则表达式', str(li), re.S), '内容3': str(re.findall('正则表达式',str(li),re.S)).replace(r'\n','').replace(' ', '').replace('[', '').replace(']', '').replace('\'', ''), '内容4': str(re.findall('正则表达式', str(li), re.S)).replace(r'\n', '').replace(' ', '').replace('[', '').replace(']', '').replace('\'', '') } writer.writerow(information) if __name__ == '__main__': for key, value in TITLE_DICT.items(): get_category(key, value)
注:参数可视情况增减,选择器选择节点时可以再开发者选项中右键按不同选择器复制其节点即可,写正则表达时参考实际获取到的原码。
今天就到这,明天见。
❄❄❄❄❄❄❄❄❄❄❄❄❄❄❄❄❄❄❄❄end❄❄❄❄❄❄❄❄❄❄❄❄❄❄❄❄❄❄❄❄❄❄❄❄❄❄