最近学了点爬虫,整理了下相关的要点
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就可以打开开发者工具,所有的浏览器基本上都有着这样的功能
Elements是网页的html元素,一般我们分析这个网页首先都要从Elements开始
3.1 比如我们要爬取某些网页上的文字
同学要我帮他复制一个网页里的内容,但是这个网页禁止复制,我一开始想的是直接查看源代码,直接复制里面的元素就好了,但是这个网页不能使用F12或者右键
https://pri2.com/1248.html?tdsourcetag=s_pctim_aiomsg
当然肯定有其他方法,比如禁用当前页面的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失败
获取了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')
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相关的内容
login?lang=zh 就是我们发送给服务器的数据 我们看看其中发了什么
request url是我们发生数据的地址,数据被发送到了这个地方
request headers 是我们发送数据的头部,包括user-agent(浏览器信息),refer(请求发送源,可以理解为你从哪个地方点击)等信息,这些信息常常用于判断你是否是一个“真人”而不是程序
form data就是我们发送的数据,里面内容很好懂,帐号,密码等信息,但是有个东西我们不知道,就是post_key,这是个什么东西呢?
提前剧透下我们如果不写上这个内容就无法登录了。经过几次登录操作,我们发现每次post_key都不一样,那么这个post_key在哪里找呢?
回到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}) 限定一下位数,不然容易获取出错
这样我们就获取了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)
|
然后我们就能获取到一些每日排行榜的页面了
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, '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, '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()
|