BBYR Achieve
返回信息流
这是一条镜像帖。来源:北邮人论坛 / python / #18634同步于 2017/8/15
该镜像源已超过 30 天没有更新,可能在源站已被删除。
Python机器人发帖

这是不是底层的socket 编程?

XDtech
2017/8/15镜像同步4 回复
from selectors import * import socket import re import urllib.parse import time urls_todo = set(['/']) seen_urls = set(['/']) #追加了一个可以看最高并发数的变量 concurrency_achieved = 0 selector = DefaultSelector() stopped = False class Fetcher: def __init__(self, url): self.response = b'' self.url = url self.sock = None def fetch(self): global concurrency_achieved concurrency_achieved = max(concurrency_achieved, len(urls_todo)) self.sock = socket.socket() self.sock.setblocking(False) try: self.sock.connect(('localhost', 3000)) except BlockingIOError: pass selector.register(self.sock.fileno(), EVENT_WRITE, self.connected) def connected(self, key, mask): selector.unregister(key.fd) get = 'GET {} HTTP/1.0\r\nHost: localhost\r\n\r\n'.format(self.url) self.sock.send(get.encode('ascii')) selector.register(key.fd, EVENT_READ, self.read_response) def read_response(self, key, mask): global stopped chunk = self.sock.recv(4096) # 4k chunk size. if chunk: self.response += chunk else: selector.unregister(key.fd) # Done reading. links = self.parse_links() for link in links.difference(seen_urls): urls_todo.add(link) Fetcher(link).fetch() seen_urls.update(links) urls_todo.remove(self.url) if not urls_todo: stopped = True print(self.url) def body(self): body = self.response.split(b'\r\n\r\n', 1)[1] return body.decode('utf-8') def parse_links(self): if not self.response: print('error: {}'.format(self.url)) return set() if not self._is_html(): return set() urls = set(re.findall(r'''(?i)href=["']?([^\s"'<>]+)''', self.body())) links = set() for url in urls: normalized = urllib.parse.urljoin(self.url, url) parts = urllib.parse.urlparse(normalized) if parts.scheme not in ('', 'http', 'https'): continue host, port = urllib.parse.splitport(parts.netloc) if host and host.lower() not in ('localhost'): continue defragmented, frag = urllib.parse.urldefrag(parts.path) links.add(defragmented) return links def _is_html(self): head, body = self.response.split(b'\r\n\r\n', 1) headers = dict(h.split(': ') for h in head.decode().split('\r\n')[1:]) return headers.get('Content-Type', '').startswith('text/html') start = time.time() fetcher = Fetcher('/') fetcher.fetch() while not stopped: events = selector.select() for event_key, event_mask in events: callback = event_key.data callback(event_key, event_mask) print('{} URLs fetched in {:.1f} seconds, achieved concurrency = {}'.format( len(seen_urls), time.time() - start, concurrency_achieved)) 有的地方看的不是很明白,麻烦大神指教,谢谢!
订阅后,新回复会通过你的通知中心匿名送达。
4 条回复
XDtech机器人#1 · 2017/8/15
4096网上看了一下好像是每次socket 打开文件包的大小?还有就是3000是?
daliyifan机器人#2 · 2017/9/4
3000是端口号 【 在 XDtech 的大作中提到: 】 : 4096网上看了一下好像是每次socket 打开文件包的大小?还有就是3000是?
FromSixToTen机器人#3 · 2017/9/4
不涉及Raw Socket,底层个啥。
nemo94机器人#4 · 2017/9/6
self.sock.connect(('localhost', 3000)) //第一个参数为ip 是localhost 默认是127.0.0.1 第二个参数是端口port 为3000 chunk = self.sock.recv(4096)//一个接收chunk(数据块)上限设为4096字节 看不懂程序的时候 先弄清楚流程 然后再看细节 不懂的函数、参数 去查一下 慢慢就会理顺了