作业①:

1)单/多线程爬取网站图片实验

  要求:指定一个网站,爬取这个网站中的所有的所有图片,例如中国气象网http://www.weather.com.cn。分别使用单线程和多线程的方式爬取。

以下按自己的编码风格复现书本代码

  • 单线程

    程序主要思路:
graph TD
A(获取指定网页字符内容) -->B(从中筛选出所有图像url)
B --> C(逐一对图像url进行预处理:拼接,去重)
C --> D(逐一下载相应的图片到本地images子文件中)
D --> E(将下载的Url信息在控制台输出)

代码:

from bs4 import BeautifulSoup
from bs4 import UnicodeDammit
import urllib.request # 可换用requests
import os
import time
import warnings
warnings.filterwarnings("ignore") # 在控制台屏蔽警告 class ThreadSpiderImages(object):
'''单线程爬取指定网站图片类'''
def __init__(self,start_url):
'''共同属性是UA头以及url'''
self.url = start_url
self.headers = {
"User-Agent": "Mozilla/5.0"
} def get_html_text(self):
'''获取指定url的网页字符串'''
req = urllib.request.Request(self.url, headers=self.headers)
html = urllib.request.urlopen(req)
html_text = html.read()
dammit = UnicodeDammit(html_text, ["utf-8","gbk"]) # 猜测文档编码
html_text = dammit.unicode_markup
return html_text def extract_imageurls(self,images):
'''
从解析出的bs4ResultSet对象中提取图像url信息,
返回图像urls
'''
urls = []
for image in images:
try:
src = image["src"] # 图像文件的src地址
url = urllib.request.urljoin(self.url, src) # 构建完整url
if url not in urls: # url去重
urls.append(url)
print(url)
except Exception as err:
print(err)
return urls def download(self,urls):
'''下载urls中每个url对应的图像'''
count = 0
dirname = "images"
current_path = os.getcwd()
if not os.path.exists(dirname): # 如果文件夹不存在则创建
os.makedirs(dirname)
print("{}文件夹创建在{}".format(dirname, current_path)) try:
for url in urls:
pos = url[::-1].index(".") + 1 # 找到最后一个.在第几个位置(注意下标从0开始)
ext = url[-pos:] # 后缀名 # 将下载的图像文件存入当前文件夹下的images文件夹 filename = str(count) + ext
filepath = dirname + "\\" + filename
try:
urllib.request.urlretrieve(url, filepath)
except:
default_ext = '.jpg' # 将异常图片格式转化为默认格式.jpg
print("将{}图片格式转化为{}图片格式存储".format(ext,default_ext))
filename = str(count) + default_ext
filepath = dirname + "\\" + filename
urllib.request.urlretrieve(url, filepath) print("download "+filename)
count += 1 except Exception as err:
print(err) if __name__ == "__main__":
start = time.clock()
start_url = "http://www.weather.com.cn/weather/101280601.shtml" # 指定网站
spider = ThreadSpiderImages(start_url) try:
html_text = spider.get_html_text()
soup = BeautifulSoup(html_text, "html.parser")
images = soup.select("img") # 选择图像文件
urls = spider.extract_imageurls(images)
spider.download(urls) except Exception as err:
print(err) end = time.clock()
print('Running time: %s Seconds' % (end - start))

运行结果部分截图:





  • 多线程

    程序主要思路基本上同单线程,差别仅在于多线程中为每一个图像url创建线程对象,逐一以download函数为目标启动线程

    代码:
