赞
踩
使用urllib和requests库已经可以爬取绝大部分网站的数据,但对于某些网站任然无能为力,因为这些网站强制使用HTTP/2.0协议访问,这时使用urllib和requests是无法爬取数据的,因为这两个库只支持HTTP/1.1,这个时候就需要用到httpx库了
# 这样安装不支持HTTP/2.0
pip install httpx
# 安装httpx并支持HTTP/2.0
pip install 'httpx[http2]'
# 导入模块 import httpx # 发送get请求 r = httpx.get('https://www.httpbin.org/get/') # 输出响应状态码 print(r.status_code) # 输出请求头 print(r.headers) # 输出响应体 print(r.text) # 说明:httpx默认不会开启对HTTP/2.0的支持,默认使用HTTP/1.1,需要手动声明一次才能使用 import httpx client = httpx.Client(http2=True) r = client.get('https://scrape.center/') print(r.text) # httpx库与requests库的很多方式类似
1、使用
# 官方推荐使用with as 语句
# 案例1
import httpx
with httpx.Client() as client:
r = client.get('https://www.httpbin.org/get')
print(r)
# 案例2:与案例1等价
import httpx
client = httpx.Client()
try:
r = client.get('https://www.htpbin.org/get')
finally:
client.close()
2、指定参数
import httpx
url = "http://www.httpbin.org/headers"
headers = {"User-Agent":"my-app/1.0.0.1"}
with httpx.Client(headers=headers) as client:
r = client.get(url)
print(r.json()['headers']['User-Agent'])
print(r.http_version)
3、支持异步请求
httpx支持异步客户端请求(AsyncClient),支持Python的async请求模式
import httpx
import asyncio
async def fetch(url):
async with httpx.AsyncClientt(http2=True) as client:
r = await client.get(url)
print(r.text)
if __name__ == "__main__":
asyncio.get_event_loop().run_until_complete(fetch('https://www.httpbin.org/get'))
1、安装Python环境
2、了解Python多进程的基本原理
3、了解Python HTTP请求库requests的基本用法
4、了解正则表达式的用法和Python中正则表达式库re的基本用法
爬取基本静态网站:电影网站
目标网址:https://movie.douban.com/top250
需完成目标:
1)利用requests爬取这个站点每一页的电影列表,顺着列表再爬取每个电影的详情页
2)用正则表达式提取每部电影的名称、封面、类别、上映时间、评分、剧情简介等内容
3)把爬取的内容保存为JSON文本文件
4)使用多进程实现爬取加速
1、分析列表页
观察列表页结构和翻页规则
分析网页结构
确认爬取目标
2、实现列表页爬取
遍历所有页码,构造10页的索引页URL
从每个索引页分析提取出每个电影的详情页URL
requests请求
# 用来请求网页 import requests # 用来输出信息 import logging # 用来实现正则表达式解析 import re # 用来做URL拼接 from urllib.parse import urljoin # 定义日志输出级别和输出格式 logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s: %(message)s") BASE_URL = 'https://movie.douban.com/top250' # 页码总数量 TOTAL_PAGE = 10 # 定义页面爬取方法 def scrape_page(url): logging.info('scraping %s...', url) try: r = requests.get(url) # 判断状态码是否为200,如果是,直接返回页面的HTML代码;如果不是,则输出错误日志信息 if r.status_code == 200: return r.text logging.error('get invalid status code %s while scraping %s', r.status_code, url) except requests.RequestException: # 如果出现爬取异常,输出对应的错误日志信息 logging.error('error occurred while scraping %s', url, exc_info=True) # 定义列表爬取方法:这个方法会接收一个page参数,即列表页的页码,在方法里面实现列表页的URL拼接,然后调用scrape_page方法爬取即可 def scrape_index(page): index_url = f'{BASE_URL}/page/{page}' return scrape_page(index_url) # 解析列表页方法 def parse_index(html): pattern = re.compile('<a.*?href="(.*?)".*?class="name">') items = re.findall(pattern, html) if not items: return [] for item in items: # 拼接完整URL detail_url = urljoin(BASE_URL, item) logging.info('get detail url %s', detail_url) yield detail_url # 主函数 def main(): for page in range(1, TOTAL_PAGE+1): index_html = scrape_index(page) detail_urls = parse_index(index_html) logging.info('detail urls %s', list(detail_urls)) # 函数开始位置 if __name__ == "__main__": main()
httx请求
# 用来请求网页 import httpx # 用来输出信息 import logging # 用来实现正则表达式解析 import re # 用来做URL拼接 from urllib.parse import urljoin # 定义日志输出级别和输出格式 logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s: %(message)s") BASE_URL = 'https://movie.douban.com/top250' # 页码总数量 TOTAL_PAGE = 10 # 定义页面爬取方法 def scrape_page(url): logging.info('scraping %s...', url) try: r = httpx.get(url) # 判断状态码是否为200,如果是,直接返回页面的HTML代码;如果不是,则输出错误日志信息 if r.status_code == 200: return r.text logging.error('get invalid status code %s while scraping %s', r.status_code, url) except httpx.RequestError: # 如果出现爬取异常,输出对应的错误日志信息 logging.error('error occurred while scraping %s', url, exc_info=True) # 定义列表爬取方法:这个方法会接收一个page参数,即列表页的页码,在方法里面实现列表页的URL拼接,然后调用scrape_page方法爬取即可 def scrape_index(page): index_url = f'{BASE_URL}/page/{page}' return scrape_page(index_url) # 解析列表页方法 def parse_index(html): pattern = re.compile('<a.*?href="(.*?)".*?class="name">') items = re.findall(pattern, html) if not items: return [] for item in items: # 拼接完整URL detail_url = urljoin(BASE_URL, item) logging.info('get detail url %s', detail_url) yield detail_url # 主函数 def main(): for page in range(1, TOTAL_PAGE+1): index_html = scrape_index(page) detail_urls = parse_index(index_html) logging.info('detail urls %s', list(detail_urls)) # 函数开始位置 if __name__ == "__main__": main()
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。