php抓取网页json数据(5.正则提取我们去网页看一下真实的源码(图))

优采云 发布时间: 2021-10-23 20:08

  php抓取网页json数据(5.正则提取我们去网页看一下真实的源码(图))

  下面用代码实现,先抓取第一页的内容。我们实现了 get_one_page() 方法并将 url 参数传递给他。然后返回获取的页面结果,然后调用main()方法。初步代码如下:

  import requests

def get_one_page(url):

headers = {

'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36'

}

response = requests.get(url,headers=headers)

if response.status_code == 200:

return response.text

return None

def main():

url = 'http://maoyan.com/board/4'

html = get_one_page(url)

print(html)

main()

  运行后就可以成功获取主页的源码了。获取到之后,需要对页面进行解析,提取出我们想要的信息。

  5.常规提取

  让我们去网页看看真正的源代码。在开发者模式下查看Network monitor组件中的源码,如图

  

  注意这里不要直接进入Elements选项卡查看,因为这里的源码可能与通过JavaScript操作的原创请求不同,但是需要查看来自Network的原创请求才能获取源码。让我们分析其中一项。

  

  可以看出,一个电影信息对应的源代码是一个dd节点,我们使用正则表达式提取其中的一些信息。首先是排名信息。它的排名在类别为 board-index 的 i-node 中。这里使用非贪婪匹配来提取 i-node 中的信息。正则表达式写成:

  .*?board-index.*?>(.*?)

  接下来需要提取的是电影图片。可以看到,后面有一个节点,里面有两个img节点。检查后发现第二个img节点的data-src属性是图片链接。这里提取第二个img节点的data-src属性,把表达式改成这样:

  .*?board-index.*?>(.*?).*?data-src="(.*?)"

  后面需要提取电影名称,在后面的p节点中,类为name。因此,您也可以使用name作为标志位,然后进一步提取其中的a节点的文本内容。这时正则表达式改写如下:

  .*?board-index.*?>(.*?).*?data-src="(.*?)".*?name.*?a.*?>(.*?)</a>

  用同样的原理提取男主角、上映时间、收视率等,最终的正则表达式为:

  .*?board-index.*?>(.*?).*?data-src="(.*?)".*?name.*?a.*?>(.*?)</a>.*?star.*?>(.*?).*?releasetime.*?>(.*?)</p>.*?integer.*?>(.*?).*?fraction.*?>(.*?).*?

</p>

  这样的正则表达式可以匹配一部电影的结果,一共有七条信息。接下来,通过调用 findall() 方法提取所有内容。

  接下来我们定义一个方法parse_one_page()来解析页面,主要是通过正则表达式从结果中提取出我们想要的内容,代码如下:

  def parse_one_page(html):