from bs4 import BeautifulSoup
from bs4 import UnicodeDammit
import urllib.request # 可换用requests
import os
import threading
import time
import warnings
warnings.filterwarnings("ignore") class ThreadsSpiderImages(object):
'''多线程爬取指定网站图片类'''
def __init__(self,start_url):
'''共同属性是UA头以及url'''
self.url = start_url
self.headers = {
"User-Agent": "Mozilla/5.0"
} def get_html_text(self):
'''获取指定url的网页字符串'''
req = urllib.request.Request(self.url, headers=self.headers)
html = urllib.request.urlopen(req)
html_text = html.read()
dammit = UnicodeDammit(html_text, ["utf-8","gbk"]) # 猜测文档编码
html_text = dammit.unicode_markup
return html_text def extract_imageurls(self,images):
'''
从解析出的bs4ResultSet对象中提取图像url信息,
返回图像urls
'''
urls = []
for image in images:
try:
src = image["src"] # 图像文件的src地址
url = urllib.request.urljoin(self.url, src) # 构建完整url
if url not in urls: # url去重
urls.append(url)
print(url)
except Exception as err:
print(err)
return urls def threads_download(self,urls):
'''根据图像urls启用多线程download'''
global count
try:
for url in urls:
count += 1 # 确保count不重,唯一的count操作
T = threading.Thread(target=self.download,args=(url,)) # 逐一(每个url)创建线程对象
T.setDaemon(False) # True则为守护线程,若设置守护线程,一旦主线程执行完毕,子线程都得结束
T.start() # 逐一启动线程
threads.append(T)
except Exception as err:
print(err) def download(self,url):
'''下载指定url对应的图像'''
dirname = "images"
if not os.path.exists(dirname): # 如果文件夹不存在则创建
os.makedirs(dirname)
current_path = os.getcwd()
print("{}文件夹创建在{}".format(dirname, current_path)) try:
pos = url[::-1].index(".") + 1 # 找到最后一个.在第几个位置(注意下标从0开始)
ext = url[-pos:] # 后缀名 # 将下载的图像文件存入当前文件夹下的images文件夹 filename = str(count) + ext
filepath = dirname + "\\" + filename
try:
urllib.request.urlretrieve(url, filepath)
except:
default_ext = '.jpg'
print("将{}图片格式转化为{}图片格式存储".format(ext,default_ext))
filename = str(count) + default_ext
filepath = dirname + "\\" + filename
urllib.request.urlretrieve(url, filepath) print("download "+filename) except Exception as err:
print(err) if __name__ == "__main__": start = time.clock()
start_url = "http://www.weather.com.cn/weather/101280601.shtml" # 指定网站
spider = ThreadsSpiderImages(start_url)
count = 0
threads = [] try:
html_text = spider.get_html_text()
soup = BeautifulSoup(html_text, "html.parser")
images = soup.select("img") # 选择图像文件
urls = spider.extract_imageurls(images)
spider.threads_download(urls)
for t in threads: # 主线程中等待所有子线程退出
t.join() except Exception as err:
print(err) end = time.clock()
print('Running time: %s Seconds' % (end - start))

运行结果:

基本与单线程运行结果一致,特殊之处在于运行时间“Running time”的大幅缩短以及由于多线程并发的不确定性导致下载的图片编号乱序





2)心得体会:

  这次实验关键在于多线程在IO密集型任务方面的应用。与单线程执行下载任务对比,可以体会到多线程爬取程序由于可以有多个文件在同时下载,互不干扰,效率和可靠性都明显比单线程爬取程序高。具体实现时主要使用threading模块。

作业②:

1)scrapy框架复现实现

  要求:使用scrapy框架复现作业①。

框架复现主要思路:

graph TD
A(在items模块确定要获取的数据项目item) -->B(在spider模块确定入口函数start_requests和回调/解析函数parse)
B --> C(在pipelines模块编写数据管道处理类处理item)
C --> D(设置配置文件settings.py)
D --> E(使用scrpy中专门的命令scrapy crawl执行爬虫程序)

代码:

  • items.py(数据项目类)
import scrapy

class ImageItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
image_url = scrapy.Field()
pass
  • SpiderImage.py(spiders文件夹下的爬虫程序)
