P站爬虫
P站中,查看一个标签中热门的图片是会员功能,但是我们可以通过爬虫实现这个功能。过程如下:
- 利用Cookie登陆P站(不登录只能看一个标签的前10页)
- 向网页发送一个get请求,获取该网页的HTML
- 通过BeautifulSoup和正则表达式提取HTML中每一张图片的P站id、作品名、收藏数,并将其写入SQLite中。
- 查询SQLite中的所有元素,按收藏数降序排序
- 将SQLite的查询结果写入该脚本所在目录的文件夹中
P站某种标签下的URL的格式为:’http://www.pixiv.net/search.php?word=’ + <标签名> + '&s_mode=s_tag_full&order=date_d&p=‘+<页数>,想要遍历该标签下所有的图片,只需从第1页开始往后读,直到匹配出'未找到任何相关结果'时结束循环。页数>标签名>
完整程序:
import requests
from bs4 import BeautifulSoup
import re
import sqlite3
import time
import sys
# 在内存中创建一个临时数据库并连接
conn = sqlite3.connect(':memory:')
curs = conn.cursor()
# 新建一个表,元素包括ID,name,collNum(收藏数)
curs.execute('''CREATE TABLE pixiv
(ID INT PRIMARY KEY,
name VARCHAR(20),
collNum INT)''')
# 定义插入语句ins
ins = 'INSERT INTO pixiv VALUES(?,?,?)'
# 输入标签名
keyword = input('标签名:')
cook ='''<填自己的cookie>'''
# 将从浏览器抓取的cook整理成可以调用的格式
cookies = {}
for line in cook.split(';'):
name, value = line.strip().split('=',1)
cookies[name] = value
# 开始一个会话
s = requests.Session()
# 需要访问的url(不完整,后面需加上页码)
url = 'http://www.pixiv.net/search.php?word=' + keyword + '&s_mode=s_tag_full&order=date_d&p='
i = 1 # 从第一页开始爬
while True:
# 给url加上页码,生成真实url
rurl = url + str(i)
# 向rurl发送一个包含cook的get请求,返回结果保存在a中
a = s.get(rurl,cookies=cookies)
soup = BeautifulSoup(a.text,'html.parser')
# 选出第一个class=column-search-result的标签,保存在soup中
soup = soup.select('.column-search-result')[0]
# 如果汤中的文本为"未找到任何相关结果",则已经爬完所有页面,爬虫结束
if (soup.text == "未找到任何相关结果"):
break
# 选出soup中所有class=image-item的标签,并遍历他们
for link in soup.select('.image-item'):
name = link.select('h1')[0].text # 提取姓名
if (link.select('.bookmark-count') != []): # 如果存在class=bookmark-count的标签,则提取其中的收藏数
collNum = int(link.select('.bookmark-count')[0].text)
else: # 如果不存在,则收藏数为0
collNum = 0
ID = int(re.search(r'(?<=id=)\d*',link.select('a')[0]['href']).group()) # 用正则表达式提取id
try: # 尝试写入数据库中
curs.execute( ins ,(ID, name, collNum))
except: # 如果写入失败,则跳过
pass
print('第'+str(i)+'页')
i +=1
time.sleep(1) # 休眠一秒(怕被封)
# 将数据库中的元素按收藏数降序排序
curs.execute('SELECT * from pixiv ORDER BY collNum DESC')
# 将结果输出至脚本所在目录的results文件夹中,文件名为<标签名>.txt
with open(sys.path[0] + keyword + '.txt', 'w', encoding='utf-8') as f:
for line in curs.fetchall():
f.write(line[1] + ' ' + str(line[2]) + '\n')
f.write('http://www.pixiv.net/member_illust.php?mode=medium&illust_id=' + str(line[0]) + '\n')
f.write('\n')
print('结果保存在' + sys.path[0] + '\\'+ keyword + '.txt' + '中')
# 关闭数据库
curs.close()
conn.close()