获取待爬取页面

今天继续爬取一个网站,http://www.27270.com/ent/meinvtupian/ 这个网站具备反爬,so我们下载的代码有些地方处理的也不是很到位,大家重点学习思路,有啥建议可以在评论的地方跟我说说。

为了以后的网络请求操作方向,我们这次简单的进行一些代码的封装操作。

在这里你可以先去安装一个叫做 retrying 的模块

pip install retrying

这个模块的具体使用,自己去百度吧。嘿嘿哒~

在这里我使用了一个随机产生user_agent的方法

import requests

from retrying import retry

import random

import datetime

class R:

def __init__(self,method="get",params=None,headers=None,cookies=None):

# do something

def get_headers(self):

user_agent_list = [ \

"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1" \

"Mozilla/5.0 (X11; CrOS i686 2268.111.0) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11", \

"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1092.0 Safari/536.6", \

"Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1090.0 Safari/536.6", \

"Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/19.77.34.5 Safari/537.1", \

"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.9 Safari/536.5", \

"Mozilla/5.0 (Windows NT 6.0) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.36 Safari/536.5", \

"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3", \

"Mozilla/5.0 (Windows NT 5.1) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3", \

"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_0) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3", \

"Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3", \

"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3", \

"Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3", \

"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3", \

"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3", \

"Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.0 Safari/536.3", \

"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.24 (KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24", \

"Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/535.24 (KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24"

]

UserAgent = random.choice(user_agent_list)

headers = {'User-Agent': UserAgent}

return headers

#other code

retrying 最简单的使用就是给你想不断重试的方法加上 装饰器 @retry

在这里,我希望网络请求模块尝试3次之后,在报错!

同时在R类初始化方法中增加一些必备的参数,你可以直接看下面的代码

__retrying_requests 方法为私有方法,其中根据get和post方式进行逻辑判断

import requests

from retrying import retry

import random

import datetime

class R:

def __init__(self,method="get",params=None,headers=None,cookies=None):

#do something

def get_headers(self):

# do something

@retry(stop_max_attempt_number=3)

def __retrying_requests(self,url):

if self.__method == "get":

response = requests.get(url,headers=self.__headers,cookies=self.__cookies,timeout=3)

else:

response = requests.post(url,params=self.__params,headers=self.__headers,cookies=self.__cookies,timeout=3)

return response.content

# other code

网络请求的方法已经声明完毕,并且返回 response.content 数据流

下面基于这个私有方法,增加一个获取网络文本的方法和一个获取网络文件的方法。同步完善类的初始化方法,在开发中发现,我们要爬取的网页编码是gb2312 所以还需要给某些方法增加一个编码参数

import requests

from retrying import retry

import random

import datetime

class R:

# 类的初始化方法

def __init__(self,method="get",params=None,headers=None,cookies=None):

self.__method = method

myheaders = self.get_headers()

if headers is not None:

myheaders.update(headers)

self.__headers = myheaders

self.__cookies = cookies

self.__params = params

def get_headers(self):

# do something

@retry(stop_max_attempt_number=3)

def __retrying_requests(self,url):

# do something

# get请求

def get_content(self,url,charset="utf-8"):

try:

html_str = self.__retrying_requests(url).decode(charset)

except:

html_str = None

return html_str

def get_file(self,file_url):

try:

file = self.__retrying_requests(file_url)

except:

file = None

return file

到此,这个R类已经被我们完善了,完整的代码,你应该从上面拼凑起来,你也可以直接翻到文章最后面,去github上直接查阅。

接下来,就是比较重要的爬虫代码部分了。这一次,我们可以简单的使用一下类和对象,并且加上简单的多线程操作。

首先,创建一个 ImageList 类,这个类第一件事情,需要获取我们爬取页面的总页码数目

这个步骤比较简单

获取网页源码

正则匹配末页元素

提取数字

import http_help as hh # 这个http_help 是我上面写到的那个R类

import re

import threading

import time

import os