import scrapy
from scrapy.selector import Selector
import warnings
warnings.filterwarnings("ignore")
import sys
sys.path.append("..") # 为导入上级目录中的模块
from items import ImageItem # items模块在上级目录中 class ScrapySpiderImages(scrapy.Spider):
'''爬取指定网站图像类'''
name = "threadsSpiderImages" # 唯一标识这个爬虫
allowed_domains = ["http://www.weather.com.cn"] # 允许爬虫的域名列表,若不定义,则不做限制
start_urls = ["http://www.weather.com.cn/weather/101280601.shtml"] # 开始爬虫的url列表,可用用start_requests()函数代替
# 设置settings中的值,优先级高于settings.py
custom_settings = {
# 下载延迟的秒数,用来限制访问的频率,默认为0,没有延时
'DOWNLOAD_DELAY': 0.3,
# 是否遵守robots协议,默认为True
'ROBOTSTXT_OBEY': False
} def parse(self,response): try:
html = response.body.decode() # 返回网页字符内容
selector = Selector(text=html) # 装载文档
images = selector.xpath("//img/@src").extract() # 获取所有图像文件url,以列表形式返回
threads = []
urls = []
for url in images:
if url not in urls:
urls.append(url)
item = ImageItem()
item["image_url"] = url
yield item except Exception as err:
print(err)
  • pipelines.py(数据管道处理类)
import os
import urllib class ThreadSpiderImagePipeline(object):
# 定义类变量,它的值将在这个类的所有实例之间共享
count = 0
dirname = "images" def process_item(self, item, spider): if not os.path.exists(ThreadSpiderImagePipeline.dirname): # 如果文件夹不存在则创建
os.makedirs(ThreadSpiderImagePipeline.dirname)
current_path = os.getcwd()
print("{}文件夹创建在{}".format(ThreadSpiderImagePipeline.dirname, current_path)) ThreadSpiderImagePipeline.count += 1 try:
image_url = item["image_url"]
print(image_url) # 在控制台输出url信息
pos = image_url[::-1].index(".") + 1 # 找到最后一个.在第几个位置(注意下标从0开始)
ext = image_url[-pos:] # 后缀名 filename = str(ThreadSpiderImagePipeline.count) + ext
filepath = ThreadSpiderImagePipeline.dirname + "\\" + filename try:
urllib.request.urlretrieve(image_url, filepath)
except:
default_ext = '.jpg'
print("将{}图片格式转化为{}图片格式存储".format(ext, default_ext))
filename = str(ThreadSpiderImagePipeline.count) + default_ext
filepath = ThreadSpiderImagePipeline.dirname + "\\" + filename
urllib.request.urlretrieve(image_url, filepath) except Exception as err:
print(err) return item
  • settings.py(配置文件)
BOT_NAME = 'ThreadSpiderImage'
SPIDER_MODULES = ['ThreadSpiderImage.spiders']
NEWSPIDER_MODULE = 'ThreadSpiderImage.spiders'
ROBOTSTXT_OBEY = True
CONCURRENT_ITEMS = 100
CONCURRENT_REQUESTS = 50 # 由Scrapy下载器执行的并发(即同时)请求的最大数量
DEFAULT_REQUEST_HEADERS = {
'User-Agent':"Mozilla/5.0",
}
ITEM_PIPELINES = {
'ThreadSpiderImage.pipelines.ThreadSpiderImagePipeline': 300, # 数值一般0-1000,数值越小优先级越高
}
  • run.py(执行爬虫程序)
from scrapy import cmdline

command = "scrapy crawl threadsSpiderImages -s LOG_ENABLED=False"
cmdline.execute(command.split())

由于只是用scrapy框架复现作业①代码,所以运行结果基本同作业①(没有打印运行时间和下载的图片名称)

  但试着使用了一下threading模块,发现速度还是提升了不少。

由于scrapy是异步执行框架,自己只编写了spiders文件夹下的ThreadSpider.py文件,其余模块(items,pipelines,settings)采用默认配置,name与上述代码一致,但由于两份代码不在同一项目中所以没有影响。

  • ThreadSpider.py(spiders文件夹下)
