赞
踩
封装到一起用的时候调用就可以了,很方便。
def self_options(): op = webdriver.ChromeOptions() # 1. 设置selenium不自动关闭浏览器 op.add_experimental_option("detach", True) # 2. 不加载网页图片,提升网页加载速度 op.add_argument('blink-settings=imagesEnabled=false') # 3. 避免终端下执行代码报错 op.add_experimental_option("excludeSwitches", ['enable-automation', 'enable-logging']) # 4. 为selenium设置请求头UA,selenium调用的浏览器自带UA,但是因为存在UA反爬,所以可以选择性是否添加 UA = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36' op.add_argument(f"--user-agent={UA}") # 5. 设置代理IP # proxy_ip = '127.0.0.1:8000' # op.add_argument(f'--proxy-server=http://{proxy_ip}') # 6. 加载拓展插件 op.add_extension('./FeHelper.crx') # 7. 加载用户缓存,可以记录使用记录和cookie,如果不指定缓存路径,会自动创建临时文件夹。 # user_dir = r'./browser_cache' # op.add_argument(f"--user-data-dir={user_dir}") # 8. 无头浏览器:提升网页访问速度,但是牺牲的是增加更多的反爬风险,如果涉及到与网页的交互,有些网站就不能使用无头模式。 op.add_argument('--headless') return op
如果窗口过小,会导致selenium无法实现下一步的操作,页面上不显示,自然就无法找到对应的位置进行交互,会返回element click intercepted
element click intercepted:有些网站有检测机制,页面元素未显示在用户视野中(网页显示区域)时,元素不允许进行交互。
browser.maximize_window():窗口最大化
蜜罐:形容抵不住诱惑,之前在学习网安的时候了解到过。爬虫蜜罐即爬虫陷阱。
一、概述
一个接入了互联网的网站,只要能和外部产生通信,就有可能被黑客攻击。所以有些网站设置了一些陷阱,来引诱攻击者从而达到自身不被攻击的目的。
二、蜜罐分类
电子邮件蜜罐:邮箱管理者会在网络中故意放出一些邮箱账号,这些账号只能被扫描器发现,正常人发现不了,所以如果这些账号接收到邮件,就可以将发件地址标记为恶意账号。
数据库蜜罐:用来监控攻击者对数据库的攻击命令或发现利用sql注入攻击,运营人员就可以将访问数据区的ip地址拉黑。
爬虫蜜罐:例如:在网页源码中注释掉一些链接,这些链接普通用户永远不会看到,但是写爬虫的人能看到,爬虫能访问到,如果有爬虫访问了这些注释掉的陷阱链接,立刻能够检测到是哪个ip地址访问了,直接将此ip拉黑。
三、蜜罐的优缺点
优点:节省资源、能够轻易捕捉到危险、准确率高。
缺点:准确率高不等于100%,有误封的缺点。
一、scrapy爬虫框架介绍
scrapy是基于python开发的爬虫框架,用于从网站中抓取数据。python爬虫领域中scrapy是最强悍的框架。该框架提供了非常多的爬虫相关的基础组件,建构清晰,可拓展性强。
二、scrapy爬虫框架出现的条件
每次写爬虫都需要写一遍重复性的内容,scrapy作者就根据重复性的内容封装成通用的代码,通过多版本迭代,住家形成规模庞大的框架。
三、安装
pip install scrapy
四、创建scrapy爬虫项目
命令:scrapy startproject 项目名
创建中国新闻网爬虫项目:scrapy startproject ChinaNews
创建完是这样式儿的:
后面会对上面的文件展开操作
五、开始操作
先使用cd命令切换进项目,通过命令初始化某个网站的爬虫文件
scrapy genspider 文件名(运行scrapy项目时的名字)被爬取网站的链接
scrapy genspider NewsSpider https://www.chinanews.com.cn/
六、scrapy爬虫项目的运行
scrapy crawl 爬虫名字
scrapy crawl NewsSpider
七、settings.py(很重要)
这是scrapy的配置文件,需要修改成不遵循robots协议:ROBOTSTXT_OBEY = False
八、多线程(默认16线程):
一、在NewsSpider.py文件内写爬虫代码
import scrapy from ..items import ChinanewsItem class NewsspiderSpider(scrapy.Spider): name = "NewsSpider" allowed_domains = ["www.chinanews.com.cn"] start_urls = ["https://www.chinanews.com.cn/"] def parse(self, response): # response:网页的响应结果 # 查看网页源代码 # print(response.text) # css方法:scrapy提供了css方法能够使用css选择器定位到元素 # 如果要取标签属性,需要在css方法的css选择器中这样写 --> 标签::attr(属性名) # get():获取到css选择器指定的内容 link = response.css('body > div:nth-child(9) > div.news-right > div.top-jsxw > div.jsxw-title.lmtitle > a::attr(href)').get() # print(link) # 将链接补全 new_link = self.start_urls[0] + link[1:] # print(new_link) # 构建10页链接 for page in range(1, 11): page_link = new_link.replace('1', str(page)) # print(page_link) # scrapy.Request():scrapy中负责请求链接的方法 # callback:回调函数,可以提前调用一个不存在的函数、变量等,然后紧接着再去创建。 yield scrapy.Request(url=page_link, callback=self.NewsInfo) # Xpath写法 def NewsInfo(self, response): # 实例化实体类 newsItem = ChinanewsItem() # 此时response根节点时html li_list = response.xpath('/html/body/div[4]/div[1]/div[2]/ul/li') for i in li_list: if i.xpath('./@class').get() != 'nocontent': news_type = i.xpath('./div[1]/a/text()').get() news_title = i.xpath('./div[2]/a/text()').get() news_link = 'https://www.chinanews.com.cn' + i.xpath('./div[2]/a/@href').get() news_time = i.xpath('./div[3]/text()').get() # print(news_type, news_title, news_link, news_time) newsItem['NewsType'] = news_type newsItem['NewsTitle'] = news_title newsItem['NewsLink'] = news_link newsItem['NewsTime'] = news_time yield newsItem
还有CSS写法,不过我不太喜欢CSS,看起来代码太臃肿。
# CSS选择器写法 def NewsInfo(self, response): # 从响应结果中查看访问的是哪个链接 # print(response.url) # 获取当前页面的所有新闻的li标签 li_list = response.css('body > div.w1280.mt20 > div.content-left > div.content_list > ul > li') # print(li_list) for i in li_list: # 如果要取标签内容,需要在css方法的css选择器中这样写 --> 标签::text news_type = i.css('li > div.dd_lm > a::text').get() # 如果li的class属性为nocontent,即值为空,则去掉此li标签 if news_type != None: news_title = i.css('li > div.dd_bt > a::text').get() news_link = 'https://www.chinanews.com.cn' + i.css('li > div.dd_bt > a::attr(href)').get() news_time = i.css('li > div.dd_time::text').get() print(news_type, news_title, news_link, news_time) newsItem['NewsType'] = news_type newsItem['NewsTitle'] = news_title newsItem['NewsLink'] = news_link newsItem['NewsTime'] = news_time yield newsItem
二、在items.py文件内实体化
import scrapy class ChinanewsItem(scrapy.Item): # define the fields for your item here like: # name = scrapy.Field() # 此处写什么代码取决于你提取了哪些信息 NewsType = scrapy.Field() NewsTitle = scrapy.Field() NewsLink = scrapy.Field() NewsTime = scrapy.Field() # Field()是获取scrapy提供的Item类(实体类)中的信息 # 爬虫主要目标就是从非结构化数据源中提取出结构化的数据 # 结构化数据一般是一个字段对应一个或一类数据,这种情况下字典是最好用的 # 但是字典很容易将键的名字写错,此时scrapy的Item类起作用了,Item类本身就是处理结构化数据的 # 将字段名化为变量名使用,就不会出错了。
三、数据存储,在piplines.py内操作
import csv # scrapy 的数据存储有两种形式 # 方式一:直接使用命令存储文件 # scrapy crawl 爬虫名字 -o 文件名.拓展名 # 或者 scrapy crawl 爬虫名字 --output 文件名.拓展名 # 使用命令的形式存储数据,拓展名支持8种类型的文件 # json、jsonlines、jsonl、jl、csv、xml、marshal、pickel(python 高性能文件) # scrapy crawl NewsSpider -o data.csv # 方式二:手写代码实现数据的存储 # 注意:管道中的代码想要执行,必须告知scrapy,我添加了什么代码 class ChinanewsPipeline: def process_item(self, item, spider): return item class ChinanewsToCsvPipline: def open_spider(self, spider): """当爬虫开始执行时,open_spider被执行""" self.file = open('数据.csv', 'w', encoding='utf-8', newline='') csv.writer(self.file).writerow(['新闻类型', '新闻标题', '新闻链接', '发布时间']) def process_item(self, item, spider): """爬虫执行过程中执行的代码""" data = [item['NewsType'], item['NewsTitle'], item['NewsLink'], item['NewsTime']] csv.writer(self.file).writerow(data) return item def close_spider(self, spider): """当爬虫结束执行时,close_spider被执行""" self.file.close()
管道中的代码想要执行,必须告知scrapy,我添加了什么代码,在settings.py中操作
# 字典中的键是管道中需要执行的代码,对应的数值是执行的先后顺序,范围[0, 1000]
# 数值越小,优先级越高
ITEM_PIPELINES = {
# "ChinaNews.pipelines.ChinanewsPipeline": 300,
"ChinaNews.pipelines.ChinanewsToCsvPipline": 300,
}
在middlewares.py文件中操作,添加如下类
class ChinanewsUserAgentDownloaderMiddleware: def __init__(self): file = open('UserAgent.txt', 'r') self.UAList = ast.literal_eval(file.read()) @classmethod def from_crawler(cls, crawler): """在爬虫开始或结束时进行一些操作的函数""" # This method is used by Scrapy to create your spiders. s = cls() crawler.signals.connect(s.spider_opened, signal=signals.spider_opened) return s def process_request(self, request, spider): """下载器发送请求前针对请求的处理""" # 将一个UA放入到请求的headers中 request.headers['User-Agent'] = random.choice(self.UAList) return None def process_response(self, request, response, spider): """下载器请求完页面,和引擎通信时对响应结果做的处理""" return response def process_exception(self, request, exception, spider): """如果出现异常,怎么处理""" pass def spider_opened(self, spider): """日志信息处理""" spider.logger.info("Spider opened: %s" % spider.name)
同样需要告诉scrapy我添加了什么代码
DOWNLOADER_MIDDLEWARES = {
# "ChinaNews.middlewares.ChinanewsDownloaderMiddleware": 543,
"ChinaNews.middlewares.ChinanewsUserAgentDownloaderMiddleware": 100,
}
这玩意儿是真有点抽象,要完全理解需要时间的,不过我觉得现在刚刚起步,不着急理解的,先依葫芦画瓢当个工具使用就就可以,毕竟用工具的时候不会有人会去完全弄清楚原理吧哈哈。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。