logging 内定义的优先级为 CRITICAL > ERROR > WARNING > INFO > DEBUG > NOTSET

简单来说,根 logger 的优先级为“保底”

对于任何 handler ,如果其优先级高于根 logger,则按照 handler 的优先级显示日志

如果其优先级低于根 logger,则按照根 logger 的优先级显示日志

有如下代码:

import logging

format = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("test logger") # 根 logger

fhandler = logging.FileHandler("log.txt")
fhandler.setLevel(logging.DEBUG)
fhandler.setFormatter(format)

shandler = logging.StreamHandler()
shandler.setLevel(logging.WARNING)
shandler.setFormatter(format)

logger.propagate = False

logger.addHandler(fhandler)
logger.addHandler(shandler)

logger.debug("debug")
logger.info("info")
logger.warning("warning")
logger.error("error")
logger.critical("critical")


其运行结果为

文件日志的 handler 日志级别为 DEBUG,比根 logger 的级别 INFO 低,文件日志输出到 INFO 级别,没有输出到 DEBUG 级别

控制台日志的 handler 日志级别为 WARNING,比根 logger 的级别 INFO 高,控制台日志输出到 WARNING 级别,没有输出到 INFO 级别

昨天用 dotnet core 把在 python 下实现的爬虫重写了一遍,体验很好( Linq + HtmlAgilityPack + ScrapySharp ),做一些零碎的记录

轮子的选择

以下涉及到的库均可以使用 Nuget 安装

HTML 爬取库

如果遇到没有 DDOS 防护的静态页面,在 python 下用 urllib 库发送请求即可获取网页代码

// ...
req = request.Request(url, headers=HEAD)
response = request.urlopen(req)
html = response.read().decode('utf-8')
// ...

在 dotnet 下同样可以使用自带的 WebClient、WebRequest 实现,但既然使用了 ScrapySharp 这个解析库(原因见下文),这里也可以使用 ScrapySharp 自带的 Web Client 实现

using ScrapySharp.Network;
// ...
var browser = new ScrapingBrowser();
WebPage page = browser.NavigateToPage(new Uri("your url here"));
var html = page.Content;
// ...

除此之外,python 下万能的浏览器自动化工具 selenium 也同样支持 dotnet core,区别在于一些 Options 的添加

在 python 下(使用 Chrome)

chrome_options = Options()
chrome_options.add_argument('--no-sandbox')
chrome_options.add_argument('--disable-dev-shm-usage')
prefs = {'profile.managed_default_content_settings.images': 2} # 不加载图片
chrome_options.add_experimental_option('prefs', prefs)
browser = webdriver.Chrome(options=chrome_options)

在 dotnet core 下,同样的打开方式变成了

var chromeOptions = new ChromeOptions();
chromeOptions.AddArgument("--no-sandbox");
chromeOptions.AddArgument("--disable-dev-shm-usage");
chromeOptions.AddUserProfilePreference("profile.managed_default_content_settings.images", 2); //这里
var mychrome = new ChromeDriver(chromeOptions);

HTML 解析库

对于 python 下常用的 html 解析库 BeautifulSoup4,在 dotnet core 下我选择了 HtmlAgilityPack

在 python 下,我通常使用以下方法将获取到的 html 源代码解析为 lxml (或其他)格式

# ...
soup = BeautifulSoup(html, 'lxml')
# ...

现在在 dotnet core 下,变成了

using HtmlAgilityPack;

// ...
var htmlDoc = new HtmlDocument();
htmlDoc.LoadHtml(html);
///
htmlDoc.Load("/your/path/here/pageSource.html");
从文件中加载
///
// ...

HAP 默认使用 XPath 语法(在 XML 文档中查找信息的语言),且暂不支持 CSS 选择器

例如在 python 中,我通常以下面的手法筛选信息

# ...
result = soup.select("div.xxxclass")
# ...

因为懒得学习 XPath想尽快尝试 dotnet core 的爬虫,ScrapySharp 出现了,此框架是对 HtmlAgilityPack 的一次扩展,添加了其缺少的 CSS 选择器,并且自带一个 Web Client 用来获取网页代码

安装之后就可以使用 CssSelect 方法筛选网页代码

using ScrapySharp.Extensions;
// ...
var result = htmlDoc.DocumentNode.CssSelect("table tr.app");
// ...

稍微熟悉 XPath 语法后,也可以很方便提取信息,如下(单个节点中的信息):

using HtmlAgilityPack;
// ...
string subID = tds[1].SelectSingleNode(".//a[@href]").Attributes["href"].Value.Split('/')[2];
string name = tds[1].SelectSingleNode(".//b").InnerText;
string URL = tds[0].SelectSingleNode(".//a[@href]").Attributes["href"].Value.Split('?')[0];
// ...

Continue reading “从 Python 向 Dotnet Core 的爬虫迁移记录”