摘要:目標站點分析本次要采集的目標網站為,目標站點描述為全球名站。由于上述代碼太少了,完全不夠今日代碼量,我們順手將其修改為多線程形式。
本篇博客是《爬蟲 120 例》的第 30 例,新學習一個爬蟲框架 requests-html
,該框架作者就是 requests
的作者,所以盲猜就很好用啦。
requests-html
模塊安裝使用 pip install requests-html
即可,官方手冊查詢地址:https://requests-html.kennethreitz.org/,官方并沒有直接的中文翻譯,在檢索過程中,確實發現了一版中文手冊,在文末提供。
先看一下官方對該庫的基本描述:
Only Python 3.6 is supported. 僅支持 Python 3.6 ,實測發現 3.6 以上版本依舊可以。
對于該庫的簡單使用,代碼如下所示:
from requests_html import HTMLSessionsession = HTMLSession()r = session.get("https://python.org/")print(r)
首先從 requests_html
庫導入 HTMLSession
類,然后將其實例化之后,調用其 get
方法,發送請求,得到的 r
輸出為
,后續即可使用內置的解析庫對數據進行解析。
由于該庫是解析 html
對象,所以可以查看對應的 html
對象包含哪些方法與與屬性。
通過 dir
函數查閱。
print(dir(r.html))# 輸出如下內容:["__aiter__", "__anext__", "__class__", "__delattr__", "__dict__", "__dir__", "__doc__", "__eq__", "__format__", "__ge__","__getattribute__", "__gt__", "__hash__", "__init__", "__init_subclass__", "__iter__", "__le__", "__lt__", "__module__", "__ne__","__new__", "__next__", "__reduce__", "__reduce_ex__", "__repr__", "__setattr__", "__sizeof__", "__str__", "__subclasshook__","__weakref__", "_async_render", "_encoding", "_html", "_lxml", "_make_absolute", "_pq", "absolute_links", "add_next_symbol","arender", "base_url", "default_encoding", "element", "encoding", "find", "full_text", "html", "links", "lxml", "next","next_symbol", "page", "pq", "raw_html", "render", "search", "search_all", "session", "skip_anchors", "text", "url", "xpath"]
該函數只能輸入大概內容,細節還是需要通過 help 函數查詢,例如:
html 對象的方法包括
find
:提供一個 css 選擇器,返回一個元素列表;xpath
:提供一個 xpath 表達式,返回一個元素列表;search
: 根據傳入的模板參數,查找 Element 對象;search_all
:同上,返回的全部數據;html 對象的屬性包括
links
:返回頁面所有鏈接;absolute_links
:返回頁面所有鏈接的絕對地址;base_url
:頁面的基準 URL;html
,raw_html
,text
:以 HTML 格式輸入頁面,輸出未解析過的網頁,提取頁面所有文本;有了上述內容鋪墊之后,在進行 Python 爬蟲的編寫就會變的容易許多,requests-html
庫將通過 3~4 個案例進行學習掌握,接下來進入第一個案例。
本次要采集的目標網站為:http://www.world68.com/top.asp?t=5star&page=1,目標站點描述為【全球名站】。
在獲取數據源發送請求前,忽然想起可以動態修改 user-agent
,查閱該庫源碼發現,它只是使用了 fake_useragent
庫來進行操作,并無太神奇的地方,所以可用可不用該內容。
DEFAULT_USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/603.3.8 (KHTML, like Gecko) Version/10.1.2 Safari/603.3.8"def user_agent(style=None) -> _UserAgent: """Returns an apparently legit user-agent, if not requested one of a specific style. Defaults to a Chrome-style User-Agent. """ global useragent if (not useragent) and style: useragent = UserAgent() return useragent[style] if style else DEFAULT_USER_AGENT
其余內容相對比較簡單,頁碼規則如下:
http://www.world68.com/top.asp?t=5star&page=1http://www.world68.com/top.asp?t=5star&page=2
累計頁數直接在底部進行了展示,可以設計為用戶手動輸入,即 input
函數實現。
目標數據存儲網站名與網站地址即可,基于此,開始編碼。
首先通過單線程實現 requests-html
的基本邏輯,注意到下述代碼非常輕量,
from requests_html import HTMLSessionsession = HTMLSession()page_size = int(input("請輸入總頁碼:"))for page in range(1, page_size + 1): world = session.get(f"http://www.world68.com/top.asp?t=5star&page={page}") world.encoding = "gb2312" # world.html.encoding = "gb2312" # print(world.text) print("正在采集數據", world.url) title_a = world.html.find("dl>dt>a") for item in title_a: name = item.text url = item.attrs["href"] with open("webs.txt", "a+", encoding="utf-8") as f: f.write(f"{name},{url}/n")
上述代碼重點部分說明如下:
world.encoding
,設置了網頁解析編碼;world.html.find("dl>dt>a")
通過 css 選擇器,查找所有的網頁標題元素;item.text
提取網頁標題內容;item.attrs["href"]
獲取元素屬性,即網站域名。運行效果如下所示,獲取到的 3519
個站點,就不在提供了,簡單運行 1 分鐘代碼,即可得到。
由于上述代碼太少了,完全不夠今日代碼量,我們順手將其修改為多線程形式。
import requests_htmlimport threadingimport timeimport fcntlclass MyThread(threading.Thread): def __init__(self): threading.Thread.__init__(self) def run(self): global page, lock, page_size while True: lock.acquire(True) if page >= page_size: lock.release() break else: page += 1 lock.release() requests_html.DEFAULT_ENCODING = "gb18030" session = requests_html.HTMLSession() print("正在采集第{}頁".format(page), "*" * 50) try: page_url = f"http://www.world68.com/top.asp?t=5star&page={page}" world = session.get(page_url, timeout=10) print("正在采集數據", world.url) # print(world.html) title_a = world.html.find("dl>dt>a") print(title_a) my_str = "" for item in title_a: name = item.text url = item.attrs["href"] my_str += f"{name.encode("utf-8").decode("utf-8")},{url}/n" with open("thread_webs.txt", "a+", encoding="utf-8") as f: fcntl.flock(f.fileno(), fcntl.LOCK_EX) # 文件加鎖 f.write(f"{my_str}") except Exception as e: print(e, page_url)if "__main__" == __name__: page_size = int(input("請輸入總頁碼:")) page = 0 thread_list = [] # 獲取開始時間 start = time.perf_counter() lock = threading.Lock() for i in range(1, 5): t = MyThread() thread_list.append(t) for t in thread_list: t.start() for t in thread_list: t.join() # 獲取時間間隔 elapsed = (time.perf_counter() - start) print("程序運行完畢,總耗時為:", elapsed)
在正式進行編碼之后,發現存在比較大的問題,編碼問題,出現如下錯誤:
encoding error : input conversion failed due to input error, bytes 0x81 0xE3 0xD3 0xAAencoding error : input conversion failed due to input error, bytes 0x81 0xE3 0xD3 0xAAencoding error : input conversion failed due to input error, bytes 0x81 0xE3 0xD3 0xAAI/O error : encoder error
該錯誤在執行單線程時并未發生,但是當執行多線程時,異常開始出現,本問題在互聯網上無解決方案,只能自行通過 requests-html
庫的源碼進行修改。
打開 requests_html.py
文件,將 417 行左右的代碼進行如下修改:
def __init__(self, *, session: Union["HTMLSession", "AsyncHTMLSession"] = None, url: str = DEFAULT_URL, html: _HTML, default_encoding: str = DEFAULT_ENCODING, async_: bool = False) -> None: # 修改本部分代碼 # Convert incoming unicode HTML into bytes. # if isinstance(html, str): html = html.decode(DEFAULT_ENCODING,"replace") super(HTML, self).__init__( # Convert unicode HTML to bytes. element=PyQuery(html)("html") or PyQuery(f"{html}")("html"), html=html, url=url, default_encoding=default_encoding )
代碼 if isinstance(html, str):
用于判斷 html
是否為 str
,但是在實測過程中發現 html
是
類型,所以數據沒有進行轉碼工作,故取消相關判斷。
除此以外,通過輸出 world.html.encoding
發現網頁的編碼不是 GB2312
,而是 gb18030
,所以通過下述代碼進行了默認編碼的設置。
requests_html.DEFAULT_ENCODING = "gb18030"
按照如上內容進行修改之后,代碼可以正常運行,數據能正確的采集到。
本案例還新增了代碼運行時長的計算,具體如下:
# 獲取開始時間start = time.perf_counter()# 執行代碼的部分# 獲取時間間隔elapsed = (time.perf_counter() - start)print("程序運行完畢,總耗時為:", elapsed)
完整的代碼運行效果如下所示:
代碼倉庫地址:https://codechina.csdn.net/hihell/python120,去給個關注或者 Star 吧。
數據沒有采集完畢,想要的可以在評論區留言交流
今天是持續寫作的第 212 / 365 天。
可以關注我,點贊我、評論我、收藏我啦。
更多精彩
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/119409.html
摘要:爬蟲實戰一使用和,我們使用了做網絡請求,拿到網頁數據再用解析,就在前不久,作者出了一個新庫,,它可以用于解析文檔的。是基于現有的框架等庫進行了二次封裝,更加方便開發者調用。參考今天用了一下庫爬蟲公眾號我的公眾號吳小龍同學,歡迎交流 Python 爬蟲實戰(一):使用 requests 和 BeautifulSoup,我們使用了 requests 做網絡請求,拿到網頁數據再用 Beaut...
摘要:提升倍雖是我胡謅的數據,開發效率的提升卻是杠杠滴。而卻不同,它提供了官方中文文檔,其中包括了很清晰的快速上手和詳盡的高級用法和接口指南。其他更多詳細內容不多說了,中文官網地址,順著看一遍,寫一遍,你就掌握這個爬蟲神器了。 他叫 Kenneth Reitz。現就職于知名云服務提供商 DigitalOcean,曾是云計算平臺 Heroku 的 Python 架構師,目前 Github 上 ...
閱讀 1412·2021-11-24 09:39
閱讀 3694·2021-11-24 09:39
閱讀 1869·2021-11-16 11:54
閱讀 1469·2021-09-30 09:47
閱讀 1718·2021-09-26 10:16
閱讀 2352·2021-09-22 15:33
閱讀 1463·2021-09-14 18:01
閱讀 2448·2021-09-07 09:59