Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/url/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用Floki和HttPotion的Elixir脚本无法解析url_Url_Enums_Web Scraping_Html Parsing_Elixir - Fatal编程技术网

使用Floki和HttPotion的Elixir脚本无法解析url

使用Floki和HttPotion的Elixir脚本无法解析url,url,enums,web-scraping,html-parsing,elixir,Url,Enums,Web Scraping,Html Parsing,Elixir,我正试图用维基百科的文章和文本来编写一个脚本。我的失败代码如下所示: defmodule Scraper do def start do base = "https://en.wikipedia.org" response = HTTPotion.get base <> "/wiki/Main_Page" html = response.body main_bg = Floki.find(html, ".MainPageBG") main

我正试图用维基百科的文章和文本来编写一个脚本。我的失败代码如下所示:

defmodule Scraper do

  def start do
    base = "https://en.wikipedia.org"
    response = HTTPotion.get base <> "/wiki/Main_Page"
    html = response.body
    main_bg = Floki.find(html, ".MainPageBG")
    main_bg
      |> Floki.find("table tr li a")
      |> Floki.attribute("href")
      |> Enum.map(fn(addr) -> HTTPotion.get(base <> addr) end)
  end
end
当我将结果通过管道传输到
Floki.attribute(“href”)
时,我会得到一个很好的url路径名列表,如:

["/wiki/Japanese_aircraft_carrier_Hiry%C5%ABwow",
 "/wiki/Boys_Don%27t_Cry_(film)wow", "/wiki/Elias_Abraham_Rosenbergwow",
 "/wiki/Japanese_aircraft_carrier_Hiry%C5%ABwow",
 "/wiki/Boys_Don%27t_Cry_(film)wow", "/wiki/Elias_Abraham_Rosenbergwow",
 "/wiki/Wikipedia:Today%27s_featured_article/November_2015wow",
 "https://lists.wikimedia.org/mailman/listinfo/daily-article-lwow",
 "/wiki/Wikipedia:Featured_articleswow", "/wiki/Schloss_Krobnitzwow",
 "/wiki/Prussiawow", "/wiki/Albrecht_von_Roonwow", "/wiki/Harry_Winerwow",
 "/wiki/Rob_Thomas_(writer)wow", "/wiki/Of_Vice_and_Menwow",
 "/wiki/Veronica_Marswow", "/wiki/Meithalunwow", "/wiki/Palestinian_peoplewow",
 "/wiki/Marj_Sanurwow", "/wiki/Soma_Norodomwow",...]
但是,当行
|>Enum.map(fn(addr)->HTTPotion.get(base addr)end)
运行时,我得到以下错误:

** (HTTPotion.HTTPError) {:url_parsing_failed, {:error, :invalid_uri}}
    (httpotion) lib/httpotion.ex:209: HTTPotion.handle_response/1
       (elixir) lib/enum.ex:977: anonymous fn/3 in Enum.map/2
       (elixir) lib/enum.ex:1261: Enum."-reduce/3-lists^foldl/2-0-"/3
       (elixir) lib/enum.ex:977: Enum.map/2
我看到
:url\u解析\u失败了
,但我不明白为什么。当我使用列表中的各个url路径尝试
Enum.map(fn(addr)->HTTPotion.get(base addr)
时,它们都可以工作

  • 我的语法错了吗
  • 我是否遗漏了一些关于管道或枚举如何工作的信息
  • 我走对了吗
根据曼努卡尔的回答,以下是有效的方法:

defmodule Scraper do
  def transform_url(url_or_path = "/" <> _, base), do: base <> url_or_path
  def transform_url(url, _base), do: url

  def start do
    base = "https://en.wikipedia.org"
    response = HTTPotion.get base <> "/wiki/Main_Page"
    html = response.body
    main_bg = Floki.find(html, ".MainPageBG")
    main_bg
      |> Floki.find("table tr li a")
      |> Floki.attribute("href")
      |> Enum.map(fn(url) -> OldRazor.transform_url(url, base) end)
      |> Enum.map(fn(url) -> HTTPotion.get(url) end)
  end
end
defmodule-Scraper-do
def transform_url(url_或_path=“/”,基本),do:base url_或_path
def transform_url(url,_base),do:url
def启动do
基数=”https://en.wikipedia.org"
response=HTTPotion.get base”/wiki/Main\u页面
html=response.body
main_bg=Floki.find(html,“.MainPageBG”)
主接线盒
|>Floki.find(“表tr li a”)
|>属性(“href”)
|>Enum.map(fn(url)->OldRazor.transform\u url(url,base)end)
|>映射(fn(url)->HTTPotion.get(url)end)
结束
结束

如果您再次仔细查看url列表,您会注意到其中有一个绝对url:“”。这不适用于
HTTPotion.get(base addr)
,因为它最终会请求类似“”的url

解决此问题的一种方法是编写另一个函数
transform\u url
,该函数检查值是否以
/
开头,然后才将基本url前置到该值:

  def transform_url(url_or_path = "/" <> _, base), do: base <> url_or_path
  def transform_url(url, _base), do: url

实际上,我运行了你的代码,但在
HTTPotion.get!
部分前面的匿名函数中加入了一个
IO.inspect(url)
。所以最后打印的url是一个坏的url。经过一些调整,效果很好!谢谢。我没有真正理解
(url\u或\u path=“/”,base)
的功能。太棒了!
url\u或\u path=“/”_
匹配以
/
开头的二进制文件,然后将整个二进制文件绑定到
url\u或_path
,如果匹配的话。因此,基本上整个方法的作用类似于:如果第一个参数以“/”开头,将该参数绑定到
url\u或\u path
,在
base
前加前缀并返回该参数。否则只需返回第一个参数。哦,太棒了。再次感谢。
  def transform_url(url_or_path = "/" <> _, base), do: base <> url_or_path
  def transform_url(url, _base), do: url
  ...
  |> Enum.map(fn(url) -> HTTPoison.get!(transform_url((url)) end)