import scrapy
from scrapy.selector import Selector
import urllib
import os
import threading
import time
import warnings
warnings.filterwarnings("ignore") class ScrapySpiderImages(scrapy.Spider):
'''多线程爬取指定网站图片'''
name = "threadsSpiderImages"
allowed_domains = ["http://www.weather.com.cn"] # 允许爬虫的域名列表,若不定义,则不做限制
start_urls = ["http://www.weather.com.cn/weather/101280601.shtml"] # 开始爬虫的url列表,可用用start_requests()函数代替
# 设置settings中的值,优先级高于settings.py
custom_settings = {
# 下载延迟的秒数,用来限制访问的频率,默认为0,没有延时
'DOWNLOAD_DELAY': 0.3,
# 是否遵守robots协议,默认为True
'ROBOTSTXT_OBEY': False
} def parse(self,response):
'''回调函数'''
global count
global threads
count = 0
threads = []
start = time.clock() try:
html = response.body.decode() # 返回网页字符内容
selector = Selector(text=html) # 装载文档
images = selector.xpath("//img/@src").extract() # 获取所有图像文件url,以列表形式返回
urls = self.pretreat_imageurls(images)
self.threads_download(urls)
for t in threads: # 主线程中等待所有子线程退出
t.join()
except Exception as err:
print(err) end = time.clock()
print('Running time: %s Seconds' % (end - start)) def pretreat_imageurls(self,images):
'''从解析出的bs4ResultSet对象中提取图像url信息'''
urls = []
for url in images:
try:
if url not in urls: # url去重
urls.append(url)
print(url)
except Exception as err:
print(err)
return urls def threads_download(self,urls):
'''根据图像urls启用多线程download'''
global count
try:
for url in urls:
count += 1 # 确保count不重,唯一的count操作
T = threading.Thread(target=self.download,args=(url,)) # 逐一(每个url)创建线程对象
T.setDaemon(False) # True则为守护线程,若设置守护线程,一旦主线程执行完毕,子线程都得结束
T.start() # 逐一启动线程
threads.append(T)
except Exception as err:
print(err) def download(self, url):
'''下载指定url对应的图像'''
dirname = "images"
if not os.path.exists(dirname): # 如果文件夹不存在则创建
os.makedirs(dirname)
current_path = os.getcwd()
print("{}文件夹创建在{}".format(dirname, current_path)) try:
pos = url[::-1].index(".") + 1 # 找到最后一个.在第几个位置(注意下标从0开始)
ext = url[-pos:] # 后缀名 # 将下载的图像文件存入当前文件夹下的images文件夹 filename = str(count) + ext
filepath = dirname + "\\" + filename
try:
urllib.request.urlretrieve(url, filepath)
except:
default_ext = '.jpg'
print("将{}图片格式转化为{}图片格式存储".format(ext, default_ext))
filename = str(count) + default_ext
filepath = dirname + "\\" + filename
urllib.request.urlretrieve(url, filepath) print("download " + filename) except Exception as err:
print(err)
  • run.py(执行爬虫程序)
from scrapy import cmdline

command = "scrapy crawl threadsSpiderImages -s LOG_ENABLED=False"
cmdline.execute(command.split())

运行结果部分截图:(其余部分与作业①中多线程结果基本相同)

可以看出scapy框架+多线程爬取图片的运行效率比单纯的scapy框架以及不在scapy框架下实现的多线程明显要更高,由此对“scrapy是多线程的,不需要再设置了”的说法表示怀疑。

2)心得体会:

  本次实验重点在于对scrapy整体框架的理解和把握。scrapy是一个快速、功能强大的爬虫框架,而非函数功能库。程序入口为spiders,出口为ItemPipeline。引用一张表格帮助理解scrapy整体框架。



总的来说自己利用scrapy框架编写爬虫的整体过程是:1、确定起始url作为函数入口。2、确定要编写数据项目类items。3、在spiders下的爬虫程序中导入设计好数据项目类,在parse方法中进行获取。4、编写数据管道处理类,处理爬虫程序推送过来的item对象。5、使用scrapy中专门命令scrapy crawl执行爬虫程序。(注:创建scrapy项目是采用命令“scrapy startproject projectname”的形式)

作业③

1)scrapy框架爬取股票信息实验

  要求:使用scrapy框架爬取股票相关信息。

候选网站:东方财富网:https://www.eastmoney.com/

​ 新浪股票:http://finance.sina.com.cn/stock/

(这里选择东方财富网)

  程序主要思路:

graph TD
A(根据设计好的url模板生成指定板块多页的urls列表作为入口) -->B(将存储每页股票信息的列表对象作为要获取的数据项目item)
B --> C(设计回调函数parse使其获取并返回上述item)
C --> D(编写数据管道处理类中的process_item函数格式化展示item数据并存储)
D --> E(配置项目对应的settings.py文件)

