18-12-19 爬虫(一)

最近学了点爬虫,整理了下相关的要点

1 相关知识点

  • python基本知识
  • requests,bs4
  • chrome抓包分析

2 python基本的知识

这个网站可以学习到python的基本语法,如果有其他语言的基础还是很容易的

w3-python

需要注意的就是:

  • python不像java,c靠括号,而是靠空格判断结构层次,所以建议使用tab,而不是空格
  • 每个语句就是一行,不需要靠 ;结束
  • 类,函数,循环,判断,都需要使用 :,例如def function(chr):
  • python经常用于科学计算,所以数组,矩阵的使用方法跟matlab,Haskell之类的相似

2.1 html 相关知识

html是非常简单的一种标记语言

w3-html

只需要花上一点点时间学习一下就行,有兴趣还可以再看下css和JavaScript的,主要能明白像是div class之类的意思就行

3 chrome开发者工具

在使用浏览器时,按下F12就可以打开开发者工具,所有的浏览器基本上都有着这样的功能
1.jpg
Elements是网页的html元素,一般我们分析这个网页首先都要从Elements开始

3.1 比如我们要爬取某些网页上的文字

2.jpg

同学要我帮他复制一个网页里的内容,但是这个网页禁止复制,我一开始想的是直接查看源代码,直接复制里面的元素就好了,但是这个网页不能使用F12或者右键

https://pri2.com/1248.html?tdsourcetag=s_pctim_aiomsg

3.jpg
4.jpg

当然肯定有其他方法,比如禁用当前页面的js,或者使用插件直接下载整个页面。既然要写爬虫,那就直接把这页html爬下来看一下吧,既然我能看到这个网页,我一定是接收到了他的html文件,直接用requests来获取吧

1
2
3
import requests
html = requests.get('https://pri2.com/1248.html')
print(html.text)

requests.get 获取网页 可以用.text来直接显示整个网页的html,或者是.encoding就是编码方式。不加,就是response,200成功,404失败

5.jpg

获取了html相关内容 直接使用beautifulsoup来提取其中内容就行了 稍微分析了一下,发现文字内容全在p标签和h2标签里

bs4文档

1
2
3
4
5
6
7
8
9
from bs4 import BeautifulSoup
import requests
html = requests.get('https://pri2.com/1248.html?tdsourcetag=s_pctim_aiomsg')
#print(html.text)
soup = BeautifulSoup(html.text)
p = soup.find_all('p')
h2 = soup.find_all('h2')
print(p[1].string)
print(h2[0].string)

直接把这些标签内容全部找出来就可以了,结果都保存到了数组中,接着使用循环把它全部打印出来就行了

3.2 模拟登陆

有些网站的内容我们会发现我们需要登录才能进行爬取,那么我们就可以先模拟登陆,我们拿p站做例子

我们开着开发者工具进行一次登录,在network中查看数据包,既然是登录,我们一定是发生数据给服务器,因此只要找到post相关的内容
6.jpg

login?lang=zh 就是我们发送给服务器的数据 我们看看其中发了什么

7.jpg

request url是我们发生数据的地址,数据被发送到了这个地方

8.jpg
request headers 是我们发送数据的头部,包括user-agent(浏览器信息),refer(请求发送源,可以理解为你从哪个地方点击)等信息,这些信息常常用于判断你是否是一个“真人”而不是程序

9.jpg

form data就是我们发送的数据,里面内容很好懂,帐号,密码等信息,但是有个东西我们不知道,就是post_key,这是个什么东西呢?

提前剧透下我们如果不写上这个内容就无法登录了。经过几次登录操作,我们发现每次post_key都不一样,那么这个post_key在哪里找呢?
10.jpg

回到elements ctrl+f查找一下 发现post_key就写在登录界面的html中,那我们就知道如何去登录了,首要的事情是要获取这个值

3.21 正则式

为了获取某些特定的值 我们就要去学习一下正则式的使用 正则式是非常重要的内容 不得不去学习一个

http://www.cnblogs.com/huxi/archive/2010/07/04/1771073.html

1
2
3
4
5
6
import requests
import re
loginHtml = requests.get('https://accounts.pixiv.net/login?lang=zh&source=pc&view_type=page&ref=wwwtop_accounts_index')
pattern = re.compile('<input type="hidden".*?value="(.*?)">', re.S)
result = re.search(pattern, loginHtml.text)
print(result.group(1))

(.*?)建议改成(.{20,50}) 限定一下位数,不然容易获取出错

11.jpg

这样我们就获取了post_key的值

p站因为魔法的原因只能全局科学上网才能爬取到数据呢

3.3 登录

接着我们写一个头部和数据部模拟发送就能完成登录了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
login_data ={
'pixiv_id':xxxx,
'password':xxxxx,
'post_key':xxxxxx,
'return_to':xxxxxx
}
loginHeaders ={
'Host': 'accounts.pixiv.net',
'User_Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36',
'Referer':'https://accounts.pixiv.net/login?lang=zh&source=pc&view_type=page&ref=wwwtop_accounts_index',
'content-type': 'application/x-www-form-urlencoded',
'Connection':'keep-alive'
}
requests.post(self.Loginurl,data = login_data, headers = self.loginHeaders)
#Loginurl就是先前的request url

