终于想开始爬自己想爬的网站了。于是就试着爬P站试试手。
一开始以为不用登陆,就直接去爬图片了。
后来发现是需要登录的,但是不会只好去学模拟登陆。
然后还要去获取我们登陆时候需要的data。点住上面的presevelog,找到登陆的网址,点开查看Form Data就可以知道我们post的时候的data需要什么了。这里可以看到有个postkey,多试几次可以发现这个是变化的,即我们要去捕获它,而不能直接输入。
于是退回到登陆界面,F12查看源码,发现有一个postkey,那么我们就可以写一个东西去捕获它,然后把它放到我们post的data里面。
这里给出登陆界面需要的代码:
1 def __init__(self):2 self.base_url = 'https://accounts.pixiv.net/login?lang=zh&source=pc&view_type=page&ref=wwwtop_accounts_index'
3 self.login_url = 'https://accounts.pixiv.net/api/login?lang=zh'
4 self.target_url = 'http://www.pixiv.net/search.php?'\5 'word=%E5%9B%9B%E6%9C%88%E3%81%AF%E5%90%9B%E3%81%AE%E5%98%98&order=date_d&p='
6 self.main_url = 'http://www.pixiv.net'
7 #headers只要这两个就可以了,之前加了太多其他的反而爬不上
8 self.headers ={9 'Referer': 'https://accounts.pixiv.net/login?lang=zh&source=pc&view_type=page&ref=wwwtop_accounts_index',10 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64)'
11 'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36'
12 }13 self.pixiv_id = 'userid'
14 self.password = '*****'
15 self.post_key =[]16 self.return_to = 'http://www.pixiv.net/'
17 self.load_path = 'D:\psdcode\Python\pixiv_pic'
18 self.ip_list =[]19
20 deflogin(self):21 post_key_html = se.get(self.base_url, headers=self.headers).text22 post_key_soup = BeautifulSoup(post_key_html, 'lxml')23 self.post_key = post_key_soup.find('input')['value']24 #上面是去捕获postkey
25 data ={26 'pixiv_id': self.pixiv_id,27 'password': self.password,28 'return_to': self.return_to,29 'post_key': self.post_key30 }31 se.post(self.login_url, data=data, headers=self.headers)
愉快地解决完登陆问题之后,就可以开始爬图片啦。
进入target_url:上面的目标网址。
点击目标的位置
点开ul这个标签,发现图片全部都是在
这里面的,因为我们要爬大一点的图(爬个小图有什么用啊!),所以还要进入一层第一个链接的网址去获取大图,我们可以发现我们只要在main_url((http://www.pixiv.net)),再加上第一个href,就可以跑到图片所在的网址了,于是我们先跳转到图片网址看看怎么提取图片。发现图片就躺在这里了,而且连标题都有,直接方便了我们存图的名字了。于是我们就可以直接去提取图片了。
注意我们在请求获取图片的时候要加一个referer,否则会403的。referer的找法就和上面一样。
1 defget_img(self, html, page_num):2 li_soup = BeautifulSoup(html, 'lxml') #传入第page_num页的html
3 li_list = li_soup.find_all('li', attrs={'class', 'image-item'}) #找到li所在位置
4 #print('get_list succeed')
5 #print(li_list)
6 for li inli_list:7 href = li.find('a')['href'] #直接提取第一个href
8 #print('get_href succeed')
9 #print(href)
10 jump_to_url = self.main_url + href #跳转到目标的url
11 #print('get_jump_to_url succeed')
12 jump_to_html = self.get_html(jump_to_url, 3).text #获取图片的html
13 #print('get_jump_to_html succeed')
14
15 img_soup = BeautifulSoup(jump_to_html, 'lxml')16 img_info = img_soup.find('div', attrs={'class', 'works_display'})\17 .find('div', attrs={'class', '_layout-thumbnail ui-modal-trigger'})18 #找到目标位置的信息
19 if img_info is None: #有些找不到url,如果不continue会报错
20 continue
21 self.download_img(img_info, jump_to_url, page_num) #去下载这个图片
22
23 defdownload_img(self, img_info, href, page_num):24 title = img_info.find('img')['alt'] #提取标题
25 src = img_info.find('img')['src'] #提取图片位置
26 src_headers =self.headers27 src_headers['Referer'] = href #增加一个referer,否则会403,referer就像上面登陆一样找
28 try:29 html = requests.get(src, headers=src_headers)30 img =html.content31 except: #有时候会发生错误导致不能获取图片.直接跳过这张图吧
32 print('获取该图片失败')33 return False
接下来轮到下载图片了。这个之前还不怎么会,临时学了一下。
首先是创建文件夹,我这里是每一页就开一个文件夹。
1 defmkdir(self, path):2 path =path.strip()3 is_exist =os.path.exists(os.path.join(self.load_path, path))4 if notis_exist:5 print('创建一个名字为' + path + '的文件夹')6 os.makedirs(os.path.join(self.load_path, path))7 os.chdir(os.path.join(self.load_path, path))8 returnTrue9 else:10 print('名字为' + path + '的文件夹已经存在')11 os.chdir(os.path.join(self.load_path, path))12 return False
1 defdownload_img(self, img_info, href, page_num):2 title = img_info.find('img')['alt'] #提取标题
3 src = img_info.find('img')['src'] #提取图片位置
4 src_headers =self.headers5 src_headers['Referer'] = href #增加一个referer,否则会403,referer就像上面登陆一样找
6 try:7 html = requests.get(src, headers=src_headers)8 img =html.content9 except: #有时候会发生错误导致不能获取图片.直接跳过这张图吧
10 print('获取该图片失败')11 returnFalse12
13 title = title.replace('?', '_').replace('/', '_').replace('\\', '_').replace('*', '_').replace('|', '_')\14 .replace('>', '_').replace('
16
17 if os.path.exists(os.path.join(self.load_path, str(page_num), title + '.jpg')):18 for i in range(1, 100):19 if not os.path.exists(os.path.join(self.load_path, str(page_num), title + str(i) + '.jpg')):20 title = title +str(i)21 break
22 #如果重名了,就加上一个数字
23 print('正在保存名字为:' + title + '的图片')24 with open(title + '.jpg', 'ab') as f:25 f.write(img)26 print('保存该图片完毕')
这样我们的大体工作就做完了。剩下的是写一个work函数让它开始跑。
1 defwork(self):2 self.login()3 for page_num in range(1, 51): #太多页了,只跑50页
4 path = str(page_num) #每一页就开一个文件夹
5 self.mkdir(path) #创建文件夹
6 #print(self.target_url + str(page_num))
7 now_html = self.get_html(self.target_url + str(page_num), 3) #获取页码
8 self.get_img(now_html.text, page_num) #获取图片
9 print('第 {page} 页保存完毕'.format(page=page_num))10 time.sleep(2) #防止太快被反
启动!
大概跑了10页之后,会弹出一大堆信息什么requests不行怎么的。问了下别人应该是被反爬了。
于是去搜了一下资料,http://cuiqingcai.com/3256.html,照着他那样写了使用代理的东西。(基本所有东西都在这学的)。
于是第一个小爬虫就好了。不过代理的东西还没怎么懂,到时候看看,50页爬了两个多钟。
对了。可能网站的源代码会有改动的。因为我吃完饭后用吃饭前的代码继续工作的时候出错了,然后要仔细观察重新干。
1 #-*- coding:utf-8 -*-
2 importrequests3 from bs4 importBeautifulSoup4 importos5 importtime6 importre7 importrandom8
9 se =requests.session()10
11
12 classPixiv():13
14 def __init__(self):15 self.base_url = 'https://accounts.pixiv.net/login?lang=zh&source=pc&view_type=page&ref=wwwtop_accounts_index'
16 self.login_url = 'https://accounts.pixiv.net/api/login?lang=zh'
17 self.target_url = 'http://www.pixiv.net/search.php?'\18 'word=%E5%9B%9B%E6%9C%88%E3%81%AF%E5%90%9B%E3%81%AE%E5%98%98&order=date_d&p='
19 self.main_url = 'http://www.pixiv.net'
20 #headers只要这两个就可以了,之前加了太多其他的反而爬不上
21 self.headers ={22 'Referer': 'https://accounts.pixiv.net/login?lang=zh&source=pc&view_type=page&ref=wwwtop_accounts_index',23 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64)'
24 'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36'
25 }26 self.pixiv_id = 'userid'
27 self.password = '*****'
28 self.post_key =[]29 self.return_to = 'http://www.pixiv.net/'
30 self.load_path = 'D:\psdcode\Python\pixiv_pic'
31 self.ip_list =[]32
33 deflogin(self):34 post_key_html = se.get(self.base_url, headers=self.headers).text35 post_key_soup = BeautifulSoup(post_key_html, 'lxml')36 self.post_key = post_key_soup.find('input')['value']37 #上面是去捕获postkey
38 data ={39 'pixiv_id': self.pixiv_id,40 'password': self.password,41 'return_to': self.return_to,42 'post_key': self.post_key43 }44 se.post(self.login_url, data=data, headers=self.headers)45
46 defget_proxy(self):47 html = requests.get('http://haoip.cc/tiqu.htm')48 ip_list_temp = re.findall(r'r/>(.*?)
54 '''会被反爬,改成使用代理55 def get_tml(self, url):56 response = se.get(url, headers=self.headers)57 return response58 '''
59 def get_html(self, url, timeout, proxy=None, num_entries=5):60 if proxy isNone:61 try:62 return se.get(url, headers=self.headers, timeout=timeout)63 except:64 if num_entries >0:65 print('获取网页出错,5秒后将会重新获取倒数第', num_entries, '次')66 time.sleep(5)67 return self.get_html(url, timeout, num_entries = num_entries - 1)68 else:69 print('开始使用代理')70 time.sleep(5)71 ip = ''.join(str(random.choice(self.ip_list))).strip()72 now_proxy = {'http': ip}73 return self.get_html(url, timeout, proxy =now_proxy)74 else:75 try:76 return se.get(url, headers=self.headers, proxies=proxy, timeout=timeout)77 except:78 if num_entries >0:79 print('正在更换代理,5秒后将会重新获取第', num_entries, '次')80 time.sleep(5)81 ip = ''.join(str(random.choice(self.ip_list))).strip()82 now_proxy = {'http': ip}83 return self.get_html(url, timeout, proxy = now_proxy, num_entries = num_entries - 1)84 else:85 print('使用代理失败,取消使用代理')86 returnself.get_html(url, timeout)87
88 defget_img(self, html, page_num):89 li_soup = BeautifulSoup(html, 'lxml') #传入第page_num页的html
90 li_list = li_soup.find_all('li', attrs={'class', 'image-item'}) #找到li所在位置
91 #print('get_list succeed')
92 #print(li_list)
93 for li inli_list:94 href = li.find('a')['href'] #直接提取第一个href
95 #print('get_href succeed')
96 #print(href)
97 jump_to_url = self.main_url + href #跳转到目标的url
98 #print('get_jump_to_url succeed')
99 jump_to_html = self.get_html(jump_to_url, 3).text #获取图片的html
100 #print('get_jump_to_html succeed')
101
102 img_soup = BeautifulSoup(jump_to_html, 'lxml')103 img_info = img_soup.find('div', attrs={'class', 'works_display'})\104 .find('div', attrs={'class', '_layout-thumbnail ui-modal-trigger'})105 #找到目标位置的信息
106 if img_info is None: #有些找不到url,如果不continue会报错
107 continue
108 self.download_img(img_info, jump_to_url, page_num) #去下载这个图片
109
110 defdownload_img(self, img_info, href, page_num):111 title = img_info.find('img')['alt'] #提取标题
112 src = img_info.find('img')['src'] #提取图片位置
113 src_headers =self.headers114 src_headers['Referer'] = href #增加一个referer,否则会403,referer就像上面登陆一样找
115 try:116 html = requests.get(src, headers=src_headers)117 img =html.content118 except: #有时候会发生错误导致不能获取图片.直接跳过这张图吧
119 print('获取该图片失败')120 returnFalse121
122 title = title.replace('?', '_').replace('/', '_').replace('\\', '_').replace('*', '_').replace('|', '_')\123 .replace('>', '_').replace('
125
126 if os.path.exists(os.path.join(self.load_path, str(page_num), title + '.jpg')):127 for i in range(1, 100):128 if not os.path.exists(os.path.join(self.load_path, str(page_num), title + str(i) + '.jpg')):129 title = title +str(i)130 break
131 #如果重名了,就加上一个数字
132 print('正在保存名字为:' + title + '的图片')133 with open(title + '.jpg', 'ab') as f: #图片要用b
134 f.write(img)135 print('保存该图片完毕')136
137 defmkdir(self, path):138 path =path.strip()139 is_exist =os.path.exists(os.path.join(self.load_path, path))140 if notis_exist:141 print('创建一个名字为' + path + '的文件夹')142 os.makedirs(os.path.join(self.load_path, path))143 os.chdir(os.path.join(self.load_path, path))144 returnTrue145 else:146 print('名字为' + path + '的文件夹已经存在')147 os.chdir(os.path.join(self.load_path, path))148 returnFalse149
150 defwork(self):151 self.login()152 for page_num in range(1, 51): #太多页了,只跑50页
153 path = str(page_num) #每一页就开一个文件夹
154 self.mkdir(path) #创建文件夹
155 #print(self.target_url + str(page_num))
156 now_html = self.get_html(self.target_url + str(page_num), 3) #获取页码
157 self.get_img(now_html.text, page_num) #获取图片
158 print('第 {page} 页保存完毕'.format(page=page_num))159 time.sleep(2) #防止太快被反
160
161
162 pixiv =Pixiv()163 pixiv.work()