代码:

  • items.py(数据项目类)
import scrapy

class StockItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
infos = scrapy.Field()
pass
  • ScapyStockSpider.py(spiders文件夹下的爬虫程序)
import scrapy
import re
import sys
sys.path.append("..") # 为导入上级目录中的模块
from items import StockItem # items模块在上级目录中 class ScrapySpiderImages(scrapy.Spider):
name = "scapySpiderStock" def start_requests(self):
urls = ["http://5.push2.eastmoney.com/api/qt/clist/get?pn={0:d}&pz=20&po=1&np=1\
&fltt=2&invt=2&fid=f3&fs={1}&fields=f2,f3,f4,f5,f6,f7,f12,f14,f15,f16,f17,f18"\
.format(page,self.get_fs("沪深A股")) for page in range(1,6)] # 指定爬取板块为沪深A股,循环爬取前五页
# return [scrapy.Request(url=url,callback=self.parse) for url in urls]
for url in urls:
yield scrapy.Request(url=url,callback=self.parse) # 效率考量 def parse(self,response):
html = response.body.decode()
info = self.extract_infos(html)
item = StockItem(infos=info)
yield item def get_fs(self,name):
'''根据板块名称返回板块部分代码号'''
fs_type = {
"沪深A股": "m:0+t:6,m:0+t:13,m:0+t:80,m:1+t:2,m:1+t:23",
"上证A股": "m:1+t:2,m:1+t:23",
"深证A股": "m:0+t:6,m:0+t:13,m:0+t:80"
} # 东方财富网行情中心的板块变化体现在fs字段,通过f12抓包可得以上编码,其余板块依此类推
return fs_type[name] def extract_infos(self,html):
'''从所有网页字符内容中提取所需信息范围,返回列表类型,元素为字典'''
pattern = "\[(.*?)\]"
infos = re.compile(pattern,re.S).findall(html)[0] # 所有信息一次被匹配,findall方法返回的列表中有且只有一个字符串元素
return list(eval(infos)) # eval返回该字符串所代表的python对象(元组),为便于后续操作再将元组转化为列表
  • pipelines.py(数据管道处理类)
from itemadapter import ItemAdapter
from prettytable import PrettyTable
from wcwidth import wcswidth
from openpyxl import Workbook class StockPipeline:
num = 1 # num为序号
dic = {
"股票代码": 'f12', "股票名称": 'f14', "最新报价": 'f2', "涨跌幅": 'f3',
"涨跌额": 'f4', "成交量": 'f5', "成交额": 'f6', "振幅": 'f7',
"最高": 'f15', "最低": 'f16', "今开": 'f17', "昨收": 'f18'
} # json网页中的字典键值对应含义
titles = ["序号", "股票代码", "股票名称", "最新报价", "涨跌幅", "涨跌额",
"成交量", "成交额", "振幅", "最高", "最低", "今开", "昨收"]
wb = Workbook()
ws = wb.active
save_path = 'stock.xlsx' def process_item(self, item, spider):
infos = item['infos']
datas = self.get_datas(infos)
for data in datas: # datas是generator的可循环对象
self.show_data(data) # 格式化展示数据
if data[0] == 1:
StockPipeline.ws.append(StockPipeline.titles)
StockPipeline.ws.append(data)
StockPipeline.wb.save(StockPipeline.save_path)
return item def get_datas(self,infos):
'''从单页所需信息范围中提取数据存为列表'''
for info in infos: # infos为列表,info为字典
info = self.format_data(info)
data = [StockPipeline.num] # 初始化为序号
StockPipeline.num += 1 # 序号递增
for value in StockPipeline.dic.values(): # 顺序存入列表
data.append(info[value])
yield data # 等待调用循环抽取 def format_data(self,info):
'''将不符合题目格式的原始量格式化'''
# pending_format = ["涨跌幅","成交量","成交额"]
try: # 实际运行过程可能会出现数据缺失的情况
info[StockPipeline.dic["涨跌幅"]] = str(info[StockPipeline.dic["涨跌幅"]]) + "%" # 更改为百分数形式
info[StockPipeline.dic["成交量"]] = str('%.2f' %(info[StockPipeline.dic["成交量"]]/1e4))+ "万" # 保留两位小数+单位
info[StockPipeline.dic["成交额"]] = str('%.1f' %(info[StockPipeline.dic["成交额"]]/1e8))+ "亿" # 保留一位小数+单位
except:
print("相应数据缺失")
finally:
return info # def show_data(self,data,shownum=20):
# '''展现结果,格式化输出所提取的数据'''
# StockPipeline.pt.add_row(data)
# if StockPipeline.num == shownum:
# print(StockPipeline.pt) def show_data(self,data):
if data[0] == 1: # 第一次打印标题
pat = "{0:^2}\t{1:^7}\t{2:^7}\t{3:^7}\t{4:^7}\t{5:^7}\t{6:^7}\t{7:^7}\t{8:^7}\t{9:^7}\t{10:^7}\t{11:^7}\t{12:^7}"
titles = StockPipeline.titles
print(pat.format(titles[0],titles[1],titles[2],titles[3],titles[4],titles[5],\
titles[6],titles[7],titles[8],titles[9],titles[10],titles[11],titles[12])) pat = "{0:^3}\t{1:^8}\t{2:^8}\t{3:^8}\t{4:^8}\t{5:^8}\t{6:^8}\t{7:^8}\t{8:^8}\t{9:^8}\t{10:^8}\t{11:^8}\t{12:^8}"
print(pat.format(data[0], data[1], data[2], data[3], data[4], data[5], \
data[6], data[7], data[8], data[9], data[10], data[11], data[12]))
  • settings.py(配置文件)