然后我们就能获取到一些每日排行榜的页面了

3.4 获取相关内容遇到的一些问题

这里没有其他新知识,所以只说大概 之后一些完整代码会传到我的github

例如p站图片的每日排行榜,里面的图片都是小图,需要点进去才能获取到大图,经过分析,我们发现这些大图图片都有固定格式
https://i.pximg.net/img-original/img/' + urls + ‘_p0.jpg

urls内容需要在排行榜里获取,特别注意的是我们要requests获取图片 一定要记得在头部添加referer

https://www.pixiv.net/member_illust.php?mode=medium&illust_id=

当然有些图是多图 那么只能在排行榜页面爬取urls的时候进行区分 获取的大图有些是png只要写一个判断就能完成
完成后的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
import requests
import re
import time

s = requests.Session()

class pixiv:
def __init__(self):
self.baseurl = 'https://accounts.pixiv.net/login?lang=zh&source=pc&view_type=page&ref=wwwtop_accounts_index'
self.Loginurl = 'https://accounts.pixiv.net/api/login?lang=zh'
self.firstPageUrl = 'https://www.pixiv.net/ranking.php?mode=daily'
self.loginHeaders ={
'Host': 'accounts.pixiv.net',
'User_Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36',
'Referer':'https://accounts.pixiv.net/login?lang=zh&source=pc&view_type=page&ref=wwwtop_accounts_index',
'content-type': 'application/x-www-form-urlencoded',
'Connection':'keep-alive'
}
self.return_to = 'https://www.pixiv.net/'
self.pixiv_id = 'xxxxx'
self.password = 'xxxxx'
self.post_key = []

def getPostKey(self):
loginHtml = s.get(self.baseurl)
pattern = re.compile('<input type="hidden".*?value="(.*?)">', re.S)
result = re.search(pattern,loginHtml.text)
self.post_key = result.group(1)

def getPageAfterLogin(self):
login_data ={
'pixiv_id':self.pixiv_id,
'password':self.password,
'post_key':self.post_key,
'return_to':self.return_to
}
re = s.post(self.Loginurl,data = login_data, headers = self.loginHeaders)
targethtml = s.get(self.firstPageUrl)
return targethtml




def getImgUrl(self,pageHtml):
pattern1 = re.compile('illust_id=(.{8,10})"class="work _work multiple "', re.S)
pattern2 = re.compile('<a.*?illust_id=(.{8,10})"class="work _work "', re.S)
MultiImg = re.findall(pattern1, pageHtml.text)
OneImg = re.findall(pattern2, pageHtml.text)
self.Oneimg = OneImg
self.MultiImg = MultiImg


def getOneImg(self):
oneimg = self.Oneimg
for ids in oneimg:
time.sleep(3)
wholePageUrl ='https://www.pixiv.net/member_illust.php?mode=medium&illust_id='+ ids
detailhtml = s.get(wholePageUrl).text
pattern = re.compile('"original":"(.*?)"', re.S)
url = re.findall(pattern,detailhtml)
imgDownloadUrls = url[0].replace('\/','/')

header = {
'Referer': wholePageUrl, # 这个referer必须要,不然get不到这个图片,会报403Forbidden,具体机制也不是很清楚,可能也和cookies之类的有关吧
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'
}

img = s.get(imgDownloadUrls, headers=header)
if (img):
print(imgDownloadUrls + ' 下载中')
f = open(ids + '.jpg', 'wb')
f.write(img.content)
f.close()


def getMultiImg(self):
multiimg = self.MultiImg
for ids in multiimg:
time.sleep(3)
wholePageUrl = 'https://www.pixiv.net/member_illust.php?mode=manga&illust_id=' + ids
detailhtml = s.get(wholePageUrl).text
pattern = re.compile('data-src="(.*?)"', re.S)
url = re.findall(pattern, detailhtml)

header = {
'Referer': wholePageUrl, # 这个referer必须要,不然get不到这个图片,会报403Forbidden,具体机制也不是很清楚,可能也和cookies之类的有关吧
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'
}
n = 1
print(url)
for index in url:
strn = str(n)
img = s.get(index, headers=header)
if (img):
print(index + ' 下载中')
f = open(ids + '_' + strn + '.jpg', 'wb')
f.write(img.content)
f.close()
n+=1

p = pixiv()
p.pixiv_id = input('pixiv_account:')
p.password = input('password:')
p.getPostKey()
pagehtml = p.getPageAfterLogin()
p.getImgUrl(pagehtml)
p.getOneImg()
p.getMultiImg()
#print(p.MultiImg)
#p.getOneImg()

作者

Xingo

发布于

2018-12-19

更新于

2020-03-03

许可协议