parser = argparse.ArgumentParser(description='Scrape Function') parser.add_argument('url', type=str, help='an integer for the accumulator') parser.add_argument('timeout', type=int, help='sum the integers (default: find the max)')
if __name__ == '__main__': args = parser.parse_args() scrape(args.url, args.timeout)
这样我们才能顺利地使用命令行来调用这个脚本:
1
python3 main.py https://www.baidu.com 10
是不是感觉非常麻烦?argparse 写起来又臭又长,想想就费劲。
Fire
但接下来我们要介绍一个库,用它我们只需要两行代码就可以做到如上操作。
这个库的名字叫做Fire,它可以快速为某个 Python 方法或者类添加命令行的参数支持。
先看看安装方法,使用 pip3 安装即可:
1
pip3 install fire
这样我们就安装好了。
使用
下面我们来看几个例子。
方法支持
第一个代码示例如下:
1 2 3 4 5 6 7
import fire
defhello(name="World"): return"Hello %s!" % name
if __name__ == '__main__': fire.Fire(hello)
这里我们定义了一个 hello 方法,然后接收一个 name 参数,默认值是 World,接着输出了 Hello 加 name 这个字符串。
然后接着我们导入了 fire 这个库,调用它的 Fire 方法并传入 hello 这个方法声明,会发生什么事情呢?
我们把这段代码保存为 demo1.py,接着用 Python3 来运行一下:
1
python3 demo1.py
运行结果如下:
1
Hello World!
看起来并没有什么不同。
但我们这时候如果运行如下命令,就可以看到一些神奇的事情了:
1
python3 demo1.py --help
运行结果如下:
1 2 3 4 5 6 7 8 9
NAME demo1.py
SYNOPSIS demo1.py <flags>
FLAGS --name=NAME Default: 'World'
可以看到,这里它将 name 这个参数转化成了命令行的一个可选参数,我们可以通过 —-name 来替换 name 参数。
我们来试下:
1
python3 demo1.py --name 123
这里我们传入了一个 name 参数是 123,这时候我们就发现运行结果就变成了如下内容:
1
Hello 123!
是不是非常方便?我们没有借助 argparse 就轻松完成了命令行参数的支持和替换。
那如果我们将 name 这个参数的默认值取消呢?代码改写如下:
1 2 3 4 5 6 7
import fire
defhello(name): return"Hello %s!" % name
if __name__ == '__main__': fire.Fire(hello)
这时候重新运行:
1
python3 demo1.py --help
就可以看到结果变成了如下内容:
1 2 3 4 5 6 7 8 9 10 11
NAME demo1.py
SYNOPSIS demo1.py NAME
POSITIONAL ARGUMENTS NAME
NOTES You can also use flags syntax for POSITIONAL ARGUMENTS
这时候我们发现 name 这个参数就变成了必传参数,我们必须在命令行里指定这个参数内容,调用就会变成如下命令:
1
python3 demo1.py 123
运行结果还是一样的。
类支持
当然 fire 这个库不仅仅支持给方法添加命令行的支持,还支持给一个类添加命令行的支持。
下面我们再看一个例子:
1 2 3 4 5 6 7 8
import fire
classCalculator(object): defdouble(self, number): return2 * number
OPTIONS: -p, --port Port to listen (default: 7681, use `0` for random port) -i, --interface Network interface to bind (eg: eth0), or UNIX domain socket path (eg: /var/run/ttyd.sock) -c, --credential Credential for Basic Authentication (format: username:password) -u, --uid User id to run with -g, --gid Group id to run with -s, --signal Signal to send to the command when exit it (default: 1, SIGHUP) -a, --url-arg Allow client to send command line arguments in URL (eg: http://localhost:7681?arg=foo&arg=bar) -R, --readonlyDo not allow clients to write to the TTY -t, --client-option Send option to client (format: key=value), repeat to add more options -T, --terminal-type Terminal type to report, default: xterm-256color -O, --check-originDo not allow websocket connection from different origin -m, --max-clients Maximum clients to support (default: 0, no limit) -o, --once Accept only one client and exit on disconnection -B, --browser Open terminal with the default system browser -I, --index Custom index.html path -b, --base-path Expected base path for requests coming from a reverse proxy (eg: /mounted/here) -P, --ping-interval Websocket ping interval(sec) (default: 300) -6, --ipv6 Enable IPv6 support -S, --ssl Enable SSL -C, --ssl-cert SSL certificate file path -K, --ssl-key SSL key file path -A, --ssl-ca SSL CA file path for client certificate verification -d, --debug Set log level (default: 7) -v, --version Print the version and exit -h, --help Print this text and exit
Visit https://github.com/tsl0922/ttyd to get more information and report bugs.
defrun(self): global l ret = subprocess.Popen( self.command, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) for i in iter(ret.stdout.readline, b""): res = i.decode().strip() print(res) l.append(res)
classServerHandler(SimpleHTTPServer.SimpleHTTPRequestHandler): defdo_GET(self): global l if self.path == uri: self.send_response(200) self.send_header('Content-Type', 'text/plain') self.end_headers() self.wfile.write(l)
if __name__ == '__main__': # New Thread: Get Command Result t1 = thread('1', sys.argv[1]) t1.start() # Webserver port = int(sys.argv[2]) print("URL: http://HOST:{0}{1}".format(port, uri)) Handler = ServerHandler httpd = BaseHTTPServer.HTTPServer(('0.0.0.0', port), Handler) httpd.serve_forever()
from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.common.exceptions import WebDriverException import time from loguru import logger
COUNT = 1000
for i in range(1, COUNT + 1): try: browser = webdriver.Chrome() wait = WebDriverWait(browser, 10) browser.get('https://captcha1.scrape.center/') button = wait.until(EC.element_to_be_clickable( (By.CSS_SELECTOR, '.el-button'))) button.click() captcha = wait.until( EC.presence_of_element_located((By.CSS_SELECTOR, '.geetest_slicebg.geetest_absolute'))) time.sleep(5) captcha.screenshot(f'data/captcha/images/captcha_{i}.png') except WebDriverException as e: logger.error(f'webdriver error occurred {e.msg}') finally: browser.close()
with sync_playwright() as p: for browser_type in [p.chromium, p.firefox, p.webkit]: browser = browser_type.launch(headless=False) page = browser.new_page() page.goto('https://www.baidu.com') page.screenshot(path=f'screenshot-{browser_type.name}.png') print(page.title()) browser.close()
Options: -o, --output <file name> saves the generated script to a file --target <language> language to use, one of javascript, python, python-async, csharp (default: "python") -b, --browser <browserType> browser to use, one of cr, chromium, ff, firefox, wk, webkit (default: "chromium") --channel <channel> Chromium distribution channel, "chrome", "chrome-beta", "msedge-dev", etc --color-scheme <scheme> emulate preferred color scheme, "light" or "dark" --device <deviceName> emulate device, for example "iPhone 11" --geolocation <coordinates> specify geolocation coordinates, for example "37.819722,-122.478611" --load-storage <filename> load context storage state from the file, previously saved with --save-storage --lang <language> specify language / locale, for example "en-GB" --proxy-server <proxy> specify proxy server, for example "http://myproxy:3128" or "socks5://myproxy:8080" --save-storage <filename> save context storage state at the end, for later use with --load-storage --timezone <time zone> time zone to emulate, for example "Europe/Rome" --timeout <timeout> timeout for Playwright actions in milliseconds (default: "10000") --user-agent <ua string> specify user agent string --viewport-size <size> specify browser viewport size in pixels, for example "1280, 720" -h, --help display help for command
with sync_playwright() as p: browser = p.chromium.launch(headless=False) page = browser.new_page() page.goto('https://spa6.scrape.center/') page.wait_for_load_state('networkidle') elements = page.query_selector_all('a.name') for element in elements: print(element.get_attribute('href')) print(element.text_content()) browser.close()
/detail/ZWYzNCN0ZXVxMGJ0dWEjKC01N3cxcTVvNS0takA5OHh5Z2ltbHlmeHMqLSFpLTAtbWIx 霸王别姬 - Farewell My Concubine /detail/ZWYzNCN0ZXVxMGJ0dWEjKC01N3cxcTVvNS0takA5OHh5Z2ltbHlmeHMqLSFpLTAtbWIy 这个杀手不太冷 - Léon /detail/ZWYzNCN0ZXVxMGJ0dWEjKC01N3cxcTVvNS0takA5OHh5Z2ltbHlmeHMqLSFpLTAtbWIz 肖申克的救赎 - The Shawshank Redemption /detail/ZWYzNCN0ZXVxMGJ0dWEjKC01N3cxcTVvNS0takA5OHh5Z2ltbHlmeHMqLSFpLTAtbWI0 泰坦尼克号 - Titanic /detail/ZWYzNCN0ZXVxMGJ0dWEjKC01N3cxcTVvNS0takA5OHh5Z2ltbHlmeHMqLSFpLTAtbWI1 罗马假日 - Roman Holiday /detail/ZWYzNCN0ZXVxMGJ0dWEjKC01N3cxcTVvNS0takA5OHh5Z2ltbHlmeHMqLSFpLTAtbWI2 唐伯虎点秋香 - Flirting Scholar /detail/ZWYzNCN0ZXVxMGJ0dWEjKC01N3cxcTVvNS0takA5OHh5Z2ltbHlmeHMqLSFpLTAtbWI3 乱世佳人 - Gone with the Wind /detail/ZWYzNCN0ZXVxMGJ0dWEjKC01N3cxcTVvNS0takA5OHh5Z2ltbHlmeHMqLSFpLTAtbWI4 喜剧之王 - The King of Comedy /detail/ZWYzNCN0ZXVxMGJ0dWEjKC01N3cxcTVvNS0takA5OHh5Z2ltbHlmeHMqLSFpLTAtbWI5 楚门的世界 - The Truman Show /detail/ZWYzNCN0ZXVxMGJ0dWEjKC01N3cxcTVvNS0takA5OHh5Z2ltbHlmeHMqLSFpLTAtbWIxMA== 狮子王 - The Lion King
I am happy to see that Python is so widely used in the Chinese IT community. I hope this book will help more people understand Python and web crawling/scraping. *
—Guido van Rossum, creator of Python, Distinguished Engineer, Microsoft
嗯,总之,经过我的一些尝试之后,就感觉 —— 为自己制定短期的目标和规划真的很有帮助,这个短期的目标和规划时间段可能在一个月或者几周,先想这个月或者几周应该去做些什么,然后细化到每天应该去做些什么,这个一定要列详细,不要空洞,然后最好还能标记好优先级。就比如说,我规划一个月可能要学一门课程,那么我就分配一下,我哪一天需要具体学从第几节到第几节的内容,记录到我的 Todo List 里面。我是用的「滴答清单」这款软件,在里面我就给我每天需要做的事情做好分配,这样每天我就知道自己需要做什么了。
接下来,可以选用任意一台带有公网 IP 的主机来配置负载均衡。首先,在这台主机上装好 Nginx,然后修改 Nginx 的配置文件 nginx.conf,添加如下内容:
1 2 3 4 5 6 7 8 9 10 11 12 13
http { upstream splash { least_conn; server 41.159.27.223:8050; server 41.159.27.221:8050; server 41.159.27.9:8050; server 41.159.117.119:8050; } server { listen 8050; location / {proxy_pass http://splash;} } }
upstream splash { server 41.159.27.223:8050 weight=4; server 41.159.27.221:8050 weight=2; server 41.159.27.9:8050 weight=2; server 41.159.117.119:8050 weight=1; }
import requests from urllib.parse import quote import re
lua = ''' function main(splash, args) local treat = require("treat") local response = splash:http_get("http://httpbin.org/get") return treat.as_string(response.body) end '''
IDA Pro 的英文全称是 Interactive Disassembler Professional,即交互式反汇编器专业版,大家也称 之为 IDA。它由一家总部位于比利时的 Hex-Rayd 公司开发,功能十分强大,是目前流行的反汇编软 件之一,也是安全分析人士必备的一款软件。
IDA Pro 最重要的功能便是可以将二进制文件中的机器代码(如 010101)转化成汇编代码,甚至 可以进一步根据汇编代码的执行逻辑还原出高级语言(如 C/C++)编写的代码,从而大大提高代码的 可读性。IDA Pro 不仅仅局限于分析 Android 中的 so 文件,它可以处理和分析几乎所有的二进制文件, Windows、DOS、Unix、Linux、Mac、Java、.NET 等平台的二进制文件都不在话下。另外,IDA Pro 提 供了图形界面和强大的调试功能,利用它我们可以直观地实时调试和分析二进制文件。除了这些,IDA Pro 还提供开放式的插件架构,我们可以编写自定义的插件轻松扩展其功能。
总之,IDA Pro 是一款极其强大的反汇编软件,已经成为业界安全分析必不可少的一个工具,更多介绍可以查看 IDA Pro 的官网。