BOT_NAME = 'stock'
SPIDER_MODULES = ['stock.spiders']
NEWSPIDER_MODULE = 'stock.spiders'
ROBOTSTXT_OBEY = False
ITEM_PIPELINES = {
'stock.pipelines.StockPipeline': 300,
}
DEFAULT_REQUEST_HEADERS = {
'User-Agent':"Mozilla/5.0",
}
  • run.py(执行爬虫程序)
from scrapy import cmdline

command = "scrapy crawl scapySpiderStock -s LOG_ENABLED=False"
cmdline.execute(command.split())

运行结果部分截图:

控制台输出

excel保存

2)心得体会:

  这次实验重点依然是scrapy框架的使用。我学会了如何编写scrapy框架的各个模块使其相互配合来完成任务。以及如何在pipelines模块中进行规范的数据展示以及数据存储(excel存储可利用openpyxl中的Workbook)。

但在使用scrapy框架的过程中其实也有以下疑惑:

1、scrapy框架中的parse_item方法和process_item方法都可以用来处理数据,那么应该选取什么样的策略在两个方法中分配数据处理的工作量?是单纯让parse_items尽可能少做数据处理还是说尽可能均衡工作量?

2、scrapy框架中多线程到底是如何实现的?我在作业②中实现多线程的方法是否规范?