pattern = re.compile(&#39;.*?board-index.*?>(.*?).*?data-src="(.*?)".*?name.*?a.*?>(.*?)</a>.*?star.*?>(.*?).*?releasetime.*?>(.*?)</p>.*?integer.*?>(.*?).*?fraction.*?>(.*?).*?&#39;,re.S)

items = re.findall(pattern,html)

print(items)

</p>

  输出如下,是一个列表形式。

  

  但是数据比较乱,所以我们先处理匹配结果,遍历提取结果生成字典,改成这样:

  def parse_one_page(html):

pattern = re.compile(&#39;.*?board-index.*?>(.*?).*?data-src="(.*?)".*?name.*?a.*?>(.*?)</a>.*?star.*?>(.*?).*?releasetime.*?>(.*?)</p>.*?integer.*?>(.*?).*?fraction.*?>(.*?).*?&#39;,re.S)

items = re.findall(pattern,html)

for item in items:

yield {

&#39;index&#39;: item[0],

&#39;image&#39;: item[1],

&#39;title&#39;: item[2].strip(),

&#39;actor&#39;: item[3].strip()[3:] if len(item[3]) > 3 else &#39;&#39;,

&#39;time&#39;: item[4].strip()[5:] if len(item[3]) > 3 else &#39;&#39;,

&#39;score&#39;: item[5].strip() + item[6].strip()

}

</p>

  这样就可以成功提取电影排名、图片、片名、演员、时间、收视率等内容,并分配到字典中,形成结构化数据。操作结果如下:

  

  6.写入文件

  随后,我们将提取的结果写入文件,这里直接写入文本文件。这里通过JSON库的dumps()方法实现字典的序列化,将ensure_ascii参数指定为False,保证输出结果是中文格式,而不是Unicode编码。代码显示如下:

  def write_to_file(content):

with open(&#39;result.txt&#39;, &#39;a&#39;, encoding=&#39;utf-8&#39;) as f:

print(type(json.dumps(content)))

f.write(json.dumps(content, ensure_ascii=False) + &#39;\n&#39;)

  将字典写入文本文件的过程可以通过调用write_to_file()方法来实现。这里的content参数是提取结果,是一个字典。

  7.集成代码

  最后实现main()方法调用前面的方法,将单页电影结果写入文件。代码如下:

  def main(offset):

url = &#39;http://maoyan.com/board/4&#39;

html = get_one_page(url)

for item in parse_one_page(html):

write_to_file(item)

  至此我们就完成了单个页面的提取。

  8.页面抓取

  因为我们要抓取TOP100电影,所以还需要遍历并将offset参数传递给这个链接,实现其他90部电影的抓取。这时,添加如下调用:

  if __name__ == &#39;__main__&#39;:

for i in range(10):

main(offset= i*10)

  还需要修改main方法,接收一个偏移值作为偏移量,然后进行URL构建。代码显示如下:

  def main(offset):

url = &#39;http://maoyan.com/board/4?offset=&#39; + str(offset)

html = get_one_page(url)

for item in parse_one_page(html):

print(item)

write_to_file(item)

  至此,集成后的代码如下:

  import json

import requests

from requests.exceptions import RequestException

import re

import time

import http

def get_one_page(url):

try:

headers = {

&#39;User-Agent&#39;:&#39;Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36&#39;

}

response = requests.get(url, headers=headers)

if response.status_code == 200:

return response.text

return None

except RequestException:

return None

def parse_one_page(html):

pattern = re.compile(&#39;.*?board-index.*?>(\d+).*?data-src="(.*?)".*?name">(.*?)</a>.*?star">(.*?).*?releasetime">(.*?)</p>&#39;

+ &#39;.*?integer">(.*?).*?fraction">(.*?).*?&#39;, re.S)

items = re.findall(pattern, str(html))

for item in items:

yield {

&#39;index&#39;: item[0],

&#39;image&#39;: item[1],

&#39;title&#39;: item[2],

&#39;actor&#39;: item[3].strip()[3:],

&#39;time&#39;: item[4].strip()[5:],

&#39;score&#39;: item[5] + item[6]

}

def write_to_file(content):

with open(&#39;result.txt&#39;, &#39;a&#39;, encoding=&#39;utf-8&#39;) as f:

f.write(json.dumps(content, ensure_ascii=False) + &#39;\n&#39;)

def main(offset):

url = &#39;http://maoyan.com/board/4?offset=&#39; + str(offset)

html = get_one_page(url)

for item in parse_one_page(html):

print(item)

write_to_file(item)

if __name__ == &#39;__main__&#39;:

for i in range(10):

main(offset= i*10)

time.sleep(1)

</p>

  因为猫眼是有抗爬虫的,如果速度太快,就会没有反应,所以加了一个延迟。可能有人在练习的时候注意到ip被封了。其实这里最好的解决办法就是设置代理。您可以找到一些免费的代理服务器。

  9.运行结果

  我们运行一下代码,输出如下

  

  我们再看一下文本文件,如图

  

  如您所见,所有电影信息也保存在一个文本文件中。

  10.本节代码

  本节的代码也已经提交到GitHub,代码地址:。

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线