import requests

# 获取所有待爬取的URL列表

class ImageList():

def __init__(self):

self.__start = "http://www.27270.com/ent/meinvtupian/list_11_{}.html" # URL模板

# 头文件

self.__headers = {"Referer":"http://www.27270.com/ent/meinvtupian/",

"Host":"www.27270.com"

}

self.__res = hh.R(headers=self.__headers) # 初始化访问请求

def run(self):

page_count = int(self.get_page_count())

if page_count==0:

return

urls = [self.__start.format(i) for i in range(1,page_count)]

return urls

# 正则表达式匹配末页,分析页码

def get_page_count(self):

# 注意这个地方需要传入编码

content = self.__res.get_content(self.__start.format("1"),"gb2312")

pattern = re.compile("

末页")

search_text = pattern.search(content)

if search_text is not None:

count = search_text.group(1)

return count

else:

return 0

if __name__ == '__main__':

img = ImageList()

urls = img.run()

上面的代码注意get_page_count方法,该方法已经获取到了末尾的页码

我们在run方法内部,通过一个列表生成器

urls = [self.__start.format(i) for i in range(1,page_count)]

批量把要爬取的所有链接都生成完毕。

分析上面爬取到的URL列表,捕获详情页

我们采用生产者和消费者模型,就是一个抓取链接图片,一个下载图片,采用多线程的方式进行操作,需要首先引入

import threading

import time

完整代码如下

import http_help as hh

import re

import threading

import time

import os

import requests

urls_lock = threading.Lock() #url操作锁

imgs_lock = threading.Lock() #图片操作锁

imgs_start_urls = []

class Product(threading.Thread):

# 类的初始化方法

def __init__(self,urls):

threading.Thread.__init__(self)

self.__urls = urls

self.__headers = {"Referer":"http://www.27270.com/ent/meinvtupian/",

"Host":"www.27270.com"

}

self.__res = hh.R(headers=self.__headers)

# 链接抓取失败之后重新加入urls列表中

def add_fail_url(self,url):

print("{}该URL抓取失败".format(url))

global urls_lock

if urls_lock.acquire():

self.__urls.insert(0, url)

urls_lock.release() # 解锁

# 线程主要方法

def run(self):

print("*"*100)

while True:

global urls_lock,imgs_start_urls

if len(self.__urls)>0:

if urls_lock.acquire(): # 锁定

last_url = self.__urls.pop() # 获取urls里面最后一个url,并且删除

urls_lock.release() # 解锁

print("正在操作{}".format(last_url))

content = self.__res.get_content(last_url,"gb2312") # 页面注意编码是gb2312其他格式报错

if content is not None:

html = self.get_page_list(content)

if len(html) == 0:

self.add_fail_url(last_url)

else:

if imgs_lock.acquire():

imgs_start_urls.extend(html) # 爬取到图片之后,把他放在待下载的图片列表里面

imgs_lock.release()

time.sleep(5)

else:

self.add_fail_url(last_url)

else:

print("所有链接已经运行完毕")

break

def get_page_list(self,content):

# 正则表达式

pattern = re.compile('

.*?')

list_page = re.findall(pattern, content)

return list_page

上述代码中比较重要的有

threading.Lock() 锁的使用,在多个线程之间操作全局变量,需要进行及时的锁定;

其他的注意内容,我已经添加在注释里面,只要你按着步骤一点点的写,并且加入一些自己微妙的理解,就可以搞定。

到现在为止,我们已经抓取到了所有的图片地址,我把他存放在了一个全局的变量里面 imgs_start_urls

那么现在又来了

这个列表里面存放的是 http://www.27270.com/ent/meinvtupian/2018/298392.html 这样的地址,当你打开这个页面之后,你会发现只有一张图片 ,并且下面有个分页。

点击分页之后,就知道规律了

http://www.27270.com/ent/meinvtupian/2018/298392.html

http://www.27270.com/ent/meinvtupian/2018/298392_2.html

http://www.27270.com/ent/meinvtupian/2018/298392_3.html

http://www.27270.com/ent/meinvtupian/2018/298392_4.html

....

当你进行多次尝试之后,你会发现,后面的链接完全可以靠拼接完成,如果没有这个页面,那么他会显示?

好了,如果你进行了上面的操作,你应该知道接下来怎么实现啦!

我把所有的代码,都直接贴在下面,还是用注释的方式给大家把最重要的地方标注出来

class Consumer(threading.Thread):

# 初始化

def __init__(self):

threading.Thread.__init__(self)

self.__headers = {"Referer": "http://www.27270.com/ent/meinvtupian/",

"Host": "www.27270.com"}

self.__res = hh.R(headers=self.__headers)

# 图片下载方法

def download_img(self,filder,img_down_url,filename):

file_path = "./downs/{}".format(filder)

# 判断目录是否存在,存在创建

if not os.path.exists(file_path):

os.mkdir(file_path) # 创建目录

if os.path.exists("./downs/{}/{}".format(filder,filename)):

return

else:

try:

# 这个地方host设置是个坑,因为图片为了防止盗链,存放在另一个服务器上面

img = requests.get(img_down_url,headers={"Host":"t2.hddhhn.com"},timeout=3)

except Exception as e:

print(e)

print("{}写入图片".format(img_down_url))

try:

# 图片写入不在赘述

with open("./downs/{}/{}".format(filder,filename),"wb+") as f:

f.write(img.content)

except Exception as e:

print(e)

return

def run(self):

while True:

global imgs_start_urls,imgs_lock

if len(imgs_start_urls)>0:

if imgs_lock.acquire(): # 锁定

img_url = imgs_start_urls[0] #获取到链接之后

del imgs_start_urls[0] # 删掉第0项

imgs_lock.release() # 解锁

else:

continue

# http://www.27270.com/ent/meinvtupian/2018/295631_1.html

#print("图片开始下载")

img_url = img_url[0]

start_index = 1

base_url = img_url[0:img_url.rindex(".")] # 字符串可以当成列表进行切片操作

while True:

img_url ="{}_{}.html".format(base_url,start_index) # url拼接

content = self.__res.get_content(img_url,charset="gbk") # 这个地方获取内容,采用了gbk编码

if content is not None:

pattern = re.compile('

[\s\S.]*?img alt="(.*?)".*? src="(.*?)" />')

# 匹配图片,匹配不到就代表本次操作已经完毕

img_down_url = pattern.search(content) # 获取到了图片地址

if img_down_url is not None:

filder = img_down_url.group(1)

img_down_url = img_down_url.group(2)

filename = img_down_url[img_down_url.rindex("/")+1:]

self.download_img(filder,img_down_url,filename) #下载图片

else:

print("-"*100)

print(content)

break # 终止循环体

else:

print("{}链接加载失败".format(img_url))

if imgs_lock.acquire(): # 锁定

imgs_start_urls.append(img_url)

imgs_lock.release() # 解锁

start_index+=1 # 上文描述中,这个地方需要不断进行+1操作

所有的代码都在上面了,关键的地方我尽量加上了标注,你可以细细的看一下,实在看不明白,就多敲几遍,因为没有特别复杂的地方,好多都是逻辑。

最后附上main部分的代码,让我们的代码跑起来

if __name__ == '__main__':

img = ImageList()

urls = img.run()

for i in range(1,2):

p = Product(urls)

p.start()

for i in range(1,2):

c = Consumer()

c.start()

一会过后,就慢慢收图吧

python爬虫爬图片教程_Python爬虫入门教程 5-100 27270图片爬取相关推荐

  1. python手机开发的软件_Python新手入门教程_在手机上就能学习编程的软件

    Python新手入门教程_在手机上就能学习编程的软件 很多小伙伴会问:我在学编程,想利用坐地铁坐公交吃饭间隙学编程,在手机上能学编程的软件有哪些?毕竟时间宝贵啊!!哈哈哈!!! 这个问题,在悟空回答的 ...

  2. python opencv 教程_python OpenCV 入门教程

    虽然python 很强大,而且也有自己的图像处理库PIL,但是相对于OpenCV 来讲,OpenCV更加强大, 可以做更多更复杂的应用,比如人脸识别等.跟很多开源软件一样OpenCV 也提供了完善的p ...

  3. 想学python都要下载什么软件-学编程闲余时间建议下载的软件_Python新手入门教程...

    原标题:学编程闲余时间建议下载的软件_Python新手入门教程 Python新手入门教程_在手机上就能学习编程的软件 很多小伙伴会问:我在学编程,想利用坐地铁坐公交吃饭间隙学编程,在手机上能学编程的软 ...

  4. Redis教程(一) Redis入门教程

    Redis教程(一) Redis入门教程 1 Redis入门教程 Redis是一个 Key-Value存储系统.和 Memcached类似,它支持存储的 value类型相对更多,包括 string(字 ...

  5. WMI 使用教程_.NET 入门教程

    WMI 使用教程_.NET 入门教程 先介绍一下WMI 相关知识:  什么是WMI 呢? Windows 管理规范 (Windows Management Instrumentation ),它的主要 ...

  6. Docker教程(一) Docker入门教程

    Docker教程(一) Docker入门教程 本文链接:https://blog.csdn.net/yuan_xw/article/details/51935278 Docker教程(一) Docke ...

  7. AFNnetworking快速教程,官方入门教程译

    AFNnetworking快速教程,官方入门教程译 分类: IOS2013-12-15 20:29 12489人阅读 评论(5) 收藏 举报 afnetworkingjsonios入门教程快速教程 A ...

  8. Kafka教程(一)Kafka入门教程

    Kafka教程(一)Kafka入门教程 1 Kafka入门教程 1.1 消息队列(Message Queue) Message Queue消息传送系统提供传送服务.消息传送依赖于大量支持组件,这些组件 ...

  9. Nginx教程(一) Nginx入门教程

    Nginx教程(一) Nginx入门教程 1 Nginx入门教程 Nginx是一款轻量级的Web服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,并在一个BSD-like协议下发行.由 ...

最新文章

  1. Ubuntu下搭建postgresql主从服务器(方法1)
  2. 中国高校4篇研究今日同时登上Nature!清华北大上交浙工大等在列
  3. 序列处理工具|Seqkit
  4. keras技巧——如何获取某一个网络层的输出
  5. 切换alwayson的时候失败
  6. Spring Cloud Spring Boot mybatis分布式微服务云架构(三)属性配置文件详解(1)
  7. servlet后台如何接受multpartfile_Servlet进阶教程(你不得不知道的Servlet知识点)
  8. ElementUI form表单 左侧label对齐注意事项
  9. string中删除一个元素
  10. HTTP缓存解释为何页面响应的数据和服务端的不一致
  11. activiti5.13 框架 数据库设计说明书
  12. 如何卸载zabbix且删除
  13. javaee utf-8文件的转换
  14. GPS、RTK、PPK三种定位技术的原理及应用
  15. python读取math_python调用通达信公式,python读取通达信公式结果
  16. arcgis海岸带_需科学划定海岸带基准地理边界
  17. MyBatis_查询缓存01
  18. 文件被占用无法删除,解决办法
  19. 使用YOLOv5实现单摄像头实时目标检测
  20. BASE64编码的图片在网页中直接用

热门文章

  1. centos7下安装gcc7
  2. 前端开发VScode常用插件
  3. spring与springMVC配置扫描的问题
  4. android开发 获取父控件的高宽
  5. 探索Android中的Parcel机制(上)
  6. 让PHP更快的提供文件下载
  7. 汇编程序开发环境搭配
  8. 数据流和十六进制转换
  9. Sublime text 3 汉化教程
  10. day16T2改错记