网络爬虫第三次作业——多线程、scrapy框架的更多相关文章

  1. python 全栈开发,Day137(爬虫系列之第4章-scrapy框架)

    一.scrapy框架简介 1. 介绍 Scrapy一个开源和协作的框架,其最初是为了页面抓取 (更确切来说, 网络抓取 )所设计的,使用它可以以快速.简单.可扩展的方式从网站中提取所需的数据.但目前S ...

  2. [Python]网络爬虫(三):异常的处理和HTTP状态码的分类

    先来说一说HTTP的异常处理问题. 当urlopen不能够处理一个response时,产生urlError. 不过通常的Python APIs异常如ValueError,TypeError等也会同时产 ...

  3. Python网络爬虫第三弹《爬取get请求的页面数据》

    一.urllib库 urllib是Python自带的一个用于爬虫的库,其主要作用就是可以通过代码模拟浏览器发送请求.其常被用到的子模块在Python3中的为urllib.request和urllib. ...

  4. Python网络爬虫实战(三)照片定位与B站弹幕

    之前两篇已经说完了如何爬取网页以及如何解析其中的数据,那么今天我们就可以开始第一次实战了. 这篇实战包含两个内容. * 利用爬虫调用Api来解析照片的拍摄位置 * 利用爬虫爬取Bilibili视频中的 ...

  5. python网络爬虫第三弹(<爬取get请求的页面数据>)

    一.urllib库 urllib是python自带的一个用于爬虫的库,其主要作用就是通过代码模拟浏览器发送请求,其常被用到的子模块在 python3中的为urllib.request 和 urllib ...

  6. python网络爬虫(三)requests库的13个控制访问参数及简单案例

    酱酱~小编又来啦~

  7. 【网络爬虫】【python】网络爬虫(三):模拟登录——伪装浏览器登录爬取过程

    一.关于抓包分析和debug Log信息 模拟登录访问需要设置request header信息,对于这个没有概念的朋友可以参见本系列前面的java版爬虫中提到的模拟登录过程,主要就是添加请求头requ ...

  8. python 网络爬虫(三)

    一.网站地图爬虫 在一个简单的爬虫中,我们将使用实例网站 robots.txt 文件中发现的网站地图来下载所有网站,为了解析网站地图,我们将会使用一个简单的正则表达式,从<loc>标签中提 ...

  9. Python爬虫从入门到放弃 之 Scrapy框架中Download Middleware用法

    这篇文章中写了常用的下载中间件的用法和例子.Downloader Middleware处理的过程主要在调度器发送requests请求的时候以及网页将response结果返回给spiders的时候,所以 ...

随机推荐

  1. Spring及tomcat初始化日志

    Tomcat StandardContext初始化过程 //org.apache.catalina.core.StandardContext#startInternal // 子容器启动 for (C ...

  2. 使用koa-log4管理nodeJs日志笔记

    前言 对于后端程序应用来说,日志是必不可少的,在nodeJs当中并没有自带的日志模块.最近正好使用koa框架来做后端服务,需要对日志进行分割处理,特记录下分享给大家. 一.后端代码目录结构 ├── b ...

  3. LeetCode刷题总结-数学篇

    本文总结LeetCode上有数学类的算法题,推荐刷题总数为40道.具体考点分析如下图: 1.基本运算问题 题号:29. 两数相除,难度中等 题号:166. 分数到小数,难度中等 题号:372. 超级次 ...

  4. 2020.09.05【NOIP提高组&普及组】模拟赛C组1总结

    T1:机器翻译 这一道题是一个很简单的队列题目,我们只要每次维护队列元素数量保持在m以内即可 T2:乌龟棋 这一道题我一开始比赛是暴力枚举(万事先暴力),很明显这个肯定会超时(30分)那么考虑动态规划 ...

  5. 008 01 Android 零基础入门 01 Java基础语法 02 Java常量与变量 02 Java 中的关键字

    008 01 Android 零基础入门 01 Java基础语法 02 Java常量与变量 02 Java 中的关键字 关键字 关键字就是一些有特殊意义的词 之前学习的程序中涉及到的关键字 Java中 ...

  6. 2-K8S常用命令

    kubectl 命令行管理工具 类型 命令 描述 基础命令 create 通过文件名或标准输入创建资源 expose 为Deployment,Pod创建service run 在集群中运行一个特定的镜 ...

  7. Hello World背后的事情

    Hello World是不少人学习C++的第一项内容,代码看似简单,很多东西却涉及根本 #include <iostream> using namespace std; int main( ...

  8. background-size 详解

    backgroun-size:cover; .是按照等比缩放铺满整个区域.主要用于图片比div小的时候,将图片按照某一边的比例扩大以填充整个div背景. .优点:图片不会被拉升,且实用于div长度和宽 ...

  9. day26 Pyhton select功能语句实现

    一.查询语句功能实现 select id,name where age > '20' name_value = {'id':0,'name':1,'age':2,'phone':3,'job': ...

  10. ansible2.9.5使用become参数实现sudo功能

    一,为什么要使用sudo? 1, 生产环境中,为了安全因素,我们不会直接使用root来登录到server, 确实有需要的情况下,我们再使用sudo切换到root权限. 所以很多ansible的演示直接 ...